Compare commits
13 Commits
v0.36.2
...
pixeebot/g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dc0a25b26 | ||
|
|
128cdc90c0 | ||
|
|
5a67b0cfe7 | ||
|
|
d1acda6440 | ||
|
|
5cf3798540 | ||
|
|
b27044016e | ||
|
|
4aec0bd679 | ||
|
|
ab7610f72c | ||
|
|
748392cd29 | ||
|
|
f0810f3952 | ||
|
|
298870ed7d | ||
|
|
6ec2c34c2b | ||
|
|
73e64e5898 |
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: 💬 Discord Server
|
- name: 💬 Discord Server
|
||||||
url: https://discord.gg/HYmhKj45pU
|
url: https://discord.gg/Cn8pWhQRxZ
|
||||||
about: You can join our Discord server for real time discussion and support
|
about: You can join our Discord server for real time discussion and support
|
||||||
|
|||||||
96
.github/workflows/multiOSReleases.yml
vendored
96
.github/workflows/multiOSReleases.yml
vendored
@@ -1,96 +0,0 @@
|
|||||||
name: Test Installers Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
release:
|
|
||||||
types: [created]
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
jobs:
|
|
||||||
build-installers:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows-latest
|
|
||||||
platform: win
|
|
||||||
ext: exe
|
|
||||||
#- os: macos-latest
|
|
||||||
# platform: mac
|
|
||||||
# ext: dmg
|
|
||||||
#- os: ubuntu-latest
|
|
||||||
# platform: linux
|
|
||||||
# ext: deb
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up JDK 21
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
java-version: "21"
|
|
||||||
distribution: "temurin"
|
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@v4
|
|
||||||
with:
|
|
||||||
gradle-version: 8.7
|
|
||||||
|
|
||||||
# Install Windows dependencies
|
|
||||||
- name: Install WiX Toolset
|
|
||||||
if: matrix.os == 'windows-latest'
|
|
||||||
run: |
|
|
||||||
curl -L -o wix.exe https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314.exe
|
|
||||||
.\wix.exe /install /quiet
|
|
||||||
|
|
||||||
# Install Linux dependencies
|
|
||||||
- name: Install Linux Dependencies
|
|
||||||
if: matrix.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y fakeroot rpm
|
|
||||||
|
|
||||||
# Get version number
|
|
||||||
- name: Get version number
|
|
||||||
id: versionNumber
|
|
||||||
run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Get version number mac
|
|
||||||
id: versionNumberMac
|
|
||||||
run: echo "versionNumberMac=$(./gradlew printMacVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
# Build installer
|
|
||||||
- name: Build Installer
|
|
||||||
run: ./gradlew build jpackage -x test --info
|
|
||||||
env:
|
|
||||||
DOCKER_ENABLE_SECURITY: false
|
|
||||||
STIRLING_PDF_DESKTOP_UI: true
|
|
||||||
|
|
||||||
# Rename and collect artifacts based on OS
|
|
||||||
- name: Prepare artifacts
|
|
||||||
id: prepare
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ "${{ matrix.os }}" = "windows-latest" ]; then
|
|
||||||
mv "build/jpackage/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.exe" "Stirling-PDF-${{ matrix.platform }}-installer.${{ matrix.ext }}"
|
|
||||||
elif [ "${{ matrix.os }}" = "macos-latest" ]; then
|
|
||||||
mv "build/jpackage/Stirling-PDF-${{ steps.versionNumberMac.outputs.versionNumberMac }}.dmg" "Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}-${{ matrix.platform }}.${{ matrix.ext }}"
|
|
||||||
else
|
|
||||||
mv "build/jpackage/stirling-pdf_${{ steps.versionNumber.outputs.versionNumber }}-1_amd64.deb" "Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}-${{ matrix.platform }}.${{ matrix.ext }}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Upload installer as artifact for testing
|
|
||||||
- name: Upload Installer Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: Stirling-PDF-${{ matrix.platform }}-installer.${{ matrix.ext }}
|
|
||||||
path: Stirling-PDF-${{ matrix.platform }}-installer.${{ matrix.ext }}
|
|
||||||
retention-days: 1
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload binaries to release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
files: ./Stirling-PDF-${{ matrix.platform }}-installer.${{ matrix.ext }}
|
|
||||||
51
.github/workflows/releaseArtifacts.yml
vendored
51
.github/workflows/releaseArtifacts.yml
vendored
@@ -35,28 +35,27 @@ jobs:
|
|||||||
run: ./gradlew clean createExe
|
run: ./gradlew clean createExe
|
||||||
env:
|
env:
|
||||||
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
|
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
|
||||||
STIRLING_PDF_DESKTOP_UI: false
|
|
||||||
|
|
||||||
- name: Get version number
|
- name: Get version number
|
||||||
id: versionNumber
|
id: versionNumber
|
||||||
run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
|
run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Rename binarie
|
- name: Rename binarie
|
||||||
run: cp ./build/launch4j/Stirling-PDF.exe ./build/launch4j/Stirling-PDF-Server${{ matrix.file_suffix }}.exe
|
if: matrix.file_suffix != ''
|
||||||
|
run: cp ./build/launch4j/Stirling-PDF.exe ./build/launch4j/Stirling-PDF${{ matrix.file_suffix }}.exe
|
||||||
|
|
||||||
- name: Upload Assets binarie
|
- name: Upload Assets binarie
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: ./build/launch4j/Stirling-PDF-Server${{ matrix.file_suffix }}.exe
|
path: ./build/launch4j/Stirling-PDF${{ matrix.file_suffix }}.exe
|
||||||
name: Stirling-PDF-Server${{ matrix.file_suffix }}.exe
|
name: Stirling-PDF${{ matrix.file_suffix }}.exe
|
||||||
overwrite: true
|
overwrite: true
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload binaries to release
|
- name: Upload binaries to release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: ./build/launch4j/Stirling-PDF-Server${{ matrix.file_suffix }}.exe
|
files: ./build/launch4j/Stirling-PDF${{ matrix.file_suffix }}.exe
|
||||||
|
|
||||||
- name: Rename jar binaries
|
- name: Rename jar binaries
|
||||||
run: cp ./build/libs/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.jar ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
|
run: cp ./build/libs/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.jar ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
|
||||||
@@ -74,43 +73,3 @@ jobs:
|
|||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
|
files: ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
|
||||||
|
|
||||||
|
|
||||||
push-ui:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up JDK 17
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
java-version: "17"
|
|
||||||
distribution: "temurin"
|
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@v4
|
|
||||||
with:
|
|
||||||
gradle-version: 8.7
|
|
||||||
|
|
||||||
- name: Generate exe
|
|
||||||
run: ./gradlew clean createExe
|
|
||||||
env:
|
|
||||||
DOCKER_ENABLE_SECURITY: false
|
|
||||||
STIRLING_PDF_DESKTOP_UI: true
|
|
||||||
|
|
||||||
- name: Get version number
|
|
||||||
id: versionNumber
|
|
||||||
run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Upload Assets binarie
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
path: ./build/launch4j/Stirling-PDF.exe
|
|
||||||
name: Stirling-PDF.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.exe
|
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -161,4 +161,3 @@ out/
|
|||||||
.pytest_cache
|
.pytest_cache
|
||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
|
|
||||||
**/jcef-bundle/
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# use alpine
|
# use alpine
|
||||||
FROM alpine:3.21.0
|
FROM alpine:3.20.3
|
||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
|
|
||||||
|
|||||||
75
README.md
75
README.md
@@ -2,7 +2,7 @@
|
|||||||
<h1 align="center">Stirling-PDF</h1>
|
<h1 align="center">Stirling-PDF</h1>
|
||||||
|
|
||||||
[](https://hub.docker.com/r/frooodle/s-pdf)
|
[](https://hub.docker.com/r/frooodle/s-pdf)
|
||||||
[](https://discord.gg/HYmhKj45pU)
|
[](https://discord.gg/Cn8pWhQRxZ)
|
||||||
[](https://github.com/Stirling-Tools/Stirling-PDF/)
|
[](https://github.com/Stirling-Tools/Stirling-PDF/)
|
||||||
[](https://github.com/Stirling-Tools/stirling-pdf)
|
[](https://github.com/Stirling-Tools/stirling-pdf)
|
||||||
|
|
||||||
@@ -187,48 +187,47 @@ Certain functionality like `Sign` supports pre-saved files stored at `/customFil
|
|||||||
|
|
||||||
## Supported Languages
|
## Supported Languages
|
||||||
|
|
||||||
Stirling-PDF currently supports 38 languages!
|
Stirling-PDF currently supports 37 languages!
|
||||||
|
|
||||||
| Language | Progress |
|
| Language | Progress |
|
||||||
| -------------------------------------------- | -------------------------------------- |
|
| -------------------------------------------- | -------------------------------------- |
|
||||||
| Arabic (العربية) (ar_AR) |  |
|
| Arabic (العربية) (ar_AR) |  |
|
||||||
| Azerbaijani (Azərbaycan Dili) (az_AZ) |  |
|
| Azerbaijani (Azərbaycan Dili) (az_AZ) |  |
|
||||||
| Basque (Euskara) (eu_ES) |  |
|
| Basque (Euskara) (eu_ES) |  |
|
||||||
| Bulgarian (Български) (bg_BG) |  |
|
| Bulgarian (Български) (bg_BG) |  |
|
||||||
| Catalan (Català) (ca_CA) |  |
|
| Catalan (Català) (ca_CA) |  |
|
||||||
| Croatian (Hrvatski) (hr_HR) |  |
|
| Croatian (Hrvatski) (hr_HR) |  |
|
||||||
| Czech (Česky) (cs_CZ) |  |
|
| Czech (Česky) (cs_CZ) |  |
|
||||||
| Danish (Dansk) (da_DK) |  |
|
| Danish (Dansk) (da_DK) |  |
|
||||||
| Dutch (Nederlands) (nl_NL) |  |
|
| Dutch (Nederlands) (nl_NL) |  |
|
||||||
| English (English) (en_GB) |  |
|
| English (English) (en_GB) |  |
|
||||||
| English (US) (en_US) |  |
|
| English (US) (en_US) |  |
|
||||||
| French (Français) (fr_FR) |  |
|
| French (Français) (fr_FR) |  |
|
||||||
| German (Deutsch) (de_DE) |  |
|
| German (Deutsch) (de_DE) |  |
|
||||||
| Greek (Ελληνικά) (el_GR) |  |
|
| Greek (Ελληνικά) (el_GR) |  |
|
||||||
| Hindi (हिंदी) (hi_IN) |  |
|
| Hindi (हिंदी) (hi_IN) |  |
|
||||||
| Hungarian (Magyar) (hu_HU) |  |
|
| Hungarian (Magyar) (hu_HU) |  |
|
||||||
| Indonesian (Bahasa Indonesia) (id_ID) |  |
|
| Indonesian (Bahasa Indonesia) (id_ID) |  |
|
||||||
| Irish (Gaeilge) (ga_IE) |  |
|
| Irish (Gaeilge) (ga_IE) |  |
|
||||||
| Italian (Italiano) (it_IT) |  |
|
| Italian (Italiano) (it_IT) |  |
|
||||||
| Japanese (日本語) (ja_JP) |  |
|
| Japanese (日本語) (ja_JP) |  |
|
||||||
| Korean (한국어) (ko_KR) |  |
|
| Korean (한국어) (ko_KR) |  |
|
||||||
| Norwegian (Norsk) (no_NB) |  |
|
| Norwegian (Norsk) (no_NB) |  |
|
||||||
| Persian (فارسی) (fa_IR) |  |
|
| Polish (Polski) (pl_PL) |  |
|
||||||
| Polish (Polski) (pl_PL) |  |
|
| Portuguese (Português) (pt_PT) |  |
|
||||||
| Portuguese (Português) (pt_PT) |  |
|
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
| Romanian (Română) (ro_RO) |  |
|
||||||
| Romanian (Română) (ro_RO) |  |
|
| Russian (Русский) (ru_RU) |  |
|
||||||
| Russian (Русский) (ru_RU) |  |
|
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
||||||
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
| Slovakian (Slovensky) (sk_SK) |  |
|
||||||
| Slovakian (Slovensky) (sk_SK) |  |
|
| Spanish (Español) (es_ES) |  |
|
||||||
| Spanish (Español) (es_ES) |  |
|
| Swedish (Svenska) (sv_SE) |  |
|
||||||
| Swedish (Svenska) (sv_SE) |  |
|
| Thai (ไทย) (th_TH) |  |
|
||||||
| Thai (ไทย) (th_TH) |  |
|
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
| Turkish (Türkçe) (tr_TR) |  |
|
||||||
| Turkish (Türkçe) (tr_TR) |  |
|
| Ukrainian (Українська) (uk_UA) |  |
|
||||||
| Ukrainian (Українська) (uk_UA) |  |
|
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
|
||||||
|
|
||||||
## Contributing (Creating Issues, Translations, Fixing Bugs, etc.)
|
## Contributing (Creating Issues, Translations, Fixing Bugs, etc.)
|
||||||
|
|
||||||
@@ -405,7 +404,7 @@ To access your account settings, go to Account Settings in the settings cog menu
|
|||||||
|
|
||||||
To add new users, go to the bottom of Account Settings and hit 'Admin Settings'. Here you can add new users. The different roles mentioned within this are for rate limiting. This is a work in progress and will be expanded on more in the future.
|
To add new users, go to the bottom of Account Settings and hit 'Admin Settings'. Here you can add new users. The different roles mentioned within this are for rate limiting. This is a work in progress and will be expanded on more in the future.
|
||||||
|
|
||||||
For API usage, you must provide a header with `X-API-KEY` and the associated API key for that user.
|
For API usage, you must provide a header with `X-API-Key` and the associated API key for that user.
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
|
|||||||
184
build.gradle
184
build.gradle
@@ -8,7 +8,6 @@ plugins {
|
|||||||
id "com.diffplug.spotless" version "6.25.0"
|
id "com.diffplug.spotless" version "6.25.0"
|
||||||
id "com.github.jk1.dependency-license-report" version "2.9"
|
id "com.github.jk1.dependency-license-report" version "2.9"
|
||||||
//id "nebula.lint" version "19.0.3"
|
//id "nebula.lint" version "19.0.3"
|
||||||
id("org.panteleyev.jpackageplugin") version "1.6.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -22,12 +21,10 @@ ext {
|
|||||||
imageioVersion = "3.12.0"
|
imageioVersion = "3.12.0"
|
||||||
lombokVersion = "1.18.36"
|
lombokVersion = "1.18.36"
|
||||||
bouncycastleVersion = "1.79"
|
bouncycastleVersion = "1.79"
|
||||||
springSecuritySamlVersion = "6.4.1"
|
|
||||||
openSamlVersion = "4.3.2"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
group = "stirling.software"
|
||||||
version = "0.36.2"
|
version = "0.35.0"
|
||||||
|
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -42,9 +39,6 @@ repositories {
|
|||||||
maven {
|
maven {
|
||||||
url 'https://build.shibboleth.net/maven/releases'
|
url 'https://build.shibboleth.net/maven/releases'
|
||||||
}
|
}
|
||||||
maven { url "https://build.shibboleth.net/maven/releases" }
|
|
||||||
maven { url "https://maven.pkg.github.com/jcefmaven/jcefmaven" }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
licenseReport {
|
licenseReport {
|
||||||
@@ -68,12 +62,6 @@ sourceSets {
|
|||||||
exclude "stirling/software/SPDF/model/User.java"
|
exclude "stirling/software/SPDF/model/User.java"
|
||||||
exclude "stirling/software/SPDF/repository/**"
|
exclude "stirling/software/SPDF/repository/**"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
|
|
||||||
exclude "stirling/software/SPDF/UI/impl/**"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,153 +72,16 @@ openApi {
|
|||||||
outputFileName = "SwaggerDoc.json"
|
outputFileName = "SwaggerDoc.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
//0.11.5 to 2024.11.5
|
|
||||||
def getMacVersion(String version) {
|
|
||||||
def currentYear = java.time.Year.now().getValue()
|
|
||||||
def versionParts = version.split("\\.", 2)
|
|
||||||
return "${currentYear}.${versionParts.length > 1 ? versionParts[1] : versionParts[0]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
jpackage {
|
|
||||||
input = "build/libs"
|
|
||||||
|
|
||||||
appName = "Stirling-PDF"
|
|
||||||
appVersion = project.version
|
|
||||||
vendor = "Stirling-Software"
|
|
||||||
appDescription = "Stirling PDF - Your Local PDF Editor"
|
|
||||||
|
|
||||||
mainJar = "Stirling-PDF-${project.version}.jar"
|
|
||||||
mainClass = "org.springframework.boot.loader.launch.JarLauncher"
|
|
||||||
|
|
||||||
icon = "src/main/resources/static/favicon.ico"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// JVM Options
|
|
||||||
javaOptions = [
|
|
||||||
"-DBROWSER_OPEN=true",
|
|
||||||
"-DSTIRLING_PDF_DESKTOP_UI=true",
|
|
||||||
"-Djava.awt.headless=false",
|
|
||||||
"-Dapple.awt.UIElement=true",
|
|
||||||
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
|
|
||||||
"--add-opens", "java.desktop/java.awt.event=ALL-UNNAMED",
|
|
||||||
"--add-opens", "java.desktop/sun.awt=ALL-UNNAMED"
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
verbose = true
|
|
||||||
|
|
||||||
destination = "${projectDir}/build/jpackage"
|
|
||||||
|
|
||||||
// Windows-specific configuration
|
|
||||||
windows {
|
|
||||||
launcherAsService = false
|
|
||||||
appVersion = project.version
|
|
||||||
winConsole = false
|
|
||||||
winDirChooser = true
|
|
||||||
winMenu = true
|
|
||||||
winShortcut = true
|
|
||||||
winPerUserInstall = true
|
|
||||||
winMenuGroup = "Stirling Software"
|
|
||||||
winUpgradeUuid = "2a43ed0c-b8c2-40cf-89e1-751129b87641" // Unique identifier for updates
|
|
||||||
winHelpUrl = "https://github.com/Stirling-Tools/Stirling-PDF"
|
|
||||||
winUpdateUrl = "https://github.com/Stirling-Tools/Stirling-PDF/releases"
|
|
||||||
type = "exe"
|
|
||||||
installDir = "C:/Program Files/Stirling-PDF"
|
|
||||||
}
|
|
||||||
|
|
||||||
// macOS-specific configuration
|
|
||||||
mac {
|
|
||||||
appVersion = getMacVersion(project.version.toString())
|
|
||||||
icon = "src/main/resources/static/favicon.icns"
|
|
||||||
type = "dmg"
|
|
||||||
macPackageIdentifier = "com.stirling.software.pdf"
|
|
||||||
macPackageName = "Stirling-PDF"
|
|
||||||
macAppCategory = "public.app-category.productivity"
|
|
||||||
macSign = false // Enable signing
|
|
||||||
macAppStore = false // Not targeting App Store initially
|
|
||||||
|
|
||||||
//installDir = "Applications"
|
|
||||||
|
|
||||||
// Add license and other documentation to DMG
|
|
||||||
/*macDmgContent = [
|
|
||||||
"README.md",
|
|
||||||
"LICENSE",
|
|
||||||
"CHANGELOG.md"
|
|
||||||
]*/
|
|
||||||
|
|
||||||
// Enable Mac-specific entitlements
|
|
||||||
//macEntitlements = "entitlements.plist" // You'll need to create this file
|
|
||||||
}
|
|
||||||
|
|
||||||
// Linux-specific configuration
|
|
||||||
linux {
|
|
||||||
appVersion = project.version
|
|
||||||
icon = "src/main/resources/static/favicon.png"
|
|
||||||
type = "deb" // Can also use "rpm" for Red Hat-based systems
|
|
||||||
|
|
||||||
// Debian package configuration
|
|
||||||
//linuxPackageName = "stirlingpdf"
|
|
||||||
linuxDebMaintainer = "support@stirlingpdf.com"
|
|
||||||
linuxMenuGroup = "Office;PDF;Productivity"
|
|
||||||
linuxAppCategory = "Office"
|
|
||||||
linuxAppRelease = "1"
|
|
||||||
linuxPackageDeps = true
|
|
||||||
|
|
||||||
installDir = "/opt/Stirling-PDF"
|
|
||||||
|
|
||||||
// RPM-specific settings
|
|
||||||
//linuxRpmLicenseType = "MIT"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common additional options
|
|
||||||
//jLinkOptions = [
|
|
||||||
// "--strip-debug",
|
|
||||||
// "--compress=2",
|
|
||||||
// "--no-header-files",
|
|
||||||
// "--no-man-pages"
|
|
||||||
//]
|
|
||||||
|
|
||||||
// Add any additional modules required
|
|
||||||
/*addModules = [
|
|
||||||
"java.base",
|
|
||||||
"java.desktop",
|
|
||||||
"java.logging",
|
|
||||||
"java.sql",
|
|
||||||
"java.xml",
|
|
||||||
"jdk.crypto.ec"
|
|
||||||
]*/
|
|
||||||
|
|
||||||
// Add copyright and license information
|
|
||||||
copyright = "Copyright © 2024 Stirling Software"
|
|
||||||
licenseFile = "LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
launch4j {
|
launch4j {
|
||||||
icon = "${projectDir}/src/main/resources/static/favicon.ico"
|
icon = "${projectDir}/src/main/resources/static/favicon.ico"
|
||||||
|
|
||||||
outfile="Stirling-PDF.exe"
|
outfile="Stirling-PDF.exe"
|
||||||
|
|
||||||
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
|
|
||||||
headerType = "gui"
|
|
||||||
} else {
|
|
||||||
headerType="console"
|
headerType="console"
|
||||||
}
|
|
||||||
jarTask = tasks.bootJar
|
jarTask = tasks.bootJar
|
||||||
|
|
||||||
errTitle="Encountered error, Do you have Java 21?"
|
errTitle="Encountered error, Do you have Java 21?"
|
||||||
downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
|
downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
|
||||||
|
|
||||||
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
|
|
||||||
variables=["BROWSER_OPEN=true", "STIRLING_PDF_DESKTOP_UI=true"]
|
|
||||||
} else {
|
|
||||||
variables=["BROWSER_OPEN=true"]
|
variables=["BROWSER_OPEN=true"]
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jreMinVersion="17"
|
jreMinVersion="17"
|
||||||
|
|
||||||
mutexName="Stirling-PDF"
|
mutexName="Stirling-PDF"
|
||||||
@@ -270,13 +121,6 @@ configurations.all {
|
|||||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") {
|
|
||||||
implementation "me.friwi:jcefmaven:127.3.1"
|
|
||||||
implementation "org.openjfx:javafx-controls:21"
|
|
||||||
implementation "org.openjfx:javafx-swing:21"
|
|
||||||
}
|
|
||||||
|
|
||||||
//security updates
|
//security updates
|
||||||
implementation "org.springframework:spring-webmvc:6.2.0"
|
implementation "org.springframework:spring-webmvc:6.2.0"
|
||||||
|
|
||||||
@@ -296,22 +140,21 @@ dependencies {
|
|||||||
|
|
||||||
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
|
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
|
||||||
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
|
||||||
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE"
|
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
||||||
|
|
||||||
implementation "org.springframework.session:spring-session-core:$springBootVersion"
|
implementation 'org.springframework.security:spring-security-saml2-service-provider:6.4.1'
|
||||||
|
|
||||||
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
||||||
// Don't upgrade h2database
|
// Don't upgrade h2database
|
||||||
runtimeOnly "com.h2database:h2:2.3.232"
|
runtimeOnly "com.h2database:h2:2.3.232"
|
||||||
constraints {
|
constraints {
|
||||||
implementation "org.opensaml:opensaml-core:$openSamlVersion"
|
implementation "org.opensaml:opensaml-core"
|
||||||
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
|
implementation "org.opensaml:opensaml-saml-api"
|
||||||
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
|
implementation "org.opensaml:opensaml-saml-impl"
|
||||||
}
|
}
|
||||||
implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
|
implementation "org.springframework.security:spring-security-saml2-service-provider"
|
||||||
// implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion'
|
|
||||||
implementation 'com.coveo:saml-client:5.0.0'
|
implementation 'com.coveo:saml-client:5.0.0'
|
||||||
|
|
||||||
|
|
||||||
@@ -343,7 +186,7 @@ dependencies {
|
|||||||
// Image metadata extractor
|
// Image metadata extractor
|
||||||
implementation "com.drewnoakes:metadata-extractor:2.19.0"
|
implementation "com.drewnoakes:metadata-extractor:2.19.0"
|
||||||
|
|
||||||
implementation "commons-io:commons-io:2.18.0"
|
implementation "commons-io:commons-io:2.17.0"
|
||||||
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
|
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
|
||||||
//general PDF
|
//general PDF
|
||||||
|
|
||||||
@@ -425,14 +268,7 @@ jar {
|
|||||||
tasks.named("test") {
|
tasks.named("test") {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
task printVersion {
|
task printVersion {
|
||||||
doLast {
|
|
||||||
println project.version
|
println project.version
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
task printMacVersion {
|
|
||||||
doLast {
|
|
||||||
println getMacVersion(project.version.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -48,6 +48,24 @@ Feature: API Validation
|
|||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ocr @negative
|
||||||
|
Scenario: Process PDF with text and OCR with type normal
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the pdf contains 3 pages with random text
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| languages | eng |
|
||||||
|
| sidecar | false |
|
||||||
|
| deskew | true |
|
||||||
|
| clean | true |
|
||||||
|
| cleanFinal | true |
|
||||||
|
| ocrType | Normal |
|
||||||
|
| ocrRenderType | hocr |
|
||||||
|
| removeImagesAfter| false |
|
||||||
|
When I send the API request to the endpoint "/api/v1/misc/ocr-pdf"
|
||||||
|
Then the response status code should be 500
|
||||||
|
|
||||||
@ocr @positive
|
@ocr @positive
|
||||||
Scenario: Process PDF with OCR
|
Scenario: Process PDF with OCR
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
@@ -66,6 +84,26 @@ Feature: API Validation
|
|||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
|
@ocr @positive
|
||||||
|
Scenario: Process PDF with OCR with sidecar
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| languages | eng |
|
||||||
|
| sidecar | true |
|
||||||
|
| deskew | true |
|
||||||
|
| clean | true |
|
||||||
|
| cleanFinal | true |
|
||||||
|
| ocrType | Force |
|
||||||
|
| ocrRenderType | hocr |
|
||||||
|
| removeImagesAfter| false |
|
||||||
|
When I send the API request to the endpoint "/api/v1/misc/ocr-pdf"
|
||||||
|
Then the response content type should be "application/octet-stream"
|
||||||
|
And the response file should have extension ".zip"
|
||||||
|
And the response ZIP should contain 2 files
|
||||||
|
And the response file should have size greater than 0
|
||||||
|
And the response status code should be 200
|
||||||
|
|
||||||
|
|
||||||
@libre @positive
|
@libre @positive
|
||||||
Scenario Outline: Convert PDF to various word formats
|
Scenario Outline: Convert PDF to various word formats
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ import shutil
|
|||||||
import re
|
import re
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
API_HEADERS = {
|
|
||||||
'X-API-KEY': '123456789'
|
|
||||||
}
|
|
||||||
|
|
||||||
#########
|
#########
|
||||||
# GIVEN #
|
# GIVEN #
|
||||||
#########
|
#########
|
||||||
@@ -231,7 +227,7 @@ def save_generated_pdf(context, filename):
|
|||||||
def step_send_get_request(context, endpoint):
|
def step_send_get_request(context, endpoint):
|
||||||
base_url = "http://localhost:8080"
|
base_url = "http://localhost:8080"
|
||||||
full_url = f"{base_url}{endpoint}"
|
full_url = f"{base_url}{endpoint}"
|
||||||
response = requests.get(full_url, headers=API_HEADERS)
|
response = requests.get(full_url)
|
||||||
context.response = response
|
context.response = response
|
||||||
|
|
||||||
@when('I send a GET request to "{endpoint}" with parameters')
|
@when('I send a GET request to "{endpoint}" with parameters')
|
||||||
@@ -239,7 +235,7 @@ def step_send_get_request_with_params(context, endpoint):
|
|||||||
base_url = "http://localhost:8080"
|
base_url = "http://localhost:8080"
|
||||||
params = {row['parameter']: row['value'] for row in context.table}
|
params = {row['parameter']: row['value'] for row in context.table}
|
||||||
full_url = f"{base_url}{endpoint}"
|
full_url = f"{base_url}{endpoint}"
|
||||||
response = requests.get(full_url, params=params, headers=API_HEADERS)
|
response = requests.get(full_url, params=params)
|
||||||
context.response = response
|
context.response = response
|
||||||
|
|
||||||
@when('I send the API request to the endpoint "{endpoint}"')
|
@when('I send the API request to the endpoint "{endpoint}"')
|
||||||
@@ -260,7 +256,7 @@ def step_send_api_request(context, endpoint):
|
|||||||
print(f"form_data {file.name} with {mime_type}")
|
print(f"form_data {file.name} with {mime_type}")
|
||||||
form_data.append((key, (file.name, file, mime_type)))
|
form_data.append((key, (file.name, file, mime_type)))
|
||||||
|
|
||||||
response = requests.post(url, files=form_data, headers=API_HEADERS)
|
response = requests.post(url, files=form_data)
|
||||||
context.response = response
|
context.response = response
|
||||||
|
|
||||||
########
|
########
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security-Fat
|
|
||||||
image: stirlingtools/stirling-pdf:latest-fat
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f -H 'X-API-KEY: 123456789' http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
|
||||||
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"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest-fat with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest-fat
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SECURITY_CUSTOMGLOBALAPIKEY: "123456789"
|
|
||||||
restart: on-failure:5
|
|
||||||
@@ -42,19 +42,14 @@ ignore = [
|
|||||||
'addPageNumbers.selectText.3',
|
'addPageNumbers.selectText.3',
|
||||||
'alphabet',
|
'alphabet',
|
||||||
'certSign.name',
|
'certSign.name',
|
||||||
'fileChooser.dragAndDrop',
|
|
||||||
'home.pipeline.title',
|
'home.pipeline.title',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
'legal.impressum',
|
|
||||||
'licenses.version',
|
'licenses.version',
|
||||||
'pipeline.title',
|
'pipeline.title',
|
||||||
'pipelineOptions.pipelineHeader',
|
'pipelineOptions.pipelineHeader',
|
||||||
'pro',
|
'pro',
|
||||||
'sponsor',
|
'sponsor',
|
||||||
'text',
|
'text',
|
||||||
'validateSignature.cert.bits',
|
|
||||||
'validateSignature.cert.version',
|
|
||||||
'validateSignature.status',
|
|
||||||
'watermark.type.1',
|
'watermark.type.1',
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -66,6 +61,7 @@ ignore = [
|
|||||||
[es_ES]
|
[es_ES]
|
||||||
ignore = [
|
ignore = [
|
||||||
'adminUserSettings.roles',
|
'adminUserSettings.roles',
|
||||||
|
'color',
|
||||||
'error',
|
'error',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
'no',
|
'no',
|
||||||
@@ -77,11 +73,6 @@ ignore = [
|
|||||||
'language.direction',
|
'language.direction',
|
||||||
]
|
]
|
||||||
|
|
||||||
[fa_IR]
|
|
||||||
ignore = [
|
|
||||||
'language.direction',
|
|
||||||
]
|
|
||||||
|
|
||||||
[fr_FR]
|
[fr_FR]
|
||||||
ignore = [
|
ignore = [
|
||||||
'AddStampRequest.alphabet',
|
'AddStampRequest.alphabet',
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ package stirling.software.SPDF.EE;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
@Lazy
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class EEAppConfig {
|
public class EEAppConfig {
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,9 @@ public class LicenseKeyChecker {
|
|||||||
KeygenLicenseVerifier licenseService, ApplicationProperties applicationProperties) {
|
KeygenLicenseVerifier licenseService, ApplicationProperties applicationProperties) {
|
||||||
this.licenseService = licenseService;
|
this.licenseService = licenseService;
|
||||||
this.applicationProperties = applicationProperties;
|
this.applicationProperties = applicationProperties;
|
||||||
this.checkLicense();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(initialDelay = 604800000, fixedRate = 604800000) // 7 days in milliseconds
|
@Scheduled(fixedRate = 604800000, initialDelay = 1000) // 7 days in milliseconds
|
||||||
public void checkLicensePeriodically() {
|
public void checkLicensePeriodically() {
|
||||||
checkLicense();
|
checkLicense();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package stirling.software.SPDF;
|
package stirling.software.SPDF;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -9,9 +8,6 @@ import java.nio.file.Paths;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -23,16 +19,13 @@ import org.springframework.core.env.Environment;
|
|||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
import io.github.pixee.security.SystemCommand;
|
import io.github.pixee.security.SystemCommand;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.PreDestroy;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.UI.WebBrowser;
|
|
||||||
import stirling.software.SPDF.config.ConfigInitializer;
|
import stirling.software.SPDF.config.ConfigInitializer;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@Slf4j
|
|
||||||
public class SPdfApplication {
|
public class SPdfApplication {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SPdfApplication.class);
|
private static final Logger logger = LoggerFactory.getLogger(SPdfApplication.class);
|
||||||
@@ -74,19 +67,36 @@ public class SPdfApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
baseUrlStatic = this.baseUrl;
|
||||||
|
// Check if the BROWSER_OPEN environment variable is set to true
|
||||||
|
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
||||||
|
boolean browserOpen = browserOpenEnv != null && "true".equalsIgnoreCase(browserOpenEnv);
|
||||||
|
if (browserOpen) {
|
||||||
|
try {
|
||||||
|
String url = baseUrl + ":" + getStaticPort();
|
||||||
|
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
Runtime rt = Runtime.getRuntime();
|
||||||
|
if (os.contains("win")) {
|
||||||
|
// For Windows
|
||||||
|
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
|
||||||
|
} else if (os.contains("mac")) {
|
||||||
|
SystemCommand.runCommand(rt, "open " + url);
|
||||||
|
} else if (os.contains("nix") || os.contains("nux")) {
|
||||||
|
SystemCommand.runCommand(rt, "xdg-open " + url);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error opening browser: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("Running configs {}", applicationProperties.toString());
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException, InterruptedException {
|
public static void main(String[] args) throws IOException, InterruptedException {
|
||||||
|
|
||||||
SpringApplication app = new SpringApplication(SPdfApplication.class);
|
SpringApplication app = new SpringApplication(SPdfApplication.class);
|
||||||
|
|
||||||
Properties props = new Properties();
|
|
||||||
|
|
||||||
if (Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) {
|
|
||||||
System.setProperty("java.awt.headless", "false");
|
|
||||||
app.setHeadless(false);
|
|
||||||
props.put("java.awt.headless", "false");
|
|
||||||
props.put("spring.main.web-application-type", "servlet");
|
|
||||||
}
|
|
||||||
|
|
||||||
app.setAdditionalProfiles("default");
|
app.setAdditionalProfiles("default");
|
||||||
app.addInitializers(new ConfigInitializer());
|
app.addInitializers(new ConfigInitializer());
|
||||||
Map<String, String> propertyFiles = new HashMap<>();
|
Map<String, String> propertyFiles = new HashMap<>();
|
||||||
@@ -110,20 +120,14 @@ public class SPdfApplication {
|
|||||||
} else {
|
} else {
|
||||||
logger.warn("Custom configuration file 'configs/custom_settings.yml' does not exist.");
|
logger.warn("Custom configuration file 'configs/custom_settings.yml' does not exist.");
|
||||||
}
|
}
|
||||||
Properties finalProps = new Properties();
|
|
||||||
|
|
||||||
if (!propertyFiles.isEmpty()) {
|
if (!propertyFiles.isEmpty()) {
|
||||||
finalProps.putAll(
|
app.setDefaultProperties(
|
||||||
Collections.singletonMap(
|
Collections.singletonMap(
|
||||||
"spring.config.additional-location",
|
"spring.config.additional-location",
|
||||||
propertyFiles.get("spring.config.additional-location")));
|
propertyFiles.get("spring.config.additional-location")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.isEmpty()) {
|
|
||||||
finalProps.putAll(props);
|
|
||||||
}
|
|
||||||
app.setDefaultProperties(finalProps);
|
|
||||||
|
|
||||||
app.run(args);
|
app.run(args);
|
||||||
|
|
||||||
// Ensure directories are created
|
// Ensure directories are created
|
||||||
@@ -143,46 +147,6 @@ public class SPdfApplication {
|
|||||||
logger.info("Navigate to {}", url);
|
logger.info("Navigate to {}", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private WebBrowser webBrowser;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
baseUrlStatic = this.baseUrl;
|
|
||||||
String url = baseUrl + ":" + getStaticPort();
|
|
||||||
if (webBrowser != null
|
|
||||||
&& Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) {
|
|
||||||
webBrowser.initWebUI(url);
|
|
||||||
} else {
|
|
||||||
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
|
||||||
boolean browserOpen = browserOpenEnv != null && "true".equalsIgnoreCase(browserOpenEnv);
|
|
||||||
if (browserOpen) {
|
|
||||||
try {
|
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
|
||||||
Runtime rt = Runtime.getRuntime();
|
|
||||||
if (os.contains("win")) {
|
|
||||||
// For Windows
|
|
||||||
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
|
|
||||||
} else if (os.contains("mac")) {
|
|
||||||
SystemCommand.runCommand(rt, "open " + url);
|
|
||||||
} else if (os.contains("nix") || os.contains("nux")) {
|
|
||||||
SystemCommand.runCommand(rt, "xdg-open " + url);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error opening browser: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info("Running configs {}", applicationProperties.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreDestroy
|
|
||||||
public void cleanup() {
|
|
||||||
if (webBrowser != null) {
|
|
||||||
webBrowser.cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getStaticBaseUrl() {
|
public static String getStaticBaseUrl() {
|
||||||
return baseUrlStatic;
|
return baseUrlStatic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package stirling.software.SPDF.UI;
|
|
||||||
|
|
||||||
public interface WebBrowser {
|
|
||||||
void initWebUI(String url);
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
}
|
|
||||||
@@ -1,354 +0,0 @@
|
|||||||
package stirling.software.SPDF.UI.impl;
|
|
||||||
|
|
||||||
import java.awt.AWTException;
|
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.Frame;
|
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.MenuItem;
|
|
||||||
import java.awt.PopupMenu;
|
|
||||||
import java.awt.SystemTray;
|
|
||||||
import java.awt.TrayIcon;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.awt.event.WindowStateListener;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.Timer;
|
|
||||||
|
|
||||||
import org.cef.CefApp;
|
|
||||||
import org.cef.CefClient;
|
|
||||||
import org.cef.CefSettings;
|
|
||||||
import org.cef.browser.CefBrowser;
|
|
||||||
import org.cef.callback.CefBeforeDownloadCallback;
|
|
||||||
import org.cef.callback.CefDownloadItem;
|
|
||||||
import org.cef.callback.CefDownloadItemCallback;
|
|
||||||
import org.cef.handler.CefDownloadHandlerAdapter;
|
|
||||||
import org.cef.handler.CefLoadHandlerAdapter;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import jakarta.annotation.PreDestroy;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import me.friwi.jcefmaven.CefAppBuilder;
|
|
||||||
import me.friwi.jcefmaven.EnumProgress;
|
|
||||||
import me.friwi.jcefmaven.MavenCefAppHandlerAdapter;
|
|
||||||
import me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler;
|
|
||||||
import stirling.software.SPDF.UI.WebBrowser;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
@ConditionalOnProperty(
|
|
||||||
name = "STIRLING_PDF_DESKTOP_UI",
|
|
||||||
havingValue = "true",
|
|
||||||
matchIfMissing = false)
|
|
||||||
public class DesktopBrowser implements WebBrowser {
|
|
||||||
private static CefApp cefApp;
|
|
||||||
private static CefClient client;
|
|
||||||
private static CefBrowser browser;
|
|
||||||
private static JFrame frame;
|
|
||||||
private static LoadingWindow loadingWindow;
|
|
||||||
private static volatile boolean browserInitialized = false;
|
|
||||||
private static TrayIcon trayIcon;
|
|
||||||
private static SystemTray systemTray;
|
|
||||||
|
|
||||||
public DesktopBrowser() {
|
|
||||||
SwingUtilities.invokeLater(
|
|
||||||
() -> {
|
|
||||||
loadingWindow = new LoadingWindow(null, "Initializing...");
|
|
||||||
loadingWindow.setVisible(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initWebUI(String url) {
|
|
||||||
CompletableFuture.runAsync(
|
|
||||||
() -> {
|
|
||||||
try {
|
|
||||||
CefAppBuilder builder = new CefAppBuilder();
|
|
||||||
configureCefSettings(builder);
|
|
||||||
builder.setProgressHandler(createProgressHandler());
|
|
||||||
|
|
||||||
// Build and initialize CEF
|
|
||||||
cefApp = builder.build();
|
|
||||||
client = cefApp.createClient();
|
|
||||||
|
|
||||||
// Set up download handler
|
|
||||||
setupDownloadHandler();
|
|
||||||
|
|
||||||
// Create browser and frame on EDT
|
|
||||||
SwingUtilities.invokeAndWait(
|
|
||||||
() -> {
|
|
||||||
browser = client.createBrowser(url, false, false);
|
|
||||||
setupMainFrame();
|
|
||||||
setupLoadHandler();
|
|
||||||
|
|
||||||
// Show the frame immediately but transparent
|
|
||||||
frame.setVisible(true);
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error initializing JCEF browser: ", e);
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureCefSettings(CefAppBuilder builder) {
|
|
||||||
CefSettings settings = builder.getCefSettings();
|
|
||||||
settings.cache_path = new File("jcef-bundle").getAbsolutePath();
|
|
||||||
settings.root_cache_path = new File("jcef-bundle").getAbsolutePath();
|
|
||||||
settings.persist_session_cookies = true;
|
|
||||||
settings.windowless_rendering_enabled = false;
|
|
||||||
settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_INFO;
|
|
||||||
|
|
||||||
builder.setAppHandler(
|
|
||||||
new MavenCefAppHandlerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void stateHasChanged(org.cef.CefApp.CefAppState state) {
|
|
||||||
log.info("CEF state changed: " + state);
|
|
||||||
if (state == CefApp.CefAppState.TERMINATED) {
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupDownloadHandler() {
|
|
||||||
client.addDownloadHandler(
|
|
||||||
new CefDownloadHandlerAdapter() {
|
|
||||||
@Override
|
|
||||||
public boolean onBeforeDownload(
|
|
||||||
CefBrowser browser,
|
|
||||||
CefDownloadItem downloadItem,
|
|
||||||
String suggestedName,
|
|
||||||
CefBeforeDownloadCallback callback) {
|
|
||||||
callback.Continue("", true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDownloadUpdated(
|
|
||||||
CefBrowser browser,
|
|
||||||
CefDownloadItem downloadItem,
|
|
||||||
CefDownloadItemCallback callback) {
|
|
||||||
if (downloadItem.isComplete()) {
|
|
||||||
log.info("Download completed: " + downloadItem.getFullPath());
|
|
||||||
} else if (downloadItem.isCanceled()) {
|
|
||||||
log.info("Download canceled: " + downloadItem.getFullPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConsoleProgressHandler createProgressHandler() {
|
|
||||||
return new ConsoleProgressHandler() {
|
|
||||||
@Override
|
|
||||||
public void handleProgress(EnumProgress state, float percent) {
|
|
||||||
Objects.requireNonNull(state, "state cannot be null");
|
|
||||||
SwingUtilities.invokeLater(
|
|
||||||
() -> {
|
|
||||||
if (loadingWindow != null) {
|
|
||||||
switch (state) {
|
|
||||||
case LOCATING:
|
|
||||||
loadingWindow.setStatus("Locating Files...");
|
|
||||||
loadingWindow.setProgress(0);
|
|
||||||
break;
|
|
||||||
case DOWNLOADING:
|
|
||||||
if (percent >= 0) {
|
|
||||||
loadingWindow.setStatus(
|
|
||||||
String.format(
|
|
||||||
"Downloading additional files: %.0f%%",
|
|
||||||
percent));
|
|
||||||
loadingWindow.setProgress((int) percent);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EXTRACTING:
|
|
||||||
loadingWindow.setStatus("Extracting files...");
|
|
||||||
loadingWindow.setProgress(60);
|
|
||||||
break;
|
|
||||||
case INITIALIZING:
|
|
||||||
loadingWindow.setStatus("Initializing UI...");
|
|
||||||
loadingWindow.setProgress(80);
|
|
||||||
break;
|
|
||||||
case INITIALIZED:
|
|
||||||
loadingWindow.setStatus("Finalising startup...");
|
|
||||||
loadingWindow.setProgress(90);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupMainFrame() {
|
|
||||||
frame = new JFrame("Stirling-PDF");
|
|
||||||
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
|
||||||
frame.setUndecorated(true);
|
|
||||||
frame.setOpacity(0.0f);
|
|
||||||
|
|
||||||
JPanel contentPane = new JPanel(new BorderLayout());
|
|
||||||
contentPane.setDoubleBuffered(true);
|
|
||||||
contentPane.add(browser.getUIComponent(), BorderLayout.CENTER);
|
|
||||||
frame.setContentPane(contentPane);
|
|
||||||
|
|
||||||
frame.addWindowListener(
|
|
||||||
new java.awt.event.WindowAdapter() {
|
|
||||||
@Override
|
|
||||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
|
||||||
cleanup();
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
frame.setSize(1280, 768);
|
|
||||||
frame.setLocationRelativeTo(null);
|
|
||||||
|
|
||||||
loadIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupLoadHandler() {
|
|
||||||
client.addLoadHandler(
|
|
||||||
new CefLoadHandlerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onLoadingStateChange(
|
|
||||||
CefBrowser browser,
|
|
||||||
boolean isLoading,
|
|
||||||
boolean canGoBack,
|
|
||||||
boolean canGoForward) {
|
|
||||||
if (!isLoading && !browserInitialized) {
|
|
||||||
browserInitialized = true;
|
|
||||||
SwingUtilities.invokeLater(
|
|
||||||
() -> {
|
|
||||||
if (loadingWindow != null) {
|
|
||||||
Timer timer =
|
|
||||||
new Timer(
|
|
||||||
500,
|
|
||||||
e -> {
|
|
||||||
loadingWindow.dispose();
|
|
||||||
loadingWindow = null;
|
|
||||||
|
|
||||||
frame.dispose();
|
|
||||||
frame.setOpacity(1.0f);
|
|
||||||
frame.setUndecorated(false);
|
|
||||||
frame.pack();
|
|
||||||
frame.setSize(1280, 800);
|
|
||||||
frame.setLocationRelativeTo(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
frame.requestFocus();
|
|
||||||
frame.toFront();
|
|
||||||
browser.getUIComponent()
|
|
||||||
.requestFocus();
|
|
||||||
});
|
|
||||||
timer.setRepeats(false);
|
|
||||||
timer.start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupTrayIcon(Image icon) {
|
|
||||||
if (!SystemTray.isSupported()) {
|
|
||||||
log.warn("System tray is not supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
systemTray = SystemTray.getSystemTray();
|
|
||||||
|
|
||||||
// Create popup menu
|
|
||||||
PopupMenu popup = new PopupMenu();
|
|
||||||
|
|
||||||
// Create menu items
|
|
||||||
MenuItem showItem = new MenuItem("Show");
|
|
||||||
showItem.addActionListener(
|
|
||||||
e -> {
|
|
||||||
frame.setVisible(true);
|
|
||||||
frame.setState(Frame.NORMAL);
|
|
||||||
});
|
|
||||||
|
|
||||||
MenuItem exitItem = new MenuItem("Exit");
|
|
||||||
exitItem.addActionListener(
|
|
||||||
e -> {
|
|
||||||
cleanup();
|
|
||||||
System.exit(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add menu items to popup menu
|
|
||||||
popup.add(showItem);
|
|
||||||
popup.addSeparator();
|
|
||||||
popup.add(exitItem);
|
|
||||||
|
|
||||||
// Create tray icon
|
|
||||||
trayIcon = new TrayIcon(icon, "Stirling-PDF", popup);
|
|
||||||
trayIcon.setImageAutoSize(true);
|
|
||||||
|
|
||||||
// Add double-click behavior
|
|
||||||
trayIcon.addActionListener(
|
|
||||||
e -> {
|
|
||||||
frame.setVisible(true);
|
|
||||||
frame.setState(Frame.NORMAL);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add tray icon to system tray
|
|
||||||
systemTray.add(trayIcon);
|
|
||||||
|
|
||||||
// Modify frame behavior to minimize to tray
|
|
||||||
frame.addWindowStateListener(
|
|
||||||
new WindowStateListener() {
|
|
||||||
public void windowStateChanged(WindowEvent e) {
|
|
||||||
if (e.getNewState() == Frame.ICONIFIED) {
|
|
||||||
frame.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (AWTException e) {
|
|
||||||
log.error("Error setting up system tray icon", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadIcon() {
|
|
||||||
try {
|
|
||||||
Image icon = null;
|
|
||||||
String[] iconPaths = {"/static/favicon.ico"};
|
|
||||||
|
|
||||||
for (String path : iconPaths) {
|
|
||||||
if (icon != null) break;
|
|
||||||
try {
|
|
||||||
try (InputStream is = getClass().getResourceAsStream(path)) {
|
|
||||||
if (is != null) {
|
|
||||||
icon = ImageIO.read(is);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.debug("Could not load icon from " + path, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (icon != null) {
|
|
||||||
frame.setIconImage(icon);
|
|
||||||
setupTrayIcon(icon);
|
|
||||||
} else {
|
|
||||||
log.warn("Could not load icon from any source");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error loading icon", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreDestroy
|
|
||||||
public void cleanup() {
|
|
||||||
if (browser != null) browser.close(true);
|
|
||||||
if (client != null) client.dispose();
|
|
||||||
if (cefApp != null) cefApp.dispose();
|
|
||||||
if (loadingWindow != null) loadingWindow.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package stirling.software.SPDF.UI.impl;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class LoadingWindow extends JDialog {
|
|
||||||
private final JProgressBar progressBar;
|
|
||||||
private final JLabel statusLabel;
|
|
||||||
private final JPanel mainPanel;
|
|
||||||
private final JLabel brandLabel;
|
|
||||||
|
|
||||||
public LoadingWindow(Frame parent, String initialUrl) {
|
|
||||||
super(parent, "Initializing Stirling-PDF", true);
|
|
||||||
|
|
||||||
// Initialize components
|
|
||||||
mainPanel = new JPanel();
|
|
||||||
mainPanel.setBackground(Color.WHITE);
|
|
||||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 30, 20, 30));
|
|
||||||
mainPanel.setLayout(new GridBagLayout());
|
|
||||||
GridBagConstraints gbc = new GridBagConstraints();
|
|
||||||
|
|
||||||
// Configure GridBagConstraints
|
|
||||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
|
||||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
|
||||||
gbc.insets = new Insets(5, 5, 5, 5);
|
|
||||||
gbc.weightx = 1.0; // Add horizontal weight
|
|
||||||
gbc.weighty = 0.0; // Add vertical weight
|
|
||||||
|
|
||||||
// Add icon
|
|
||||||
try {
|
|
||||||
try (InputStream is = getClass().getResourceAsStream("/static/favicon.ico")) {
|
|
||||||
if (is != null) {
|
|
||||||
Image img = ImageIO.read(is);
|
|
||||||
if (img != null) {
|
|
||||||
Image scaledImg = img.getScaledInstance(48, 48, Image.SCALE_SMOOTH);
|
|
||||||
JLabel iconLabel = new JLabel(new ImageIcon(scaledImg));
|
|
||||||
iconLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
|
||||||
gbc.gridy = 0;
|
|
||||||
mainPanel.add(iconLabel, gbc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to load icon", e);
|
|
||||||
}
|
|
||||||
// URL Label with explicit size
|
|
||||||
brandLabel = new JLabel(initialUrl);
|
|
||||||
brandLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
|
||||||
brandLabel.setPreferredSize(new Dimension(300, 25));
|
|
||||||
brandLabel.setText("Stirling-PDF");
|
|
||||||
gbc.gridy = 1;
|
|
||||||
mainPanel.add(brandLabel, gbc);
|
|
||||||
|
|
||||||
// Status label with explicit size
|
|
||||||
statusLabel = new JLabel("Initializing...");
|
|
||||||
statusLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
|
||||||
statusLabel.setPreferredSize(new Dimension(300, 25));
|
|
||||||
gbc.gridy = 2;
|
|
||||||
mainPanel.add(statusLabel, gbc);
|
|
||||||
// Progress bar with explicit size
|
|
||||||
progressBar = new JProgressBar(0, 100);
|
|
||||||
progressBar.setStringPainted(true);
|
|
||||||
progressBar.setPreferredSize(new Dimension(300, 25));
|
|
||||||
gbc.gridy = 3;
|
|
||||||
mainPanel.add(progressBar, gbc);
|
|
||||||
|
|
||||||
// Set dialog properties
|
|
||||||
setContentPane(mainPanel);
|
|
||||||
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
|
|
||||||
setResizable(false);
|
|
||||||
setUndecorated(false);
|
|
||||||
|
|
||||||
// Set size and position
|
|
||||||
setSize(400, 200);
|
|
||||||
setLocationRelativeTo(parent);
|
|
||||||
setAlwaysOnTop(true);
|
|
||||||
setProgress(0);
|
|
||||||
setStatus("Starting...");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProgress(final int progress) {
|
|
||||||
SwingUtilities.invokeLater(
|
|
||||||
() -> {
|
|
||||||
try {
|
|
||||||
progressBar.setValue(Math.min(Math.max(progress, 0), 100));
|
|
||||||
progressBar.setString(progress + "%");
|
|
||||||
mainPanel.revalidate();
|
|
||||||
mainPanel.repaint();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error updating progress", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(final String status) {
|
|
||||||
log.info(status);
|
|
||||||
SwingUtilities.invokeLater(
|
|
||||||
() -> {
|
|
||||||
try {
|
|
||||||
statusLabel.setText(status != null ? status : "");
|
|
||||||
mainPanel.revalidate();
|
|
||||||
mainPanel.repaint();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error updating status", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -260,9 +260,6 @@ public class EndpointConfiguration {
|
|||||||
|
|
||||||
// Pdftohtml dependent endpoints
|
// Pdftohtml dependent endpoints
|
||||||
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
||||||
|
|
||||||
// disabled for now while we resolve issues
|
|
||||||
disableEndpoint("pdf-to-pdfa");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processEnvironmentConfigs() {
|
private void processEnvironmentConfigs() {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class ExternalAppDepConfig {
|
|||||||
put("unoconv", List.of("Unoconv"));
|
put("unoconv", List.of("Unoconv"));
|
||||||
put("qpdf", List.of("qpdf"));
|
put("qpdf", List.of("qpdf"));
|
||||||
put("tesseract", List.of("tesseract"));
|
put("tesseract", List.of("tesseract"));
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
package stirling.software.SPDF.config;
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import io.micrometer.common.util.StringUtils;
|
import io.micrometer.common.util.StringUtils;
|
||||||
@@ -26,18 +23,6 @@ public class InitialSetup {
|
|||||||
@Autowired private ApplicationProperties applicationProperties;
|
@Autowired private ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() throws IOException {
|
|
||||||
initUUIDKey();
|
|
||||||
|
|
||||||
initSecretKey();
|
|
||||||
|
|
||||||
initEnableCSRFSecurity();
|
|
||||||
|
|
||||||
initLegalUrls();
|
|
||||||
|
|
||||||
initSetAppVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initUUIDKey() throws IOException {
|
public void initUUIDKey() throws IOException {
|
||||||
String uuid = applicationProperties.getAutomaticallyGenerated().getUUID();
|
String uuid = applicationProperties.getAutomaticallyGenerated().getUUID();
|
||||||
if (!GeneralUtils.isValidUUID(uuid)) {
|
if (!GeneralUtils.isValidUUID(uuid)) {
|
||||||
@@ -47,6 +32,7 @@ public class InitialSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
public void initSecretKey() throws IOException {
|
public void initSecretKey() throws IOException {
|
||||||
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
|
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
|
||||||
if (!GeneralUtils.isValidUUID(secretKey)) {
|
if (!GeneralUtils.isValidUUID(secretKey)) {
|
||||||
@@ -56,24 +42,13 @@ public class InitialSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initEnableCSRFSecurity() throws IOException {
|
@PostConstruct
|
||||||
if (GeneralUtils.isVersionHigher(
|
|
||||||
"0.36.0", applicationProperties.getAutomaticallyGenerated().getAppVersion())) {
|
|
||||||
Boolean csrf = applicationProperties.getSecurity().getCsrfDisabled();
|
|
||||||
if (!csrf) {
|
|
||||||
GeneralUtils.saveKeyToConfig("security.csrfDisabled", false, false);
|
|
||||||
GeneralUtils.saveKeyToConfig("system.enableAnalytics", "true", false);
|
|
||||||
applicationProperties.getSecurity().setCsrfDisabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initLegalUrls() throws IOException {
|
public void initLegalUrls() throws IOException {
|
||||||
// Initialize Terms and Conditions
|
// Initialize Terms and Conditions
|
||||||
String termsUrl = applicationProperties.getLegal().getTermsAndConditions();
|
String termsUrl = applicationProperties.getLegal().getTermsAndConditions();
|
||||||
if (StringUtils.isEmpty(termsUrl)) {
|
if (StringUtils.isEmpty(termsUrl)) {
|
||||||
String defaultTermsUrl = "https://www.stirlingpdf.com/terms-and-conditions";
|
String defaultTermsUrl = "https://www.stirlingpdf.com/terms-and-conditions";
|
||||||
GeneralUtils.saveKeyToConfig("legal.termsAndConditions", defaultTermsUrl, false);
|
GeneralUtils.saveKeyToConfig("legal.termsAndConditions", defaultTermsUrl);
|
||||||
applicationProperties.getLegal().setTermsAndConditions(defaultTermsUrl);
|
applicationProperties.getLegal().setTermsAndConditions(defaultTermsUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,23 +56,8 @@ public class InitialSetup {
|
|||||||
String privacyUrl = applicationProperties.getLegal().getPrivacyPolicy();
|
String privacyUrl = applicationProperties.getLegal().getPrivacyPolicy();
|
||||||
if (StringUtils.isEmpty(privacyUrl)) {
|
if (StringUtils.isEmpty(privacyUrl)) {
|
||||||
String defaultPrivacyUrl = "https://www.stirlingpdf.com/privacy-policy";
|
String defaultPrivacyUrl = "https://www.stirlingpdf.com/privacy-policy";
|
||||||
GeneralUtils.saveKeyToConfig("legal.privacyPolicy", defaultPrivacyUrl, false);
|
GeneralUtils.saveKeyToConfig("legal.privacyPolicy", defaultPrivacyUrl);
|
||||||
applicationProperties.getLegal().setPrivacyPolicy(defaultPrivacyUrl);
|
applicationProperties.getLegal().setPrivacyPolicy(defaultPrivacyUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initSetAppVersion() throws IOException {
|
|
||||||
|
|
||||||
String appVersion = "0.0.0";
|
|
||||||
Resource resource = new ClassPathResource("version.properties");
|
|
||||||
Properties props = new Properties();
|
|
||||||
try {
|
|
||||||
props.load(resource.getInputStream());
|
|
||||||
appVersion = props.getProperty("version");
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
applicationProperties.getAutomaticallyGenerated().setAppVersion(appVersion);
|
|
||||||
GeneralUtils.saveKeyToConfig("AutomaticallyGenerated.appVersion", appVersion, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ public class InitialSecuritySetup {
|
|||||||
initializeAdminUser();
|
initializeAdminUser();
|
||||||
} else {
|
} else {
|
||||||
databaseBackupHelper.exportDatabase();
|
databaseBackupHelper.exportDatabase();
|
||||||
userService.migrateOauth2ToSSO();
|
|
||||||
}
|
}
|
||||||
initializeInternalApiUser();
|
initializeInternalApiUser();
|
||||||
}
|
}
|
||||||
@@ -75,6 +74,5 @@ public class InitialSecuritySetup {
|
|||||||
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
|
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
|
||||||
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
|
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
|
||||||
}
|
}
|
||||||
userService.syncCustomApiUser(applicationProperties.getSecurity().getCustomGlobalAPIKey());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,14 @@ package stirling.software.SPDF.config.security;
|
|||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.opensaml.saml.saml2.core.AuthnRequest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.security.authentication.ProviderManager;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
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.builders.HttpSecurity;
|
||||||
@@ -34,8 +32,7 @@ import org.springframework.security.saml2.provider.service.authentication.OpenSa
|
|||||||
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
|
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||||
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
|
||||||
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||||
@@ -44,7 +41,6 @@ import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
|||||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
|
||||||
@@ -68,7 +64,6 @@ import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@DependsOn("runningEE")
|
|
||||||
public class SecurityConfiguration {
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
@Autowired private CustomUserDetailsService userDetailsService;
|
@Autowired private CustomUserDetailsService userDetailsService;
|
||||||
@@ -84,10 +79,6 @@ public class SecurityConfiguration {
|
|||||||
@Qualifier("loginEnabled")
|
@Qualifier("loginEnabled")
|
||||||
public boolean loginEnabledValue;
|
public boolean loginEnabledValue;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("runningEE")
|
|
||||||
public boolean runningEE;
|
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Autowired private UserAuthenticationFilter userAuthenticationFilter;
|
@Autowired private UserAuthenticationFilter userAuthenticationFilter;
|
||||||
@@ -99,14 +90,13 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
if (applicationProperties.getSecurity().getCsrfDisabled() || !loginEnabledValue) {
|
|
||||||
http.csrf(csrf -> csrf.disable());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loginEnabledValue) {
|
if (loginEnabledValue) {
|
||||||
http.addFilterBefore(
|
http.addFilterBefore(
|
||||||
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
if (!applicationProperties.getSecurity().getCsrfDisabled()) {
|
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
||||||
|
http.csrf(csrf -> csrf.disable());
|
||||||
|
} else {
|
||||||
CookieCsrfTokenRepository cookieRepo =
|
CookieCsrfTokenRepository cookieRepo =
|
||||||
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||||
CsrfTokenRequestAttributeHandler requestHandler =
|
CsrfTokenRequestAttributeHandler requestHandler =
|
||||||
@@ -116,7 +106,7 @@ public class SecurityConfiguration {
|
|||||||
csrf ->
|
csrf ->
|
||||||
csrf.ignoringRequestMatchers(
|
csrf.ignoringRequestMatchers(
|
||||||
request -> {
|
request -> {
|
||||||
String apiKey = request.getHeader("X-API-KEY");
|
String apiKey = request.getHeader("X-API-Key");
|
||||||
|
|
||||||
// If there's no API key, don't ignore CSRF
|
// If there's no API key, don't ignore CSRF
|
||||||
// (return false)
|
// (return false)
|
||||||
@@ -255,22 +245,12 @@ public class SecurityConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle SAML
|
// Handle SAML
|
||||||
if (applicationProperties.getSecurity().isSaml2Activ()) { // && runningEE
|
if (applicationProperties.getSecurity().isSaml2Activ()
|
||||||
// Configure the authentication provider
|
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
|
||||||
OpenSaml4AuthenticationProvider authenticationProvider =
|
http.authenticationProvider(samlAuthenticationProvider());
|
||||||
new OpenSaml4AuthenticationProvider();
|
http.saml2Login(
|
||||||
authenticationProvider.setResponseAuthenticationConverter(
|
saml2 ->
|
||||||
new CustomSaml2ResponseAuthenticationConverter(userService));
|
|
||||||
|
|
||||||
http.authenticationProvider(authenticationProvider)
|
|
||||||
.saml2Login(
|
|
||||||
saml2 -> {
|
|
||||||
try {
|
|
||||||
saml2.loginPage("/saml2")
|
saml2.loginPage("/saml2")
|
||||||
.relyingPartyRegistrationRepository(
|
|
||||||
relyingPartyRegistrations())
|
|
||||||
.authenticationManager(
|
|
||||||
new ProviderManager(authenticationProvider))
|
|
||||||
.successHandler(
|
.successHandler(
|
||||||
new CustomSaml2AuthenticationSuccessHandler(
|
new CustomSaml2AuthenticationSuccessHandler(
|
||||||
loginAttemptService,
|
loginAttemptService,
|
||||||
@@ -278,34 +258,44 @@ public class SecurityConfiguration {
|
|||||||
userService))
|
userService))
|
||||||
.failureHandler(
|
.failureHandler(
|
||||||
new CustomSaml2AuthenticationFailureHandler())
|
new CustomSaml2AuthenticationFailureHandler())
|
||||||
.authenticationRequestResolver(
|
.permitAll())
|
||||||
authenticationRequestResolver(
|
.addFilterBefore(
|
||||||
relyingPartyRegistrations()));
|
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error configuring SAML2 login", e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if (!applicationProperties.getSecurity().getCsrfDisabled()) {
|
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
||||||
// CookieCsrfTokenRepository cookieRepo =
|
http.csrf(csrf -> csrf.disable());
|
||||||
// CookieCsrfTokenRepository.withHttpOnlyFalse();
|
} else {
|
||||||
// CsrfTokenRequestAttributeHandler requestHandler =
|
CookieCsrfTokenRepository cookieRepo =
|
||||||
// new CsrfTokenRequestAttributeHandler();
|
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||||
// requestHandler.setCsrfRequestAttributeName(null);
|
CsrfTokenRequestAttributeHandler requestHandler =
|
||||||
// http.csrf(
|
new CsrfTokenRequestAttributeHandler();
|
||||||
// csrf ->
|
requestHandler.setCsrfRequestAttributeName(null);
|
||||||
// csrf.csrfTokenRepository(cookieRepo)
|
http.csrf(
|
||||||
// .csrfTokenRequestHandler(requestHandler));
|
csrf ->
|
||||||
// }
|
csrf.csrfTokenRepository(cookieRepo)
|
||||||
|
.csrfTokenRequestHandler(requestHandler));
|
||||||
|
}
|
||||||
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(
|
||||||
|
name = "security.saml2.enabled",
|
||||||
|
havingValue = "true",
|
||||||
|
matchIfMissing = false)
|
||||||
|
public AuthenticationProvider samlAuthenticationProvider() {
|
||||||
|
OpenSaml4AuthenticationProvider authenticationProvider =
|
||||||
|
new OpenSaml4AuthenticationProvider();
|
||||||
|
authenticationProvider.setResponseAuthenticationConverter(
|
||||||
|
new CustomSaml2ResponseAuthenticationConverter(userService));
|
||||||
|
return authenticationProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client Registration Repository for OAUTH2 OIDC Login
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
@ConditionalOnProperty(
|
||||||
value = "security.oauth2.enabled",
|
value = "security.oauth2.enabled",
|
||||||
@@ -442,12 +432,11 @@ public class SecurityConfiguration {
|
|||||||
havingValue = "true",
|
havingValue = "true",
|
||||||
matchIfMissing = false)
|
matchIfMissing = false)
|
||||||
public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exception {
|
public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exception {
|
||||||
|
|
||||||
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
|
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
|
||||||
|
|
||||||
X509Certificate idpCert = CertificateUtils.readCertificate(samlConf.getidpCert());
|
|
||||||
Saml2X509Credential verificationCredential = Saml2X509Credential.verification(idpCert);
|
|
||||||
|
|
||||||
Resource privateKeyResource = samlConf.getPrivateKey();
|
Resource privateKeyResource = samlConf.getPrivateKey();
|
||||||
|
|
||||||
Resource certificateResource = samlConf.getSpCert();
|
Resource certificateResource = samlConf.getSpCert();
|
||||||
|
|
||||||
Saml2X509Credential signingCredential =
|
Saml2X509Credential signingCredential =
|
||||||
@@ -456,97 +445,26 @@ public class SecurityConfiguration {
|
|||||||
CertificateUtils.readCertificate(certificateResource),
|
CertificateUtils.readCertificate(certificateResource),
|
||||||
Saml2X509CredentialType.SIGNING);
|
Saml2X509CredentialType.SIGNING);
|
||||||
|
|
||||||
|
X509Certificate idpCert = CertificateUtils.readCertificate(samlConf.getidpCert());
|
||||||
|
|
||||||
|
Saml2X509Credential verificationCredential = Saml2X509Credential.verification(idpCert);
|
||||||
|
|
||||||
RelyingPartyRegistration rp =
|
RelyingPartyRegistration rp =
|
||||||
RelyingPartyRegistration.withRegistrationId(samlConf.getRegistrationId())
|
RelyingPartyRegistration.withRegistrationId(samlConf.getRegistrationId())
|
||||||
.signingX509Credentials(c -> c.add(signingCredential))
|
.signingX509Credentials((c) -> c.add(signingCredential))
|
||||||
.assertingPartyMetadata(
|
.assertingPartyMetadata(
|
||||||
metadata ->
|
(details) ->
|
||||||
metadata.entityId(samlConf.getIdpIssuer())
|
details.entityId(samlConf.getIdpIssuer())
|
||||||
.singleSignOnServiceLocation(
|
.singleSignOnServiceLocation(
|
||||||
samlConf.getIdpSingleLoginUrl())
|
samlConf.getIdpSingleLoginUrl())
|
||||||
.verificationX509Credentials(
|
.verificationX509Credentials(
|
||||||
c -> c.add(verificationCredential))
|
(c) -> c.add(verificationCredential))
|
||||||
.singleSignOnServiceBinding(
|
|
||||||
Saml2MessageBinding.POST)
|
|
||||||
.wantAuthnRequestsSigned(true))
|
.wantAuthnRequestsSigned(true))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return new InMemoryRelyingPartyRegistrationRepository(rp);
|
return new InMemoryRelyingPartyRegistrationRepository(rp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
|
||||||
name = "security.saml2.enabled",
|
|
||||||
havingValue = "true",
|
|
||||||
matchIfMissing = false)
|
|
||||||
public OpenSaml4AuthenticationRequestResolver authenticationRequestResolver(
|
|
||||||
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {
|
|
||||||
OpenSaml4AuthenticationRequestResolver resolver =
|
|
||||||
new OpenSaml4AuthenticationRequestResolver(relyingPartyRegistrationRepository);
|
|
||||||
resolver.setAuthnRequestCustomizer(
|
|
||||||
customizer -> {
|
|
||||||
log.debug("Customizing SAML Authentication request");
|
|
||||||
|
|
||||||
AuthnRequest authnRequest = customizer.getAuthnRequest();
|
|
||||||
log.debug("AuthnRequest ID: {}", authnRequest.getID());
|
|
||||||
|
|
||||||
if (authnRequest.getID() == null) {
|
|
||||||
authnRequest.setID("ARQ" + UUID.randomUUID().toString());
|
|
||||||
}
|
|
||||||
log.debug("AuthnRequest new ID after set: {}", authnRequest.getID());
|
|
||||||
log.debug("AuthnRequest IssueInstant: {}", authnRequest.getIssueInstant());
|
|
||||||
log.debug(
|
|
||||||
"AuthnRequest Issuer: {}",
|
|
||||||
authnRequest.getIssuer() != null
|
|
||||||
? authnRequest.getIssuer().getValue()
|
|
||||||
: "null");
|
|
||||||
|
|
||||||
HttpServletRequest request = customizer.getRequest();
|
|
||||||
|
|
||||||
// Log HTTP request details
|
|
||||||
log.debug("HTTP Request Method: {}", request.getMethod());
|
|
||||||
log.debug("Request URI: {}", request.getRequestURI());
|
|
||||||
log.debug("Request URL: {}", request.getRequestURL().toString());
|
|
||||||
log.debug("Query String: {}", request.getQueryString());
|
|
||||||
log.debug("Remote Address: {}", request.getRemoteAddr());
|
|
||||||
|
|
||||||
// Log headers
|
|
||||||
Collections.list(request.getHeaderNames())
|
|
||||||
.forEach(
|
|
||||||
headerName -> {
|
|
||||||
log.debug(
|
|
||||||
"Header - {}: {}",
|
|
||||||
headerName,
|
|
||||||
request.getHeader(headerName));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Log SAML specific parameters
|
|
||||||
log.debug("SAML Request Parameters:");
|
|
||||||
log.debug("SAMLRequest: {}", request.getParameter("SAMLRequest"));
|
|
||||||
log.debug("RelayState: {}", request.getParameter("RelayState"));
|
|
||||||
|
|
||||||
// Log session debugrmation if exists
|
|
||||||
if (request.getSession(false) != null) {
|
|
||||||
log.debug("Session ID: {}", request.getSession().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log any assertions consumer service details if present
|
|
||||||
if (authnRequest.getAssertionConsumerServiceURL() != null) {
|
|
||||||
log.debug(
|
|
||||||
"AssertionConsumerServiceURL: {}",
|
|
||||||
authnRequest.getAssertionConsumerServiceURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log NameID policy if present
|
|
||||||
if (authnRequest.getNameIDPolicy() != null) {
|
|
||||||
log.debug(
|
|
||||||
"NameIDPolicy Format: {}",
|
|
||||||
authnRequest.getNameIDPolicy().getFormat());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DaoAuthenticationProvider daoAuthenticationProvider() {
|
public DaoAuthenticationProvider daoAuthenticationProvider() {
|
||||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||||
provider.setUserDetailsService(userDetailsService);
|
provider.setUserDetailsService(userDetailsService);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
// Check for API key in the request headers if no authentication exists
|
// Check for API key in the request headers if no authentication exists
|
||||||
if (authentication == null || !authentication.isAuthenticated()) {
|
if (authentication == null || !authentication.isAuthenticated()) {
|
||||||
String apiKey = request.getHeader("X-API-KEY");
|
String apiKey = request.getHeader("X-API-Key");
|
||||||
if (apiKey != null && !apiKey.trim().isEmpty()) {
|
if (apiKey != null && !apiKey.trim().isEmpty()) {
|
||||||
try {
|
try {
|
||||||
// Use API key to authenticate. This requires you to have an authentication
|
// Use API key to authenticate. This requires you to have an authentication
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
|
|||||||
String identifier = null;
|
String identifier = null;
|
||||||
|
|
||||||
// Check for API key in the request headers
|
// Check for API key in the request headers
|
||||||
String apiKey = request.getHeader("X-API-KEY");
|
String apiKey = request.getHeader("X-API-Key");
|
||||||
if (apiKey != null && !apiKey.trim().isEmpty()) {
|
if (apiKey != null && !apiKey.trim().isEmpty()) {
|
||||||
identifier =
|
identifier =
|
||||||
"API_KEY_" + apiKey; // Prefix to distinguish between API keys and usernames
|
"API_KEY_" + apiKey; // Prefix to distinguish between API keys and usernames
|
||||||
@@ -79,7 +79,7 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
|
|||||||
Role userRole =
|
Role userRole =
|
||||||
getRoleFromAuthentication(SecurityContextHolder.getContext().getAuthentication());
|
getRoleFromAuthentication(SecurityContextHolder.getContext().getAuthentication());
|
||||||
|
|
||||||
if (request.getHeader("X-API-KEY") != null) {
|
if (request.getHeader("X-API-Key") != null) {
|
||||||
// It's an API call
|
// It's an API call
|
||||||
processRequest(
|
processRequest(
|
||||||
userRole.getApiCallsPerDay(),
|
userRole.getApiCallsPerDay(),
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
||||||
@@ -51,19 +50,8 @@ public class UserService implements UserServiceInterface {
|
|||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void migrateOauth2ToSSO() {
|
|
||||||
userRepository
|
|
||||||
.findByAuthenticationTypeIgnoreCase("OAUTH2")
|
|
||||||
.forEach(
|
|
||||||
user -> {
|
|
||||||
user.setAuthenticationType(AuthenticationType.SSO);
|
|
||||||
userRepository.save(user);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle OAUTH2 login and user auto creation.
|
// Handle OAUTH2 login and user auto creation.
|
||||||
public boolean processSSOPostLogin(String username, boolean autoCreateUser)
|
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
|
||||||
throws IllegalArgumentException, IOException {
|
throws IllegalArgumentException, IOException {
|
||||||
if (!isUsernameValid(username)) {
|
if (!isUsernameValid(username)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -73,7 +61,7 @@ public class UserService implements UserServiceInterface {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (autoCreateUser) {
|
if (autoCreateUser) {
|
||||||
saveUser(username, AuthenticationType.SSO);
|
saveUser(username, AuthenticationType.OAUTH2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -390,37 +378,6 @@ public class UserService implements UserServiceInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void syncCustomApiUser(String customApiKey) throws IOException {
|
|
||||||
if (customApiKey == null || customApiKey.trim().length() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String username = "CUSTOM_API_USER";
|
|
||||||
Optional<User> existingUser = findByUsernameIgnoreCase(username);
|
|
||||||
|
|
||||||
if (!existingUser.isPresent()) {
|
|
||||||
// Create new user with API role
|
|
||||||
User user = new User();
|
|
||||||
user.setUsername(username);
|
|
||||||
user.setPassword(UUID.randomUUID().toString());
|
|
||||||
user.setEnabled(true);
|
|
||||||
user.setFirstLogin(false);
|
|
||||||
user.setAuthenticationType(AuthenticationType.WEB);
|
|
||||||
user.setApiKey(customApiKey);
|
|
||||||
user.addAuthority(new Authority(Role.INTERNAL_API_USER.getRoleId(), user));
|
|
||||||
userRepository.save(user);
|
|
||||||
databaseBackupHelper.exportDatabase();
|
|
||||||
} else {
|
|
||||||
// Update API key if it has changed
|
|
||||||
User user = existingUser.get();
|
|
||||||
if (!customApiKey.equals(user.getApiKey())) {
|
|
||||||
user.setApiKey(customApiKey);
|
|
||||||
userRepository.save(user);
|
|
||||||
databaseBackupHelper.exportDatabase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTotalUsersCount() {
|
public long getTotalUsersCount() {
|
||||||
return userRepository.count();
|
return userRepository.count();
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ public class CustomOAuth2AuthenticationSuccessHandler
|
|||||||
}
|
}
|
||||||
if (userService.usernameExistsIgnoreCase(username)
|
if (userService.usernameExistsIgnoreCase(username)
|
||||||
&& userService.hasPassword(username)
|
&& userService.hasPassword(username)
|
||||||
&& !userService.isAuthenticationTypeByUsername(username, AuthenticationType.SSO)
|
&& !userService.isAuthenticationTypeByUsername(
|
||||||
|
username, AuthenticationType.OAUTH2)
|
||||||
&& oAuth.getAutoCreateUser()) {
|
&& oAuth.getAutoCreateUser()) {
|
||||||
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
||||||
return;
|
return;
|
||||||
@@ -94,7 +95,7 @@ public class CustomOAuth2AuthenticationSuccessHandler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (principal instanceof OAuth2User) {
|
if (principal instanceof OAuth2User) {
|
||||||
userService.processSSOPostLogin(username, oAuth.getAutoCreateUser());
|
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
|
||||||
}
|
}
|
||||||
response.sendRedirect(contextPath + "/");
|
response.sendRedirect(contextPath + "/");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ package stirling.software.SPDF.config.security.saml2;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
|
||||||
import org.bouncycastle.openssl.PEMKeyPair;
|
|
||||||
import org.bouncycastle.openssl.PEMParser;
|
|
||||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
|
||||||
import org.bouncycastle.util.io.pem.PemObject;
|
import org.bouncycastle.util.io.pem.PemObject;
|
||||||
import org.bouncycastle.util.io.pem.PemReader;
|
import org.bouncycastle.util.io.pem.PemReader;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@@ -30,26 +28,15 @@ public class CertificateUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception {
|
public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception {
|
||||||
try (PEMParser pemParser =
|
try (PemReader pemReader =
|
||||||
new PEMParser(
|
new PemReader(
|
||||||
new InputStreamReader(
|
new InputStreamReader(
|
||||||
privateKeyResource.getInputStream(), StandardCharsets.UTF_8))) {
|
privateKeyResource.getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
|
PemObject pemObject = pemReader.readPemObject();
|
||||||
Object object = pemParser.readObject();
|
byte[] decodedKey = pemObject.getContent();
|
||||||
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
|
return (RSAPrivateKey)
|
||||||
|
KeyFactory.getInstance("RSA")
|
||||||
if (object instanceof PEMKeyPair) {
|
.generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
|
||||||
// Handle traditional RSA private key format
|
|
||||||
PEMKeyPair keypair = (PEMKeyPair) object;
|
|
||||||
return (RSAPrivateKey) converter.getPrivateKey(keypair.getPrivateKeyInfo());
|
|
||||||
} else if (object instanceof PrivateKeyInfo) {
|
|
||||||
// Handle PKCS#8 format
|
|
||||||
return (RSAPrivateKey) converter.getPrivateKey((PrivateKeyInfo) object);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unsupported key format: "
|
|
||||||
+ (object != null ? object.getClass().getName() : "null"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.config.security.LoginAttemptService;
|
import stirling.software.SPDF.config.security.LoginAttemptService;
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
@@ -21,11 +20,11 @@ import stirling.software.SPDF.model.AuthenticationType;
|
|||||||
import stirling.software.SPDF.utils.RequestUriUtils;
|
import stirling.software.SPDF.utils.RequestUriUtils;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Slf4j
|
|
||||||
public class CustomSaml2AuthenticationSuccessHandler
|
public class CustomSaml2AuthenticationSuccessHandler
|
||||||
extends SavedRequestAwareAuthenticationSuccessHandler {
|
extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||||
|
|
||||||
private LoginAttemptService loginAttemptService;
|
private LoginAttemptService loginAttemptService;
|
||||||
|
|
||||||
private ApplicationProperties applicationProperties;
|
private ApplicationProperties applicationProperties;
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
@@ -35,12 +34,10 @@ public class CustomSaml2AuthenticationSuccessHandler
|
|||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
Object principal = authentication.getPrincipal();
|
Object principal = authentication.getPrincipal();
|
||||||
log.debug("Starting SAML2 authentication success handling");
|
|
||||||
|
|
||||||
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
String username = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
String username = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
||||||
log.debug("Authenticated principal found for user: {}", username);
|
// Get the saved request
|
||||||
|
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
String contextPath = request.getContextPath();
|
String contextPath = request.getContextPath();
|
||||||
SavedRequest savedRequest =
|
SavedRequest savedRequest =
|
||||||
@@ -48,77 +45,46 @@ public class CustomSaml2AuthenticationSuccessHandler
|
|||||||
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
|
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
log.debug(
|
|
||||||
"Session exists: {}, Saved request exists: {}",
|
|
||||||
session != null,
|
|
||||||
savedRequest != null);
|
|
||||||
|
|
||||||
if (savedRequest != null
|
if (savedRequest != null
|
||||||
&& !RequestUriUtils.isStaticResource(
|
&& !RequestUriUtils.isStaticResource(
|
||||||
contextPath, savedRequest.getRedirectUrl())) {
|
contextPath, savedRequest.getRedirectUrl())) {
|
||||||
log.debug(
|
// Redirect to the original destination
|
||||||
"Valid saved request found, redirecting to original destination: {}",
|
|
||||||
savedRequest.getRedirectUrl());
|
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
} else {
|
} else {
|
||||||
SAML2 saml2 = applicationProperties.getSecurity().getSaml2();
|
SAML2 saml2 = applicationProperties.getSecurity().getSaml2();
|
||||||
log.debug(
|
|
||||||
"Processing SAML2 authentication with autoCreateUser: {}",
|
|
||||||
saml2.getAutoCreateUser());
|
|
||||||
|
|
||||||
if (loginAttemptService.isBlocked(username)) {
|
if (loginAttemptService.isBlocked(username)) {
|
||||||
log.debug("User {} is blocked due to too many login attempts", username);
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
||||||
}
|
}
|
||||||
throw new LockedException(
|
throw new LockedException(
|
||||||
"Your account has been locked due to too many failed login attempts.");
|
"Your account has been locked due to too many failed login attempts.");
|
||||||
}
|
}
|
||||||
|
if (userService.usernameExistsIgnoreCase(username)
|
||||||
boolean userExists = userService.usernameExistsIgnoreCase(username);
|
&& userService.hasPassword(username)
|
||||||
boolean hasPassword = userExists && userService.hasPassword(username);
|
&& !userService.isAuthenticationTypeByUsername(
|
||||||
boolean isSSOUser =
|
username, AuthenticationType.OAUTH2)
|
||||||
userExists
|
&& saml2.getAutoCreateUser()) {
|
||||||
&& userService.isAuthenticationTypeByUsername(
|
|
||||||
username, AuthenticationType.SSO);
|
|
||||||
|
|
||||||
log.debug(
|
|
||||||
"User status - Exists: {}, Has password: {}, Is SSO user: {}",
|
|
||||||
userExists,
|
|
||||||
hasPassword,
|
|
||||||
isSSOUser);
|
|
||||||
|
|
||||||
if (userExists && hasPassword && !isSSOUser && saml2.getAutoCreateUser()) {
|
|
||||||
log.debug(
|
|
||||||
"User {} exists with password but is not SSO user, redirecting to logout",
|
|
||||||
username);
|
|
||||||
response.sendRedirect(
|
response.sendRedirect(
|
||||||
contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (saml2.getBlockRegistration() && !userExists) {
|
if (saml2.getBlockRegistration()
|
||||||
log.debug("Registration blocked for new user: {}", username);
|
&& !userService.usernameExistsIgnoreCase(username)) {
|
||||||
response.sendRedirect(
|
response.sendRedirect(
|
||||||
contextPath + "/login?erroroauth=oauth2_admin_blocked_user");
|
contextPath + "/login?erroroauth=oauth2_admin_blocked_user");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.debug("Processing SSO post-login for user: {}", username);
|
userService.processOAuth2PostLogin(username, saml2.getAutoCreateUser());
|
||||||
userService.processSSOPostLogin(username, saml2.getAutoCreateUser());
|
|
||||||
log.debug("Successfully processed authentication for user: {}", username);
|
|
||||||
response.sendRedirect(contextPath + "/");
|
response.sendRedirect(contextPath + "/");
|
||||||
return;
|
return;
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
log.debug(
|
|
||||||
"Invalid username detected for user: {}, redirecting to logout",
|
|
||||||
username);
|
|
||||||
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
|
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug("Non-SAML2 principal detected, delegating to parent handler");
|
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package stirling.software.SPDF.config.security.saml2;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.opensaml.core.xml.XMLObject;
|
import org.opensaml.core.xml.XMLObject;
|
||||||
|
import org.opensaml.core.xml.schema.XSBoolean;
|
||||||
|
import org.opensaml.core.xml.schema.XSString;
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
import org.opensaml.saml.saml2.core.Attribute;
|
import org.opensaml.saml.saml2.core.Attribute;
|
||||||
import org.opensaml.saml.saml2.core.AttributeStatement;
|
import org.opensaml.saml.saml2.core.AttributeStatement;
|
||||||
@@ -28,60 +30,15 @@ public class CustomSaml2ResponseAuthenticationConverter
|
|||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<Object>> extractAttributes(Assertion assertion) {
|
|
||||||
Map<String, List<Object>> attributes = new HashMap<>();
|
|
||||||
|
|
||||||
for (AttributeStatement attributeStatement : assertion.getAttributeStatements()) {
|
|
||||||
for (Attribute attribute : attributeStatement.getAttributes()) {
|
|
||||||
String attributeName = attribute.getName();
|
|
||||||
List<Object> values = new ArrayList<>();
|
|
||||||
|
|
||||||
for (XMLObject xmlObject : attribute.getAttributeValues()) {
|
|
||||||
// Get the text content directly
|
|
||||||
String value = xmlObject.getDOM().getTextContent();
|
|
||||||
if (value != null && !value.trim().isEmpty()) {
|
|
||||||
values.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!values.isEmpty()) {
|
|
||||||
// Store with both full URI and last part of the URI
|
|
||||||
attributes.put(attributeName, values);
|
|
||||||
String shortName = attributeName.substring(attributeName.lastIndexOf('/') + 1);
|
|
||||||
attributes.put(shortName, values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Saml2Authentication convert(ResponseToken responseToken) {
|
public Saml2Authentication convert(ResponseToken responseToken) {
|
||||||
|
// Extract the assertion from the response
|
||||||
Assertion assertion = responseToken.getResponse().getAssertions().get(0);
|
Assertion assertion = responseToken.getResponse().getAssertions().get(0);
|
||||||
Map<String, List<Object>> attributes = extractAttributes(assertion);
|
|
||||||
|
|
||||||
// Debug log with actual values
|
// Extract the NameID
|
||||||
log.debug("Extracted SAML Attributes: " + attributes);
|
String nameId = assertion.getSubject().getNameID().getValue();
|
||||||
|
|
||||||
// Try to get username/identifier in order of preference
|
Optional<User> userOpt = userService.findByUsernameIgnoreCase(nameId);
|
||||||
String userIdentifier = null;
|
|
||||||
if (hasAttribute(attributes, "username")) {
|
|
||||||
userIdentifier = getFirstAttributeValue(attributes, "username");
|
|
||||||
} else if (hasAttribute(attributes, "emailaddress")) {
|
|
||||||
userIdentifier = getFirstAttributeValue(attributes, "emailaddress");
|
|
||||||
} else if (hasAttribute(attributes, "name")) {
|
|
||||||
userIdentifier = getFirstAttributeValue(attributes, "name");
|
|
||||||
} else if (hasAttribute(attributes, "upn")) {
|
|
||||||
userIdentifier = getFirstAttributeValue(attributes, "upn");
|
|
||||||
} else if (hasAttribute(attributes, "uid")) {
|
|
||||||
userIdentifier = getFirstAttributeValue(attributes, "uid");
|
|
||||||
} else {
|
|
||||||
userIdentifier = assertion.getSubject().getNameID().getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rest of your existing code...
|
|
||||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(userIdentifier);
|
|
||||||
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
|
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
|
||||||
if (userOpt.isPresent()) {
|
if (userOpt.isPresent()) {
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
@@ -91,27 +48,39 @@ public class CustomSaml2ResponseAuthenticationConverter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract the SessionIndexes
|
||||||
List<String> sessionIndexes = new ArrayList<>();
|
List<String> sessionIndexes = new ArrayList<>();
|
||||||
for (AuthnStatement authnStatement : assertion.getAuthnStatements()) {
|
for (AuthnStatement authnStatement : assertion.getAuthnStatements()) {
|
||||||
sessionIndexes.add(authnStatement.getSessionIndex());
|
sessionIndexes.add(authnStatement.getSessionIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomSaml2AuthenticatedPrincipal principal =
|
// Extract the Attributes
|
||||||
new CustomSaml2AuthenticatedPrincipal(
|
Map<String, List<Object>> attributes = extractAttributes(assertion);
|
||||||
userIdentifier, attributes, userIdentifier, sessionIndexes);
|
|
||||||
|
|
||||||
|
// Create the custom principal
|
||||||
|
CustomSaml2AuthenticatedPrincipal principal =
|
||||||
|
new CustomSaml2AuthenticatedPrincipal(nameId, attributes, nameId, sessionIndexes);
|
||||||
|
|
||||||
|
// Create the Saml2Authentication
|
||||||
return new Saml2Authentication(
|
return new Saml2Authentication(
|
||||||
principal,
|
principal,
|
||||||
responseToken.getToken().getSaml2Response(),
|
responseToken.getToken().getSaml2Response(),
|
||||||
Collections.singletonList(simpleGrantedAuthority));
|
Collections.singletonList(simpleGrantedAuthority));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasAttribute(Map<String, List<Object>> attributes, String name) {
|
private Map<String, List<Object>> extractAttributes(Assertion assertion) {
|
||||||
return attributes.containsKey(name) && !attributes.get(name).isEmpty();
|
Map<String, List<Object>> attributes = new HashMap<>();
|
||||||
|
for (AttributeStatement attributeStatement : assertion.getAttributeStatements()) {
|
||||||
|
for (Attribute attribute : attributeStatement.getAttributes()) {
|
||||||
|
String attributeName = attribute.getName();
|
||||||
|
List<Object> values = new ArrayList<>();
|
||||||
|
for (XMLObject xmlObject : attribute.getAttributeValues()) {
|
||||||
|
log.info("BOOL: " + ((XSBoolean) xmlObject).getValue());
|
||||||
|
values.add(((XSString) xmlObject).getValue());
|
||||||
}
|
}
|
||||||
|
attributes.put(attributeName, values);
|
||||||
private String getFirstAttributeValue(Map<String, List<Object>> attributes, String name) {
|
}
|
||||||
List<Object> values = attributes.get(name);
|
}
|
||||||
return values != null && !values.isEmpty() ? values.get(0).toString() : null;
|
return attributes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,18 +52,11 @@ public class SplitPDFController {
|
|||||||
"This endpoint splits a given PDF file into separate documents based on the specified page numbers or ranges. Users can specify pages using individual numbers, ranges, or 'all' for every page. Input:PDF Output:PDF Type:SIMO")
|
"This endpoint splits a given PDF file into separate documents based on the specified page numbers or ranges. Users can specify pages using individual numbers, ranges, or 'all' for every page. Input:PDF Output:PDF Type:SIMO")
|
||||||
public ResponseEntity<byte[]> splitPdf(@ModelAttribute PDFWithPageNums request)
|
public ResponseEntity<byte[]> splitPdf(@ModelAttribute PDFWithPageNums request)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
PDDocument document = null;
|
|
||||||
Path zipFile = null;
|
|
||||||
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
MultipartFile file = request.getFileInput();
|
MultipartFile file = request.getFileInput();
|
||||||
String pages = request.getPageNumbers();
|
String pages = request.getPageNumbers();
|
||||||
// open the pdf document
|
// open the pdf document
|
||||||
|
|
||||||
document = Loader.loadPDF(file.getBytes());
|
PDDocument document = Loader.loadPDF(file.getBytes());
|
||||||
// PdfMetadata metadata = PdfMetadataService.extractMetadataFromPdf(document);
|
// PdfMetadata metadata = PdfMetadataService.extractMetadataFromPdf(document);
|
||||||
int totalPages = document.getNumberOfPages();
|
int totalPages = document.getNumberOfPages();
|
||||||
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
|
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
|
||||||
@@ -78,7 +71,7 @@ public class SplitPDFController {
|
|||||||
pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
||||||
|
|
||||||
// split the document
|
// split the document
|
||||||
splitDocumentsBoas = new ArrayList<>();
|
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
||||||
int previousPageNumber = 0;
|
int previousPageNumber = 0;
|
||||||
for (int splitPoint : pageNumbers) {
|
for (int splitPoint : pageNumbers) {
|
||||||
try (PDDocument splitDocument =
|
try (PDDocument splitDocument =
|
||||||
@@ -106,7 +99,7 @@ public class SplitPDFController {
|
|||||||
// closing the original document
|
// closing the original document
|
||||||
document.close();
|
document.close();
|
||||||
|
|
||||||
zipFile = Files.createTempFile("split_documents", ".zip");
|
Path zipFile = Files.createTempFile("split_documents", ".zip");
|
||||||
|
|
||||||
String filename =
|
String filename =
|
||||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||||
@@ -131,36 +124,12 @@ public class SplitPDFController {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.info("Successfully created zip file with split documents: {}", zipFile.toString());
|
||||||
"Successfully created zip file with split documents: {}", zipFile.toString());
|
|
||||||
byte[] data = Files.readAllBytes(zipFile);
|
byte[] data = Files.readAllBytes(zipFile);
|
||||||
Files.deleteIfExists(zipFile);
|
Files.deleteIfExists(zipFile);
|
||||||
|
|
||||||
// return the Resource in the response
|
// return the Resource in the response
|
||||||
return WebResponseUtils.bytesToWebResponse(
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||||
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
// Close the main document
|
|
||||||
if (document != null) {
|
|
||||||
document.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all ByteArrayOutputStreams
|
|
||||||
for (ByteArrayOutputStream baos : splitDocumentsBoas) {
|
|
||||||
if (baos != null) {
|
|
||||||
baos.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete temporary zip file
|
|
||||||
if (zipFile != null) {
|
|
||||||
Files.deleteIfExists(zipFile);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error while cleaning up resources", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,17 +59,13 @@ public class SplitPdfByChaptersController {
|
|||||||
public ResponseEntity<byte[]> splitPdf(@ModelAttribute SplitPdfByChaptersRequest request)
|
public ResponseEntity<byte[]> splitPdf(@ModelAttribute SplitPdfByChaptersRequest request)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
MultipartFile file = request.getFileInput();
|
MultipartFile file = request.getFileInput();
|
||||||
PDDocument sourceDocument = null;
|
|
||||||
Path zipFile = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
boolean includeMetadata = request.getIncludeMetadata();
|
boolean includeMetadata = request.getIncludeMetadata();
|
||||||
Integer bookmarkLevel =
|
Integer bookmarkLevel =
|
||||||
request.getBookmarkLevel(); // levels start from 0 (top most bookmarks)
|
request.getBookmarkLevel(); // levels start from 0 (top most bookmarks)
|
||||||
if (bookmarkLevel < 0) {
|
if (bookmarkLevel < 0) {
|
||||||
return ResponseEntity.badRequest().body("Invalid bookmark level".getBytes());
|
return ResponseEntity.badRequest().body("Invalid bookmark level".getBytes());
|
||||||
}
|
}
|
||||||
sourceDocument = Loader.loadPDF(file.getBytes());
|
PDDocument sourceDocument = Loader.loadPDF(file.getBytes());
|
||||||
|
|
||||||
PDDocumentOutline outline = sourceDocument.getDocumentCatalog().getDocumentOutline();
|
PDDocumentOutline outline = sourceDocument.getDocumentCatalog().getDocumentOutline();
|
||||||
|
|
||||||
@@ -116,7 +112,7 @@ public class SplitPdfByChaptersController {
|
|||||||
List<ByteArrayOutputStream> splitDocumentsBoas =
|
List<ByteArrayOutputStream> splitDocumentsBoas =
|
||||||
getSplitDocumentsBoas(sourceDocument, bookmarks, includeMetadata);
|
getSplitDocumentsBoas(sourceDocument, bookmarks, includeMetadata);
|
||||||
|
|
||||||
zipFile = createZipFile(bookmarks, splitDocumentsBoas);
|
Path zipFile = createZipFile(bookmarks, splitDocumentsBoas);
|
||||||
|
|
||||||
byte[] data = Files.readAllBytes(zipFile);
|
byte[] data = Files.readAllBytes(zipFile);
|
||||||
Files.deleteIfExists(zipFile);
|
Files.deleteIfExists(zipFile);
|
||||||
@@ -127,18 +123,6 @@ public class SplitPdfByChaptersController {
|
|||||||
sourceDocument.close();
|
sourceDocument.close();
|
||||||
return WebResponseUtils.bytesToWebResponse(
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (sourceDocument != null) {
|
|
||||||
sourceDocument.close();
|
|
||||||
}
|
|
||||||
if (zipFile != null) {
|
|
||||||
Files.deleteIfExists(zipFile);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error while cleaning up resources", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Bookmark> mergeBookmarksThatCorrespondToSamePage(List<Bookmark> bookmarks) {
|
private List<Bookmark> mergeBookmarksThatCorrespondToSamePage(List<Bookmark> bookmarks) {
|
||||||
|
|||||||
@@ -105,13 +105,15 @@ public class SplitPdfBySectionsController {
|
|||||||
|
|
||||||
if (sectionNum == horiz * verti) pageNum++;
|
if (sectionNum == horiz * verti) pageNum++;
|
||||||
}
|
}
|
||||||
data = Files.readAllBytes(zipFile);
|
} catch (Exception e) {
|
||||||
return WebResponseUtils.bytesToWebResponse(
|
logger.error("exception", e);
|
||||||
data, filename + "_split.zip", MediaType.APPLICATION_OCTET_STREAM);
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
data = Files.readAllBytes(zipFile);
|
||||||
Files.deleteIfExists(zipFile);
|
Files.deleteIfExists(zipFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
|
data, filename + "_split.zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PDDocument> splitPdfPages(
|
public List<PDDocument> splitPdfPages(
|
||||||
|
|||||||
@@ -244,8 +244,8 @@ public class UserController {
|
|||||||
return new RedirectView("/addUsers?messageType=invalidRole", true);
|
return new RedirectView("/addUsers?messageType=invalidRole", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authType.equalsIgnoreCase(AuthenticationType.SSO.toString())) {
|
if (authType.equalsIgnoreCase(AuthenticationType.OAUTH2.toString())) {
|
||||||
userService.saveUser(username, AuthenticationType.SSO, role);
|
userService.saveUser(username, AuthenticationType.OAUTH2, role);
|
||||||
} else {
|
} else {
|
||||||
if (password.isBlank()) {
|
if (password.isBlank()) {
|
||||||
return new RedirectView("/addUsers?messageType=invalidPassword", true);
|
return new RedirectView("/addUsers?messageType=invalidPassword", true);
|
||||||
|
|||||||
@@ -65,12 +65,6 @@ public class ConvertImgPDFController {
|
|||||||
String colorType = request.getColorType();
|
String colorType = request.getColorType();
|
||||||
String dpi = request.getDpi();
|
String dpi = request.getDpi();
|
||||||
|
|
||||||
Path tempFile = null;
|
|
||||||
Path tempOutputDir = null;
|
|
||||||
Path tempPdfPath = null;
|
|
||||||
byte[] result = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
byte[] pdfBytes = file.getBytes();
|
byte[] pdfBytes = file.getBytes();
|
||||||
ImageType colorTypeResult = ImageType.RGB;
|
ImageType colorTypeResult = ImageType.RGB;
|
||||||
if ("greyscale".equals(colorType)) {
|
if ("greyscale".equals(colorType)) {
|
||||||
@@ -80,6 +74,7 @@ public class ConvertImgPDFController {
|
|||||||
}
|
}
|
||||||
// returns bytes for image
|
// returns bytes for image
|
||||||
boolean singleImage = "single".equals(singleOrMultiple);
|
boolean singleImage = "single".equals(singleOrMultiple);
|
||||||
|
byte[] result = null;
|
||||||
String filename =
|
String filename =
|
||||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||||
.replaceFirst("[.][^.]+$", "");
|
.replaceFirst("[.][^.]+$", "");
|
||||||
@@ -87,9 +82,7 @@ public class ConvertImgPDFController {
|
|||||||
result =
|
result =
|
||||||
PdfUtils.convertFromPdf(
|
PdfUtils.convertFromPdf(
|
||||||
pdfBytes,
|
pdfBytes,
|
||||||
"webp".equalsIgnoreCase(imageFormat)
|
"webp".equalsIgnoreCase(imageFormat) ? "png" : imageFormat.toUpperCase(),
|
||||||
? "png"
|
|
||||||
: imageFormat.toUpperCase(),
|
|
||||||
colorTypeResult,
|
colorTypeResult,
|
||||||
singleImage,
|
singleImage,
|
||||||
Integer.valueOf(dpi),
|
Integer.valueOf(dpi),
|
||||||
@@ -102,7 +95,7 @@ public class ConvertImgPDFController {
|
|||||||
} else if ("webp".equalsIgnoreCase(imageFormat)
|
} else if ("webp".equalsIgnoreCase(imageFormat)
|
||||||
&& CheckProgramInstall.isPythonAvailable()) {
|
&& CheckProgramInstall.isPythonAvailable()) {
|
||||||
// Write the output stream to a temp file
|
// Write the output stream to a temp file
|
||||||
tempFile = Files.createTempFile("temp_png", ".png");
|
Path tempFile = Files.createTempFile("temp_png", ".png");
|
||||||
try (FileOutputStream fos = new FileOutputStream(tempFile.toFile())) {
|
try (FileOutputStream fos = new FileOutputStream(tempFile.toFile())) {
|
||||||
fos.write(result);
|
fos.write(result);
|
||||||
fos.flush();
|
fos.flush();
|
||||||
@@ -115,7 +108,7 @@ public class ConvertImgPDFController {
|
|||||||
command.add("./scripts/png_to_webp.py"); // Python script to handle the conversion
|
command.add("./scripts/png_to_webp.py"); // Python script to handle the conversion
|
||||||
|
|
||||||
// Create a temporary directory for the output WebP files
|
// Create a temporary directory for the output WebP files
|
||||||
tempOutputDir = Files.createTempDirectory("webp_output");
|
Path tempOutputDir = Files.createTempDirectory("webp_output");
|
||||||
if (singleImage) {
|
if (singleImage) {
|
||||||
// Run the Python script to convert PNG to WebP
|
// Run the Python script to convert PNG to WebP
|
||||||
command.add(tempFile.toString());
|
command.add(tempFile.toString());
|
||||||
@@ -123,7 +116,7 @@ public class ConvertImgPDFController {
|
|||||||
command.add("--single");
|
command.add("--single");
|
||||||
} else {
|
} else {
|
||||||
// Save the uploaded PDF to a temporary file
|
// Save the uploaded PDF to a temporary file
|
||||||
tempPdfPath = Files.createTempFile("temp_pdf", ".pdf");
|
Path tempPdfPath = Files.createTempFile("temp_pdf", ".pdf");
|
||||||
file.transferTo(tempPdfPath.toFile());
|
file.transferTo(tempPdfPath.toFile());
|
||||||
// Run the Python script to convert PDF to WebP
|
// Run the Python script to convert PDF to WebP
|
||||||
command.add(tempPdfPath.toString());
|
command.add(tempPdfPath.toString());
|
||||||
@@ -143,8 +136,7 @@ public class ConvertImgPDFController {
|
|||||||
|
|
||||||
if (webpFiles.isEmpty()) {
|
if (webpFiles.isEmpty()) {
|
||||||
logger.error("No WebP files were created in: {}", tempOutputDir.toString());
|
logger.error("No WebP files were created in: {}", tempOutputDir.toString());
|
||||||
throw new IOException(
|
throw new IOException("No WebP files were created. " + resultProcess.getMessages());
|
||||||
"No WebP files were created. " + resultProcess.getMessages());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] bodyBytes = new byte[0];
|
byte[] bodyBytes = new byte[0];
|
||||||
@@ -180,23 +172,6 @@ public class ConvertImgPDFController {
|
|||||||
return WebResponseUtils.bytesToWebResponse(
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
result, zipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
result, zipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
// Clean up temporary files
|
|
||||||
if (tempFile != null) {
|
|
||||||
Files.deleteIfExists(tempFile);
|
|
||||||
}
|
|
||||||
if (tempPdfPath != null) {
|
|
||||||
Files.deleteIfExists(tempPdfPath);
|
|
||||||
}
|
|
||||||
if (tempOutputDir != null) {
|
|
||||||
FileUtils.deleteDirectory(tempOutputDir.toFile());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error cleaning up temporary files", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/img/pdf")
|
@PostMapping(consumes = "multipart/form-data", value = "/img/pdf")
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
|
||||||
import org.springframework.web.bind.annotation.InitBinder;
|
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -28,7 +26,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import stirling.software.SPDF.model.api.misc.MetadataRequest;
|
import stirling.software.SPDF.model.api.misc.MetadataRequest;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
import stirling.software.SPDF.utils.propertyeditor.StringToMapPropertyEditor;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/misc")
|
@RequestMapping("/api/v1/misc")
|
||||||
@@ -47,11 +44,6 @@ public class MetadataController {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@InitBinder
|
|
||||||
public void initBinder(WebDataBinder binder) {
|
|
||||||
binder.registerCustomEditor(Map.class, "allRequestParams", new StringToMapPropertyEditor());
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/update-metadata")
|
@PostMapping(consumes = "multipart/form-data", value = "/update-metadata")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Update metadata of a PDF file",
|
summary = "Update metadata of a PDF file",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
|
import io.github.pixee.security.BoundedLineReader;
|
||||||
|
import io.github.pixee.security.Filenames;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -33,8 +35,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import io.github.pixee.security.BoundedLineReader;
|
|
||||||
import io.github.pixee.security.Filenames;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -87,7 +87,7 @@ public class OCRController {
|
|||||||
|
|
||||||
Files.createDirectories(tempOutputDir);
|
Files.createDirectories(tempOutputDir);
|
||||||
Files.createDirectories(tempImagesDir);
|
Files.createDirectories(tempImagesDir);
|
||||||
Process process = null;
|
|
||||||
try {
|
try {
|
||||||
// Save input file
|
// Save input file
|
||||||
inputFile.transferTo(tempInputFile.toFile());
|
inputFile.transferTo(tempInputFile.toFile());
|
||||||
@@ -139,7 +139,7 @@ public class OCRController {
|
|||||||
command.add("pdf"); // Always output PDF
|
command.add("pdf"); // Always output PDF
|
||||||
|
|
||||||
ProcessBuilder pb = new ProcessBuilder(command);
|
ProcessBuilder pb = new ProcessBuilder(command);
|
||||||
process = pb.start();
|
Process process = pb.start();
|
||||||
|
|
||||||
// Capture any error output
|
// Capture any error output
|
||||||
try (BufferedReader reader =
|
try (BufferedReader reader =
|
||||||
@@ -176,9 +176,7 @@ public class OCRController {
|
|||||||
// Read the final PDF file
|
// Read the final PDF file
|
||||||
byte[] pdfContent = Files.readAllBytes(finalOutputFile);
|
byte[] pdfContent = Files.readAllBytes(finalOutputFile);
|
||||||
String outputFilename =
|
String outputFilename =
|
||||||
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
|
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_OCR.pdf";
|
||||||
.replaceFirst("[.][^.]+$", "")
|
|
||||||
+ "_OCR.pdf";
|
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.header(
|
.header(
|
||||||
@@ -188,10 +186,6 @@ public class OCRController {
|
|||||||
.body(pdfContent);
|
.body(pdfContent);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (process != null) {
|
|
||||||
process.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up temporary files
|
// Clean up temporary files
|
||||||
deleteDirectory(tempDir);
|
deleteDirectory(tempDir);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class RepairController {
|
|||||||
MultipartFile inputFile = request.getFileInput();
|
MultipartFile inputFile = request.getFileInput();
|
||||||
// Save the uploaded file to a temporary location
|
// Save the uploaded file to a temporary location
|
||||||
Path tempInputFile = Files.createTempFile("input_", ".pdf");
|
Path tempInputFile = Files.createTempFile("input_", ".pdf");
|
||||||
|
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||||
byte[] pdfBytes = null;
|
byte[] pdfBytes = null;
|
||||||
inputFile.transferTo(tempInputFile.toFile());
|
inputFile.transferTo(tempInputFile.toFile());
|
||||||
try {
|
try {
|
||||||
@@ -60,13 +61,14 @@ public class RepairController {
|
|||||||
command.add("--qdf"); // Linearizes and normalizes PDF structure
|
command.add("--qdf"); // Linearizes and normalizes PDF structure
|
||||||
command.add("--object-streams=disable"); // Can help with some corruptions
|
command.add("--object-streams=disable"); // Can help with some corruptions
|
||||||
command.add(tempInputFile.toString());
|
command.add(tempInputFile.toString());
|
||||||
|
command.add(tempOutputFile.toString());
|
||||||
|
|
||||||
ProcessExecutorResult returnCode =
|
ProcessExecutorResult returnCode =
|
||||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
|
ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
|
||||||
.runCommandWithOutputHandling(command);
|
.runCommandWithOutputHandling(command);
|
||||||
|
|
||||||
// Read the optimized PDF file
|
// Read the optimized PDF file
|
||||||
pdfBytes = pdfDocumentFactory.loadToBytes(tempInputFile.toFile());
|
pdfBytes = pdfDocumentFactory.loadToBytes(tempOutputFile.toFile());
|
||||||
|
|
||||||
// Return the optimized PDF as a response
|
// Return the optimized PDF as a response
|
||||||
String outputFilename =
|
String outputFilename =
|
||||||
@@ -77,6 +79,7 @@ public class RepairController {
|
|||||||
} finally {
|
} finally {
|
||||||
// Clean up the temporary files
|
// Clean up the temporary files
|
||||||
Files.deleteIfExists(tempInputFile);
|
Files.deleteIfExists(tempInputFile);
|
||||||
|
Files.deleteIfExists(tempOutputFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,22 +229,10 @@ public class StampController {
|
|||||||
calculatePositionY(
|
calculatePositionY(
|
||||||
pageSize, position, calculateTextCapHeight(font, fontSize), margin);
|
pageSize, position, calculateTextCapHeight(font, fontSize), margin);
|
||||||
}
|
}
|
||||||
// Split the stampText into multiple lines
|
|
||||||
String[] lines = stampText.split("\\\\n");
|
|
||||||
|
|
||||||
// Calculate dynamic line height based on font ascent and descent
|
|
||||||
float ascent = font.getFontDescriptor().getAscent();
|
|
||||||
float descent = font.getFontDescriptor().getDescent();
|
|
||||||
float lineHeight = ((ascent - descent) / 1000) * fontSize;
|
|
||||||
|
|
||||||
contentStream.beginText();
|
contentStream.beginText();
|
||||||
for (int i = 0; i < lines.length; i++) {
|
contentStream.setTextMatrix(Matrix.getRotateInstance(Math.toRadians(rotation), x, y));
|
||||||
String line = lines[i];
|
contentStream.showText(stampText);
|
||||||
// Set the text matrix for each line with rotation
|
|
||||||
contentStream.setTextMatrix(
|
|
||||||
Matrix.getRotateInstance(Math.toRadians(rotation), x, y - (i * lineHeight)));
|
|
||||||
contentStream.showText(line);
|
|
||||||
}
|
|
||||||
contentStream.endText();
|
contentStream.endText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ public class PipelineProcessor {
|
|||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
String apiKey = getApiKeyForUser();
|
String apiKey = getApiKeyForUser();
|
||||||
headers.add("X-API-KEY", apiKey);
|
headers.add("X-API-Key", apiKey);
|
||||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||||
|
|
||||||
// Create HttpEntity with the body and headers
|
// Create HttpEntity with the body and headers
|
||||||
|
|||||||
@@ -322,14 +322,27 @@ public class GetInfoOnPDF {
|
|||||||
PDEncryption pdfEncryption = pdfBoxDoc.getEncryption();
|
PDEncryption pdfEncryption = pdfBoxDoc.getEncryption();
|
||||||
encryption.put("EncryptionAlgorithm", pdfEncryption.getFilter());
|
encryption.put("EncryptionAlgorithm", pdfEncryption.getFilter());
|
||||||
encryption.put("KeyLength", pdfEncryption.getLength());
|
encryption.put("KeyLength", pdfEncryption.getLength());
|
||||||
|
AccessPermission ap = pdfBoxDoc.getCurrentAccessPermission();
|
||||||
|
if (ap != null) {
|
||||||
|
ObjectNode permissionsNode = objectMapper.createObjectNode();
|
||||||
|
|
||||||
|
permissionsNode.put("CanAssembleDocument", ap.canAssembleDocument());
|
||||||
|
permissionsNode.put("CanExtractContent", ap.canExtractContent());
|
||||||
|
permissionsNode.put(
|
||||||
|
"CanExtractForAccessibility", ap.canExtractForAccessibility());
|
||||||
|
permissionsNode.put("CanFillInForm", ap.canFillInForm());
|
||||||
|
permissionsNode.put("CanModify", ap.canModify());
|
||||||
|
permissionsNode.put("CanModifyAnnotations", ap.canModifyAnnotations());
|
||||||
|
permissionsNode.put("CanPrint", ap.canPrint());
|
||||||
|
|
||||||
|
encryption.set(
|
||||||
|
"Permissions", permissionsNode); // set the node under "Permissions"
|
||||||
|
}
|
||||||
// Add other encryption-related properties as needed
|
// Add other encryption-related properties as needed
|
||||||
} else {
|
} else {
|
||||||
encryption.put("IsEncrypted", false);
|
encryption.put("IsEncrypted", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectNode permissionsNode = objectMapper.createObjectNode();
|
|
||||||
setNodePermissions(pdfBoxDoc, permissionsNode);
|
|
||||||
|
|
||||||
ObjectNode pageInfoParent = objectMapper.createObjectNode();
|
ObjectNode pageInfoParent = objectMapper.createObjectNode();
|
||||||
for (int pageNum = 0; pageNum < pdfBoxDoc.getNumberOfPages(); pageNum++) {
|
for (int pageNum = 0; pageNum < pdfBoxDoc.getNumberOfPages(); pageNum++) {
|
||||||
ObjectNode pageInfo = objectMapper.createObjectNode();
|
ObjectNode pageInfo = objectMapper.createObjectNode();
|
||||||
@@ -571,7 +584,6 @@ public class GetInfoOnPDF {
|
|||||||
jsonOutput.set("DocumentInfo", docInfoNode);
|
jsonOutput.set("DocumentInfo", docInfoNode);
|
||||||
jsonOutput.set("Compliancy", compliancy);
|
jsonOutput.set("Compliancy", compliancy);
|
||||||
jsonOutput.set("Encryption", encryption);
|
jsonOutput.set("Encryption", encryption);
|
||||||
jsonOutput.set("Permissions", permissionsNode); // set the node under "Permissions"
|
|
||||||
jsonOutput.set("Other", other);
|
jsonOutput.set("Other", other);
|
||||||
jsonOutput.set("PerPageInfo", pageInfoParent);
|
jsonOutput.set("PerPageInfo", pageInfoParent);
|
||||||
|
|
||||||
@@ -590,24 +602,6 @@ public class GetInfoOnPDF {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setNodePermissions(PDDocument pdfBoxDoc, ObjectNode permissionsNode) {
|
|
||||||
AccessPermission ap = pdfBoxDoc.getCurrentAccessPermission();
|
|
||||||
|
|
||||||
permissionsNode.put("Document Assembly", getPermissionState(ap.canAssembleDocument()));
|
|
||||||
permissionsNode.put("Extracting Content", getPermissionState(ap.canExtractContent()));
|
|
||||||
permissionsNode.put(
|
|
||||||
"Extracting for accessibility",
|
|
||||||
getPermissionState(ap.canExtractForAccessibility()));
|
|
||||||
permissionsNode.put("Form Filling", getPermissionState(ap.canFillInForm()));
|
|
||||||
permissionsNode.put("Modifying", getPermissionState(ap.canModify()));
|
|
||||||
permissionsNode.put("Modifying annotations", getPermissionState(ap.canModifyAnnotations()));
|
|
||||||
permissionsNode.put("Printing", getPermissionState(ap.canPrint()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getPermissionState(boolean state) {
|
|
||||||
return state ? "Allowed" : "Not Allowed";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addOutlinesToArray(PDOutlineItem outline, ArrayNode arrayNode) {
|
private static void addOutlinesToArray(PDOutlineItem outline, ArrayNode arrayNode) {
|
||||||
if (outline == null) return;
|
if (outline == null) return;
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,10 @@ public class PasswordController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-password")
|
@PostMapping(consumes = "multipart/form-data", value = "/remove-password")
|
||||||
@Operation(summary = "Remove password from a PDF file", description = "This endpoint removes the password from a protected PDF file. Users need to provide the existing password. Input:PDF Output:PDF Type:SISO")
|
@Operation(
|
||||||
|
summary = "Remove password from a PDF file",
|
||||||
|
description =
|
||||||
|
"This endpoint removes the password from a protected PDF file. Users need to provide the existing password. Input:PDF Output:PDF Type:SISO")
|
||||||
public ResponseEntity<byte[]> removePassword(@ModelAttribute PDFPasswordRequest request)
|
public ResponseEntity<byte[]> removePassword(@ModelAttribute PDFPasswordRequest request)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
MultipartFile fileInput = request.getFileInput();
|
MultipartFile fileInput = request.getFileInput();
|
||||||
@@ -54,7 +57,10 @@ public class PasswordController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/add-password")
|
@PostMapping(consumes = "multipart/form-data", value = "/add-password")
|
||||||
@Operation(summary = "Add password to a PDF file", description = "This endpoint adds password protection to a PDF file. Users can specify a set of permissions that should be applied to the file. Input:PDF Output:PDF")
|
@Operation(
|
||||||
|
summary = "Add password to a PDF file",
|
||||||
|
description =
|
||||||
|
"This endpoint adds password protection to a PDF file. Users can specify a set of permissions that should be applied to the file. Input:PDF Output:PDF")
|
||||||
public ResponseEntity<byte[]> addPassword(@ModelAttribute AddPasswordRequest request)
|
public ResponseEntity<byte[]> addPassword(@ModelAttribute AddPasswordRequest request)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
MultipartFile fileInput = request.getFileInput();
|
MultipartFile fileInput = request.getFileInput();
|
||||||
|
|||||||
@@ -1,180 +0,0 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.interfaces.RSAPublicKey;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder;
|
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
|
||||||
import org.bouncycastle.cms.CMSProcessable;
|
|
||||||
import org.bouncycastle.cms.CMSProcessableByteArray;
|
|
||||||
import org.bouncycastle.cms.CMSSignedData;
|
|
||||||
import org.bouncycastle.cms.SignerInformation;
|
|
||||||
import org.bouncycastle.cms.SignerInformationStore;
|
|
||||||
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
|
|
||||||
import org.bouncycastle.util.Store;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
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.security.SignatureValidationRequest;
|
|
||||||
import stirling.software.SPDF.model.api.security.SignatureValidationResult;
|
|
||||||
import stirling.software.SPDF.service.CertificateValidationService;
|
|
||||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/security")
|
|
||||||
@Tag(name = "Security", description = "Security APIs")
|
|
||||||
public class ValidateSignatureController {
|
|
||||||
|
|
||||||
private final CustomPDDocumentFactory pdfDocumentFactory;
|
|
||||||
private final CertificateValidationService certValidationService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ValidateSignatureController(
|
|
||||||
CustomPDDocumentFactory pdfDocumentFactory,
|
|
||||||
CertificateValidationService certValidationService) {
|
|
||||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
|
||||||
this.certValidationService = certValidationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(
|
|
||||||
summary = "Validate PDF Digital Signature",
|
|
||||||
description =
|
|
||||||
"Validates the digital signatures in a PDF file against default or custom certificates. Input:PDF Output:JSON Type:SISO")
|
|
||||||
@PostMapping(value = "/validate-signature")
|
|
||||||
public ResponseEntity<List<SignatureValidationResult>> validateSignature(
|
|
||||||
@ModelAttribute SignatureValidationRequest request) throws IOException {
|
|
||||||
List<SignatureValidationResult> results = new ArrayList<>();
|
|
||||||
MultipartFile file = request.getFileInput();
|
|
||||||
|
|
||||||
// Load custom certificate if provided
|
|
||||||
X509Certificate customCert = null;
|
|
||||||
if (request.getCertFile() != null && !request.getCertFile().isEmpty()) {
|
|
||||||
try (ByteArrayInputStream certStream =
|
|
||||||
new ByteArrayInputStream(request.getCertFile().getBytes())) {
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
customCert = (X509Certificate) cf.generateCertificate(certStream);
|
|
||||||
} catch (CertificateException e) {
|
|
||||||
throw new RuntimeException("Invalid certificate file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try (PDDocument document = pdfDocumentFactory.load(file.getInputStream())) {
|
|
||||||
List<PDSignature> signatures = document.getSignatureDictionaries();
|
|
||||||
|
|
||||||
for (PDSignature sig : signatures) {
|
|
||||||
SignatureValidationResult result = new SignatureValidationResult();
|
|
||||||
|
|
||||||
try {
|
|
||||||
byte[] signedContent = sig.getSignedContent(file.getInputStream());
|
|
||||||
byte[] signatureBytes = sig.getContents(file.getInputStream());
|
|
||||||
|
|
||||||
CMSProcessable content = new CMSProcessableByteArray(signedContent);
|
|
||||||
CMSSignedData signedData = new CMSSignedData(content, signatureBytes);
|
|
||||||
|
|
||||||
Store<X509CertificateHolder> certStore = signedData.getCertificates();
|
|
||||||
SignerInformationStore signerStore = signedData.getSignerInfos();
|
|
||||||
|
|
||||||
for (SignerInformation signer : signerStore.getSigners()) {
|
|
||||||
X509CertificateHolder certHolder =
|
|
||||||
(X509CertificateHolder)
|
|
||||||
certStore.getMatches(signer.getSID()).iterator().next();
|
|
||||||
X509Certificate cert =
|
|
||||||
new JcaX509CertificateConverter().getCertificate(certHolder);
|
|
||||||
|
|
||||||
boolean isValid =
|
|
||||||
signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert));
|
|
||||||
result.setValid(isValid);
|
|
||||||
|
|
||||||
// Additional validations
|
|
||||||
result.setChainValid(
|
|
||||||
customCert != null
|
|
||||||
? certValidationService
|
|
||||||
.validateCertificateChainWithCustomCert(
|
|
||||||
cert, customCert)
|
|
||||||
: certValidationService.validateCertificateChain(cert));
|
|
||||||
|
|
||||||
result.setTrustValid(
|
|
||||||
customCert != null
|
|
||||||
? certValidationService.validateTrustWithCustomCert(
|
|
||||||
cert, customCert)
|
|
||||||
: certValidationService.validateTrustStore(cert));
|
|
||||||
|
|
||||||
result.setNotRevoked(!certValidationService.isRevoked(cert));
|
|
||||||
result.setNotExpired(!cert.getNotAfter().before(new Date()));
|
|
||||||
|
|
||||||
// Set basic signature info
|
|
||||||
result.setSignerName(sig.getName());
|
|
||||||
result.setSignatureDate(sig.getSignDate().getTime().toString());
|
|
||||||
result.setReason(sig.getReason());
|
|
||||||
result.setLocation(sig.getLocation());
|
|
||||||
|
|
||||||
// Set new certificate details
|
|
||||||
result.setIssuerDN(cert.getIssuerX500Principal().getName());
|
|
||||||
result.setSubjectDN(cert.getSubjectX500Principal().getName());
|
|
||||||
result.setSerialNumber(cert.getSerialNumber().toString(16)); // Hex format
|
|
||||||
result.setValidFrom(cert.getNotBefore().toString());
|
|
||||||
result.setValidUntil(cert.getNotAfter().toString());
|
|
||||||
result.setSignatureAlgorithm(cert.getSigAlgName());
|
|
||||||
|
|
||||||
// Get key size (if possible)
|
|
||||||
try {
|
|
||||||
result.setKeySize(
|
|
||||||
((RSAPublicKey) cert.getPublicKey()).getModulus().bitLength());
|
|
||||||
} catch (Exception e) {
|
|
||||||
// If not RSA or error, set to 0
|
|
||||||
result.setKeySize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.setVersion(String.valueOf(cert.getVersion()));
|
|
||||||
|
|
||||||
// Set key usage
|
|
||||||
List<String> keyUsages = new ArrayList<>();
|
|
||||||
boolean[] keyUsageFlags = cert.getKeyUsage();
|
|
||||||
if (keyUsageFlags != null) {
|
|
||||||
String[] keyUsageLabels = {
|
|
||||||
"Digital Signature", "Non-Repudiation", "Key Encipherment",
|
|
||||||
"Data Encipherment", "Key Agreement", "Certificate Signing",
|
|
||||||
"CRL Signing", "Encipher Only", "Decipher Only"
|
|
||||||
};
|
|
||||||
for (int i = 0; i < keyUsageFlags.length; i++) {
|
|
||||||
if (keyUsageFlags[i]) {
|
|
||||||
keyUsages.add(keyUsageLabels[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.setKeyUsages(keyUsages);
|
|
||||||
|
|
||||||
// Check if self-signed
|
|
||||||
result.setSelfSigned(
|
|
||||||
cert.getSubjectX500Principal()
|
|
||||||
.equals(cert.getIssuerX500Principal()));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
result.setValid(false);
|
|
||||||
result.setErrorMessage("Signature validation failed: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResponseEntity.ok(results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -69,7 +69,6 @@ public class WatermarkController {
|
|||||||
float opacity = request.getOpacity();
|
float opacity = request.getOpacity();
|
||||||
int widthSpacer = request.getWidthSpacer();
|
int widthSpacer = request.getWidthSpacer();
|
||||||
int heightSpacer = request.getHeightSpacer();
|
int heightSpacer = request.getHeightSpacer();
|
||||||
String customColor = request.getCustomColor();
|
|
||||||
boolean convertPdfToImage = request.isConvertPDFToImage();
|
boolean convertPdfToImage = request.isConvertPDFToImage();
|
||||||
|
|
||||||
// Load the input PDF
|
// Load the input PDF
|
||||||
@@ -98,8 +97,7 @@ public class WatermarkController {
|
|||||||
widthSpacer,
|
widthSpacer,
|
||||||
heightSpacer,
|
heightSpacer,
|
||||||
fontSize,
|
fontSize,
|
||||||
alphabet,
|
alphabet);
|
||||||
customColor);
|
|
||||||
} else if ("image".equalsIgnoreCase(watermarkType)) {
|
} else if ("image".equalsIgnoreCase(watermarkType)) {
|
||||||
addImageWatermark(
|
addImageWatermark(
|
||||||
contentStream,
|
contentStream,
|
||||||
@@ -138,8 +136,7 @@ public class WatermarkController {
|
|||||||
int widthSpacer,
|
int widthSpacer,
|
||||||
int heightSpacer,
|
int heightSpacer,
|
||||||
float fontSize,
|
float fontSize,
|
||||||
String alphabet,
|
String alphabet)
|
||||||
String colorString)
|
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String resourceDir = "";
|
String resourceDir = "";
|
||||||
PDFont font = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
|
PDFont font = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
|
||||||
@@ -176,18 +173,7 @@ public class WatermarkController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentStream.setFont(font, fontSize);
|
contentStream.setFont(font, fontSize);
|
||||||
|
contentStream.setNonStrokingColor(Color.LIGHT_GRAY);
|
||||||
Color redactColor;
|
|
||||||
try {
|
|
||||||
if (!colorString.startsWith("#")) {
|
|
||||||
colorString = "#" + colorString;
|
|
||||||
}
|
|
||||||
redactColor = Color.decode(colorString);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
|
|
||||||
redactColor = Color.LIGHT_GRAY;
|
|
||||||
}
|
|
||||||
contentStream.setNonStrokingColor(redactColor);
|
|
||||||
|
|
||||||
String[] textLines = watermarkText.split("\\\\n");
|
String[] textLines = watermarkText.split("\\\\n");
|
||||||
float maxLineWidth = 0;
|
float maxLineWidth = 0;
|
||||||
|
|||||||
@@ -53,13 +53,6 @@ public class SecurityWebController {
|
|||||||
return "security/cert-sign";
|
return "security/cert-sign";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/validate-signature")
|
|
||||||
@Hidden
|
|
||||||
public String certSignVerifyForm(Model model) {
|
|
||||||
model.addAttribute("currentPage", "validate-signature");
|
|
||||||
return "security/validate-signature";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/remove-cert-sign")
|
@GetMapping("/remove-cert-sign")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String certUnSignForm(Model model) {
|
public String certUnSignForm(Model model) {
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ public class ApplicationProperties {
|
|||||||
private int loginAttemptCount;
|
private int loginAttemptCount;
|
||||||
private long loginResetTimeMinutes;
|
private long loginResetTimeMinutes;
|
||||||
private String loginMethod = "all";
|
private String loginMethod = "all";
|
||||||
private String customGlobalAPIKey;
|
|
||||||
|
|
||||||
public Boolean isAltLogin() {
|
public Boolean isAltLogin() {
|
||||||
return saml2.getEnabled() || oauth2.getEnabled();
|
return saml2.getEnabled() || oauth2.getEnabled();
|
||||||
@@ -286,7 +285,6 @@ public class ApplicationProperties {
|
|||||||
public static class AutomaticallyGenerated {
|
public static class AutomaticallyGenerated {
|
||||||
@ToString.Exclude private String key;
|
@ToString.Exclude private String key;
|
||||||
private String UUID;
|
private String UUID;
|
||||||
private String appVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ package stirling.software.SPDF.model;
|
|||||||
|
|
||||||
public enum AuthenticationType {
|
public enum AuthenticationType {
|
||||||
WEB,
|
WEB,
|
||||||
SSO
|
OAUTH2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,9 +45,6 @@ public class AddWatermarkRequest extends PDFFile {
|
|||||||
@Schema(description = "The height spacer between watermark elements", example = "50")
|
@Schema(description = "The height spacer between watermark elements", example = "50")
|
||||||
private int heightSpacer;
|
private int heightSpacer;
|
||||||
|
|
||||||
@Schema(description = "The color for watermark", defaultValue = "#d3d3d3")
|
|
||||||
private String customColor = "#d3d3d3";
|
|
||||||
|
|
||||||
@Schema(description = "Convert the redacted PDF to an image", defaultValue = "false")
|
@Schema(description = "Convert the redacted PDF to an image", defaultValue = "false")
|
||||||
private boolean convertPDFToImage;
|
private boolean convertPDFToImage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.security;
|
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
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 SignatureValidationRequest extends PDFFile {
|
|
||||||
|
|
||||||
@Schema(description = "(Optional) file to compare PDF cert signatures against x.509 format")
|
|
||||||
private MultipartFile certFile;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.security;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class SignatureValidationResult {
|
|
||||||
private boolean valid;
|
|
||||||
private String signerName;
|
|
||||||
private String signatureDate;
|
|
||||||
private String reason;
|
|
||||||
private String location;
|
|
||||||
private String errorMessage;
|
|
||||||
private boolean chainValid;
|
|
||||||
private boolean trustValid;
|
|
||||||
private boolean notExpired;
|
|
||||||
private boolean notRevoked;
|
|
||||||
|
|
||||||
private String issuerDN; // Certificate issuer's Distinguished Name
|
|
||||||
private String subjectDN; // Certificate subject's Distinguished Name
|
|
||||||
private String serialNumber; // Certificate serial number
|
|
||||||
private String validFrom; // Certificate validity start date
|
|
||||||
private String validUntil; // Certificate validity end date
|
|
||||||
private String signatureAlgorithm; // Algorithm used for signing
|
|
||||||
private int keySize; // Key size in bits
|
|
||||||
private String version; // Certificate version
|
|
||||||
private List<String> keyUsages; // List of key usage purposes
|
|
||||||
private boolean isSelfSigned; // Whether the certificate is self-signed
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package stirling.software.SPDF.repository;
|
package stirling.software.SPDF.repository;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
@@ -20,6 +19,4 @@ public interface UserRepository extends JpaRepository<User, Long> {
|
|||||||
Optional<User> findByUsername(String username);
|
Optional<User> findByUsername(String username);
|
||||||
|
|
||||||
Optional<User> findByApiKey(String apiKey);
|
Optional<User> findByApiKey(String apiKey);
|
||||||
|
|
||||||
List<User> findByAuthenticationTypeIgnoreCase(String authenticationType);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
package stirling.software.SPDF.service;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.cert.CertPath;
|
|
||||||
import java.security.cert.CertPathValidator;
|
|
||||||
import java.security.cert.CertificateExpiredException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.CertificateNotYetValidException;
|
|
||||||
import java.security.cert.PKIXParameters;
|
|
||||||
import java.security.cert.TrustAnchor;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import io.github.pixee.security.BoundedLineReader;
|
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class CertificateValidationService {
|
|
||||||
private KeyStore trustStore;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
private void initializeTrustStore() throws Exception {
|
|
||||||
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
trustStore.load(null, null);
|
|
||||||
loadMozillaCertificates();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadMozillaCertificates() throws Exception {
|
|
||||||
try (InputStream is = getClass().getResourceAsStream("/certdata.txt")) {
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
|
||||||
String line;
|
|
||||||
StringBuilder certData = new StringBuilder();
|
|
||||||
boolean inCert = false;
|
|
||||||
int certCount = 0;
|
|
||||||
|
|
||||||
while ((line = BoundedLineReader.readLine(reader, 5_000_000)) != null) {
|
|
||||||
if (line.startsWith("CKA_VALUE MULTILINE_OCTAL")) {
|
|
||||||
inCert = true;
|
|
||||||
certData = new StringBuilder();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inCert) {
|
|
||||||
if ("END".equals(line)) {
|
|
||||||
inCert = false;
|
|
||||||
byte[] certBytes = parseOctalData(certData.toString());
|
|
||||||
if (certBytes != null) {
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
X509Certificate cert =
|
|
||||||
(X509Certificate)
|
|
||||||
cf.generateCertificate(
|
|
||||||
new ByteArrayInputStream(certBytes));
|
|
||||||
trustStore.setCertificateEntry("mozilla-cert-" + certCount++, cert);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
certData.append(line).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] parseOctalData(String data) {
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
String[] tokens = data.split("\\\\");
|
|
||||||
for (String token : tokens) {
|
|
||||||
token = token.trim();
|
|
||||||
if (!token.isEmpty()) {
|
|
||||||
baos.write(Integer.parseInt(token, 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return baos.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateCertificateChain(X509Certificate cert) {
|
|
||||||
try {
|
|
||||||
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
List<X509Certificate> certList = Arrays.asList(cert);
|
|
||||||
CertPath certPath = cf.generateCertPath(certList);
|
|
||||||
|
|
||||||
Set<TrustAnchor> anchors = new HashSet<>();
|
|
||||||
Enumeration<String> aliases = trustStore.aliases();
|
|
||||||
while (aliases.hasMoreElements()) {
|
|
||||||
Object trustCert = trustStore.getCertificate(aliases.nextElement());
|
|
||||||
if (trustCert instanceof X509Certificate) {
|
|
||||||
anchors.add(new TrustAnchor((X509Certificate) trustCert, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PKIXParameters params = new PKIXParameters(anchors);
|
|
||||||
params.setRevocationEnabled(false);
|
|
||||||
validator.validate(certPath, params);
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateTrustStore(X509Certificate cert) {
|
|
||||||
try {
|
|
||||||
Enumeration<String> aliases = trustStore.aliases();
|
|
||||||
while (aliases.hasMoreElements()) {
|
|
||||||
Object trustCert = trustStore.getCertificate(aliases.nextElement());
|
|
||||||
if (trustCert instanceof X509Certificate && cert.equals(trustCert)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (KeyStoreException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRevoked(X509Certificate cert) {
|
|
||||||
try {
|
|
||||||
cert.checkValidity();
|
|
||||||
return false;
|
|
||||||
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateCertificateChainWithCustomCert(
|
|
||||||
X509Certificate cert, X509Certificate customCert) {
|
|
||||||
try {
|
|
||||||
cert.verify(customCert.getPublicKey());
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateTrustWithCustomCert(X509Certificate cert, X509Certificate customCert) {
|
|
||||||
try {
|
|
||||||
// Compare the issuer of the signature certificate with the custom certificate
|
|
||||||
return cert.getIssuerX500Principal().equals(customCert.getSubjectX500Principal());
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@ public class MetricsAggregatorService {
|
|||||||
this.postHogService = postHogService;
|
this.postHogService = postHogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedRate = 7200000) // Run every 2 hours
|
@Scheduled(fixedRate = 1800000) // Run every 30 minutes
|
||||||
public void aggregateAndSendMetrics() {
|
public void aggregateAndSendMetrics() {
|
||||||
Map<String, Object> metrics = new HashMap<>();
|
Map<String, Object> metrics = new HashMap<>();
|
||||||
Search.in(meterRegistry)
|
Search.in(meterRegistry)
|
||||||
@@ -39,13 +39,6 @@ public class MetricsAggregatorService {
|
|||||||
if (method == null || uri == null) {
|
if (method == null || uri == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!method.equals("GET") && !method.equals("POST")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Skip URIs that are 2 characters or shorter
|
|
||||||
if (uri.length() <= 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String key =
|
String key =
|
||||||
String.format(
|
String.format(
|
||||||
|
|||||||
@@ -17,18 +17,15 @@ public class PdfMetadataService {
|
|||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
private final String stirlingPDFLabel;
|
private final String stirlingPDFLabel;
|
||||||
private final UserServiceInterface userService;
|
private final UserServiceInterface userService;
|
||||||
private final boolean runningEE;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PdfMetadataService(
|
public PdfMetadataService(
|
||||||
ApplicationProperties applicationProperties,
|
ApplicationProperties applicationProperties,
|
||||||
@Qualifier("StirlingPDFLabel") String stirlingPDFLabel,
|
@Qualifier("StirlingPDFLabel") String stirlingPDFLabel,
|
||||||
@Qualifier("runningEE") boolean runningEE,
|
|
||||||
@Autowired(required = false) UserServiceInterface userService) {
|
@Autowired(required = false) UserServiceInterface userService) {
|
||||||
this.applicationProperties = applicationProperties;
|
this.applicationProperties = applicationProperties;
|
||||||
this.stirlingPDFLabel = stirlingPDFLabel;
|
this.stirlingPDFLabel = stirlingPDFLabel;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.runningEE = runningEE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
|
public PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
|
||||||
@@ -64,8 +61,10 @@ public class PdfMetadataService {
|
|||||||
|
|
||||||
String creator = stirlingPDFLabel;
|
String creator = stirlingPDFLabel;
|
||||||
|
|
||||||
if (applicationProperties.getEnterpriseEdition().getCustomMetadata().isAutoUpdateMetadata()
|
if (applicationProperties
|
||||||
&& runningEE) {
|
.getEnterpriseEdition()
|
||||||
|
.getCustomMetadata()
|
||||||
|
.isAutoUpdateMetadata()) {
|
||||||
|
|
||||||
creator = applicationProperties.getEnterpriseEdition().getCustomMetadata().getCreator();
|
creator = applicationProperties.getEnterpriseEdition().getCustomMetadata().getCreator();
|
||||||
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
|
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
|
||||||
@@ -84,8 +83,10 @@ public class PdfMetadataService {
|
|||||||
pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
|
pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
|
||||||
|
|
||||||
String author = pdfMetadata.getAuthor();
|
String author = pdfMetadata.getAuthor();
|
||||||
if (applicationProperties.getEnterpriseEdition().getCustomMetadata().isAutoUpdateMetadata()
|
if (applicationProperties
|
||||||
&& runningEE) {
|
.getEnterpriseEdition()
|
||||||
|
.getCustomMetadata()
|
||||||
|
.isAutoUpdateMetadata()) {
|
||||||
author = applicationProperties.getEnterpriseEdition().getCustomMetadata().getAuthor();
|
author = applicationProperties.getEnterpriseEdition().getCustomMetadata().getAuthor();
|
||||||
|
|
||||||
if (userService != null) {
|
if (userService != null) {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class FileToPdf {
|
|||||||
new ByteArrayInputStream(Files.readAllBytes(zipFilePath)))) {
|
new ByteArrayInputStream(Files.readAllBytes(zipFilePath)))) {
|
||||||
ZipEntry entry = zipIn.getNextEntry();
|
ZipEntry entry = zipIn.getNextEntry();
|
||||||
while (entry != null) {
|
while (entry != null) {
|
||||||
Path filePath = tempUnzippedDir.resolve(sanitizeZipFilename(entry.getName()));
|
Path filePath = tempUnzippedDir.resolve(entry.getName());
|
||||||
if (!entry.isDirectory()) {
|
if (!entry.isDirectory()) {
|
||||||
Files.createDirectories(filePath.getParent());
|
Files.createDirectories(filePath.getParent());
|
||||||
if (entry.getName().toLowerCase().endsWith(".html")
|
if (entry.getName().toLowerCase().endsWith(".html")
|
||||||
@@ -175,7 +175,7 @@ public class FileToPdf {
|
|||||||
ZipSecurity.createHardenedInputStream(new ByteArrayInputStream(fileBytes))) {
|
ZipSecurity.createHardenedInputStream(new ByteArrayInputStream(fileBytes))) {
|
||||||
ZipEntry entry = zipIn.getNextEntry();
|
ZipEntry entry = zipIn.getNextEntry();
|
||||||
while (entry != null) {
|
while (entry != null) {
|
||||||
Path filePath = tempDirectory.resolve(sanitizeZipFilename(entry.getName()));
|
Path filePath = tempDirectory.resolve(entry.getName());
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
Files.createDirectories(filePath); // Explicitly create the directory structure
|
Files.createDirectories(filePath); // Explicitly create the directory structure
|
||||||
} else {
|
} else {
|
||||||
@@ -241,14 +241,4 @@ public class FileToPdf {
|
|||||||
Files.deleteIfExists(tempOutputFile);
|
Files.deleteIfExists(tempOutputFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String sanitizeZipFilename(String entryName) {
|
|
||||||
if (entryName == null || entryName.trim().isEmpty()) {
|
|
||||||
return entryName;
|
|
||||||
}
|
|
||||||
while (entryName.contains("../") || entryName.contains("..\\")) {
|
|
||||||
entryName = entryName.replace("../", "").replace("..\\", "");
|
|
||||||
}
|
|
||||||
return entryName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,45 +88,15 @@ public class GeneralUtils {
|
|||||||
|
|
||||||
public static boolean isURLReachable(String urlStr) {
|
public static boolean isURLReachable(String urlStr) {
|
||||||
try {
|
try {
|
||||||
// Parse the URL
|
|
||||||
URL url = URI.create(urlStr).toURL();
|
URL url = URI.create(urlStr).toURL();
|
||||||
|
|
||||||
// Allow only http and https protocols
|
|
||||||
String protocol = url.getProtocol();
|
|
||||||
if (!protocol.equals("http") && !protocol.equals("https")) {
|
|
||||||
return false; // Disallow other protocols
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the host is a local address
|
|
||||||
String host = url.getHost();
|
|
||||||
if (isLocalAddress(host)) {
|
|
||||||
return false; // Exclude local addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the URL is reachable
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
connection.setRequestMethod("HEAD");
|
connection.setRequestMethod("HEAD");
|
||||||
// connection.setConnectTimeout(5000); // Set connection timeout
|
|
||||||
// connection.setReadTimeout(5000); // Set read timeout
|
|
||||||
int responseCode = connection.getResponseCode();
|
int responseCode = connection.getResponseCode();
|
||||||
return (200 <= responseCode && responseCode <= 399);
|
return (200 <= responseCode && responseCode <= 399);
|
||||||
} catch (Exception e) {
|
} catch (MalformedURLException e) {
|
||||||
return false; // Return false in case of any exception
|
return false;
|
||||||
}
|
} catch (IOException e) {
|
||||||
}
|
return false;
|
||||||
|
|
||||||
private static boolean isLocalAddress(String host) {
|
|
||||||
try {
|
|
||||||
// Resolve DNS to IP address
|
|
||||||
InetAddress address = InetAddress.getByName(host);
|
|
||||||
|
|
||||||
// Check for local addresses
|
|
||||||
return address.isAnyLocalAddress() || // Matches 0.0.0.0 or similar
|
|
||||||
address.isLoopbackAddress() || // Matches 127.0.0.1 or ::1
|
|
||||||
address.isSiteLocalAddress() || // Matches private IPv4 ranges: 192.168.x.x, 10.x.x.x, 172.16.x.x to 172.31.x.x
|
|
||||||
address.getHostAddress().startsWith("fe80:"); // Matches link-local IPv6 addresses
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false; // Return false for invalid or unresolved addresses
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,10 +289,6 @@ public class GeneralUtils {
|
|||||||
saveKeyToConfig(id, key, true);
|
saveKeyToConfig(id, key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveKeyToConfig(String id, boolean key) throws IOException {
|
|
||||||
saveKeyToConfig(id, key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveKeyToConfig(String id, String key, boolean autoGenerated)
|
public static void saveKeyToConfig(String id, String key, boolean autoGenerated)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
|
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
|
||||||
@@ -341,24 +307,6 @@ public class GeneralUtils {
|
|||||||
settingsYml.save();
|
settingsYml.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveKeyToConfig(String id, boolean key, boolean autoGenerated)
|
|
||||||
throws IOException {
|
|
||||||
Path path = Paths.get("configs", "settings.yml");
|
|
||||||
|
|
||||||
final YamlFile settingsYml = new YamlFile(path.toFile());
|
|
||||||
DumperOptions yamlOptionssettingsYml =
|
|
||||||
((SimpleYamlImplementation) settingsYml.getImplementation()).getDumperOptions();
|
|
||||||
yamlOptionssettingsYml.setSplitLines(false);
|
|
||||||
|
|
||||||
settingsYml.loadWithComments();
|
|
||||||
|
|
||||||
YamlFileWrapper writer = settingsYml.path(id).set(key);
|
|
||||||
if (autoGenerated) {
|
|
||||||
writer.comment("# Automatically Generated Settings (Do Not Edit Directly)");
|
|
||||||
}
|
|
||||||
settingsYml.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String generateMachineFingerprint() {
|
public static String generateMachineFingerprint() {
|
||||||
try {
|
try {
|
||||||
// Get the MAC address
|
// Get the MAC address
|
||||||
@@ -401,33 +349,4 @@ public class GeneralUtils {
|
|||||||
return "GenericID";
|
return "GenericID";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isVersionHigher(String currentVersion, String compareVersion) {
|
|
||||||
if (currentVersion == null || compareVersion == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split versions into components
|
|
||||||
String[] current = currentVersion.split("\\.");
|
|
||||||
String[] compare = compareVersion.split("\\.");
|
|
||||||
|
|
||||||
// Get the length of the shorter version array
|
|
||||||
int length = Math.min(current.length, compare.length);
|
|
||||||
|
|
||||||
// Compare each component
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
int currentPart = Integer.parseInt(current[i]);
|
|
||||||
int comparePart = Integer.parseInt(compare[i]);
|
|
||||||
|
|
||||||
if (currentPart > comparePart) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (currentPart < comparePart) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all components so far are equal, the longer version is considered higher
|
|
||||||
return current.length > compare.length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package stirling.software.SPDF.utils.propertyeditor;
|
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
public class StringToMapPropertyEditor extends PropertyEditorSupport {
|
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAsText(String text) throws IllegalArgumentException {
|
|
||||||
try {
|
|
||||||
TypeReference<HashMap<String, String>> typeRef =
|
|
||||||
new TypeReference<HashMap<String, String>>() {};
|
|
||||||
Map<String, String> map = objectMapper.readValue(text, typeRef);
|
|
||||||
setValue(map);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Failed to convert java.lang.String to java.util.Map");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,10 +3,6 @@ multipart.enabled=true
|
|||||||
logging.level.org.springframework=WARN
|
logging.level.org.springframework=WARN
|
||||||
logging.level.org.hibernate=WARN
|
logging.level.org.hibernate=WARN
|
||||||
logging.level.org.eclipse.jetty=WARN
|
logging.level.org.eclipse.jetty=WARN
|
||||||
#logging.level.org.springframework.security.saml2=TRACE
|
|
||||||
#logging.level.org.springframework.security=DEBUG
|
|
||||||
#logging.level.org.opensaml=DEBUG
|
|
||||||
#logging.level.stirling.software.SPDF.config.security: DEBUG
|
|
||||||
logging.level.com.zaxxer.hikari=WARN
|
logging.level.com.zaxxer.hikari=WARN
|
||||||
|
|
||||||
spring.jpa.open-in-view=false
|
spring.jpa.open-in-view=false
|
||||||
@@ -31,8 +27,6 @@ server.servlet.context-path=${SYSTEM_ROOTURIPATH:/}
|
|||||||
|
|
||||||
spring.devtools.restart.enabled=true
|
spring.devtools.restart.enabled=true
|
||||||
spring.devtools.livereload.enabled=true
|
spring.devtools.livereload.enabled=true
|
||||||
spring.devtools.restart.exclude=stirling.software.SPDF.config.security/**
|
|
||||||
|
|
||||||
spring.thymeleaf.encoding=UTF-8
|
spring.thymeleaf.encoding=UTF-8
|
||||||
|
|
||||||
spring.web.resources.mime-mappings.webmanifest=application/manifest+json
|
spring.web.resources.mime-mappings.webmanifest=application/manifest+json
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=تجزئة المستندات PDF حسب الفص
|
|||||||
home.splitPdfByChapters.desc=قسم مستند PDF إلى ملفات متعددة بناءً على هيكل فصوله.
|
home.splitPdfByChapters.desc=قسم مستند PDF إلى ملفات متعددة بناءً على هيكل فصوله.
|
||||||
splitPdfByChapters.tags=تجزئة، فصول، علامات تبويب، تنظيم
|
splitPdfByChapters.tags=تجزئة، فصول، علامات تبويب، تنظيم
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=إستبدال-عكس اللون
|
replace-color.title=إستبدال-عكس اللون
|
||||||
replace-color.header=استبدال-عكس لون PDF
|
replace-color.header=استبدال-عكس لون PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=تحريك إلى اليسار
|
|||||||
multiTool.moveRight=تحريك إلى اليمين
|
multiTool.moveRight=تحريك إلى اليمين
|
||||||
multiTool.delete=حذف
|
multiTool.delete=حذف
|
||||||
multiTool.dragDropMessage=الصفحات المحددة
|
multiTool.dragDropMessage=الصفحات المحددة
|
||||||
multiTool.undo=تراجع
|
|
||||||
multiTool.redo=إعادة إجراء
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=هذه الميزة متوفرة في <a href="{0}">صفحة الأدوات المتعددة</a> لدينا. اطلع عليها للحصول على واجهة مستخدم محسّنة لكل صفحة وميزات إضافية!
|
multiTool-advert.message=هذه الميزة متوفرة في <a href="{0}">صفحة الأدوات المتعددة</a> لدينا. اطلع عليها للحصول على واجهة مستخدم محسّنة لكل صفحة وميزات إضافية!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=تشفير
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=إضافة علامة مائية
|
watermark.title=إضافة علامة مائية
|
||||||
watermark.header=إضافة علامة مائية
|
watermark.header=إضافة علامة مائية
|
||||||
watermark.customColor=لون نص مخصص
|
|
||||||
watermark.selectText.1=حدد PDF لإضافة العلامة المائية إليه:
|
watermark.selectText.1=حدد PDF لإضافة العلامة المائية إليه:
|
||||||
watermark.selectText.2=نص العلامة المائية:
|
watermark.selectText.2=نص العلامة المائية:
|
||||||
watermark.selectText.3=حجم الخط:
|
watermark.selectText.3=حجم الخط:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=مستوى الإشارة المرجعية: اختر مس
|
|||||||
splitByChapters.desc.3=تمثيل البيانات الأصلية: إذا تم اختيارها، سترمز البيانات المرجعية الأصلية إلى كل PDF مجزأ.
|
splitByChapters.desc.3=تمثيل البيانات الأصلية: إذا تم اختيارها، سترمز البيانات المرجعية الأصلية إلى كل PDF مجزأ.
|
||||||
splitByChapters.desc.4=سماح بالتكرار: إذا تم اختياره، يسمح بوجود معاينات متعددة في الصفحة نفسها لخلق ملفات PDF منفصلة.
|
splitByChapters.desc.4=سماح بالتكرار: إذا تم اختياره، يسمح بوجود معاينات متعددة في الصفحة نفسها لخلق ملفات PDF منفصلة.
|
||||||
splitByChapters.submit=تقطيع ملف PDF
|
splitByChapters.submit=تقطيع ملف PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=انقر هنا
|
|
||||||
fileChooser.or=أو
|
|
||||||
fileChooser.dragAndDrop=قم بسحب الملفات وإفلاتها
|
|
||||||
fileChooser.hoveredDragAndDrop=قم بسحب المفات وإفلاتها هنا
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ sizes.small=Kiçik
|
|||||||
sizes.medium=Orta
|
sizes.medium=Orta
|
||||||
sizes.large=Böyük
|
sizes.large=Böyük
|
||||||
sizes.x-large=Ekstra Böyük
|
sizes.x-large=Ekstra Böyük
|
||||||
error.pdfPassword=PDF sənədi şifrlənmişdir və şifr təmin edilməmişdir və ya yanlışdır.
|
error.pdfPassword=PDF sənədi şifrələnmişdir və şifrə təmin edilməmişdir və ya yanlışdır.
|
||||||
delete=Sil
|
delete=Sil
|
||||||
username=İstifadəçi Adı
|
username=İstifadəçi Adı
|
||||||
password=Şifr
|
password=Şifrə
|
||||||
welcome=Xoş gəldiniz
|
welcome=Xoş gəldiniz
|
||||||
property=Xüsusiyyət
|
property=Xüsusiyyət
|
||||||
black=Qara
|
black=Qara
|
||||||
@@ -53,11 +53,11 @@ no=Xeyr
|
|||||||
changedCredsMessage=Etibarnamələr dəyişdirildi!
|
changedCredsMessage=Etibarnamələr dəyişdirildi!
|
||||||
notAuthenticatedMessage=İstifadəçinin kimliyi təsdiqlənməyib.
|
notAuthenticatedMessage=İstifadəçinin kimliyi təsdiqlənməyib.
|
||||||
userNotFoundMessage=İstifadəçi tapılmadı.
|
userNotFoundMessage=İstifadəçi tapılmadı.
|
||||||
incorrectPasswordMessage=Cari şifr yanlışdır.
|
incorrectPasswordMessage=Cari şifrə yanlışdır.
|
||||||
usernameExistsMessage=İstifadəçi adı mövcuddur.
|
usernameExistsMessage=İstifadəçi adı mövcuddur.
|
||||||
invalidUsernameMessage=Yanlış istifadəçi adı, istifadəçi adı sadəcə hərflərdən, rəqəmlərdən və @._+- xüsusi simvollarından ibarət ola bilər və ya düzgün email ünvanı olmalıdır.
|
invalidUsernameMessage=Yanlış istifadəçi adı, istifadəçi adı sadəcə hərflərdən, rəqəmlərdən və @._+- xüsusi simvollarından ibarət ola bilər və ya düzgün email ünvanı olmalıdır.
|
||||||
invalidPasswordMessage=Şifr boş olmamalıdır, başlanğıc və sonunda boşluqdan istifadə edilməməlidir.
|
invalidPasswordMessage=Şifrə boş olmamalıdır, başlanğıc və sonunda boşluqdan istifadə edilməməlidir.
|
||||||
confirmPasswordErrorMessage=Yeni Şifr və Yeni Şifri Doğrula uyğun olmalıdır.
|
confirmPasswordErrorMessage=Yeni Şifrə və Yeni Şifrəni Doğrula uyğun olmalıdır.
|
||||||
deleteCurrentUserMessage=Hazırda daxil olmuş istifadəçini silmək mümkün deyil.
|
deleteCurrentUserMessage=Hazırda daxil olmuş istifadəçini silmək mümkün deyil.
|
||||||
deleteUsernameExistsMessage=İstifadəçi adı mövcud deyildir və silinə bilməz.
|
deleteUsernameExistsMessage=İstifadəçi adı mövcud deyildir və silinə bilməz.
|
||||||
downgradeCurrentUserMessage=Cari istifadəçinin rolunu aşağı salmaq mümkün deyil
|
downgradeCurrentUserMessage=Cari istifadəçinin rolunu aşağı salmaq mümkün deyil
|
||||||
@@ -70,8 +70,8 @@ oops=Oops!
|
|||||||
help=Yardım
|
help=Yardım
|
||||||
goHomepage=Ana səhifəyə get
|
goHomepage=Ana səhifəyə get
|
||||||
joinDiscord=Discord serverimizə qatıl
|
joinDiscord=Discord serverimizə qatıl
|
||||||
seeDockerHub=Docker Hub-a bax
|
seeDockerHub=Docker Hub'a bax
|
||||||
visitGithub=Github Repository-ə Baş Çək
|
visitGithub=Github Repository'ə Baş Çək
|
||||||
donate=İanə Ver
|
donate=İanə Ver
|
||||||
color=Rəng
|
color=Rəng
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
@@ -126,9 +126,9 @@ enterpriseEdition.ssoAdvert=Daha çox istifadəçi-idarəetmə xüsusiyyətləri
|
|||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Stirling PDF-i daha yaxşı etmək istəyirsinizmi?
|
analytics.title=Stirling PDF'i daha yaxşı etmək istəyirsinizmi?
|
||||||
analytics.paragraph1=Stirling PDF bizə məhsulu inkişaf etdirməyə kömək etmək üçün analitikaya üstünlük verib. Biz heç bir şəxsi məlumatı və ya fayl məzmununu izləmirik.
|
analytics.paragraph1=Stirling PDF bizə məhsulu inkişaf etdirməyə kömək etmək üçün analitikaya üstünlük verib. Biz heç bir şəxsi məlumatı və ya fayl məzmununu izləmirik.
|
||||||
analytics.paragraph2=Zəhmət olmasa, Stringling-PDF-ə inkişaf etməkdə və istifadəçilərimizi daha yaxşı anlamaqda yardım etmək üçün analitikanı aktivləşdirməyi nəzərə alın.
|
analytics.paragraph2=Zəhmət olmasa, Stringling-PDF'ə inkişaf etməkdə və istifadəçilərimizi daha yaxşı anlamaqda yardım etmək üçün analitikanı aktivləşdirməyi nəzərə alın.
|
||||||
analytics.enable=Analitikanı aktivləşdir
|
analytics.enable=Analitikanı aktivləşdir
|
||||||
analytics.disable=Analitikanı deaktivləşdir
|
analytics.disable=Analitikanı deaktivləşdir
|
||||||
analytics.settings=Analitikanın parametrlərini config/settings.yml faylından dəyişə bilərsiniz.
|
analytics.settings=Analitikanın parametrlərini config/settings.yml faylından dəyişə bilərsiniz.
|
||||||
@@ -141,11 +141,11 @@ navbar.darkmode=Qaranlıq Tema
|
|||||||
navbar.language=Dillər
|
navbar.language=Dillər
|
||||||
navbar.settings=Parametrlər
|
navbar.settings=Parametrlər
|
||||||
navbar.allTools=Alətlər
|
navbar.allTools=Alətlər
|
||||||
navbar.multiTool=Multi-Alət
|
navbar.multiTool=Çox Alət
|
||||||
navbar.search=Axtar
|
navbar.search=Axtar
|
||||||
navbar.sections.organize=Təşkil et
|
navbar.sections.organize=Təşkil et
|
||||||
navbar.sections.convertTo=PDF-ə Çevir
|
navbar.sections.convertTo=PDF'ə Çevir
|
||||||
navbar.sections.convertFrom=PDF-dən Çevir
|
navbar.sections.convertFrom=PDF'dən Çevir
|
||||||
navbar.sections.security=İmza & Təhlükəsizlik
|
navbar.sections.security=İmza & Təhlükəsizlik
|
||||||
navbar.sections.advance=Qabaqcıl
|
navbar.sections.advance=Qabaqcıl
|
||||||
navbar.sections.edit=Bax & Redaktə et
|
navbar.sections.edit=Bax & Redaktə et
|
||||||
@@ -171,11 +171,11 @@ settings.cacheInputs.help=Gələcək əməliyyatlar üçün əvvəllər istifad
|
|||||||
|
|
||||||
changeCreds.title=Məlumatları dəyişdirin
|
changeCreds.title=Məlumatları dəyişdirin
|
||||||
changeCreds.header=Hesab Məlumatlarınızı Yeniləyin
|
changeCreds.header=Hesab Məlumatlarınızı Yeniləyin
|
||||||
changeCreds.changePassword=Siz standart giriş məlumatlarından istifadə edirsiniz. Zəhmət olmasa, yeni şifr daxil edin
|
changeCreds.changePassword=Siz standart giriş məlumatlarından istifadə edirsiniz. Zəhmət olmasa, yeni şifrə daxil edin
|
||||||
changeCreds.newUsername=Yeni İstifadəçi Adı
|
changeCreds.newUsername=Yeni İstifadəçi Adı
|
||||||
changeCreds.oldPassword=Cari Şifr
|
changeCreds.oldPassword=Cari Şifrə
|
||||||
changeCreds.newPassword=Yeni Şifr
|
changeCreds.newPassword=Yeni Şifrə
|
||||||
changeCreds.confirmNewPassword=Yeni Şifri Təsdiqləyin
|
changeCreds.confirmNewPassword=Yeni Şifrəni Təsdiqləyin
|
||||||
changeCreds.submit=Dəyişiklikləri Təsdiqlə
|
changeCreds.submit=Dəyişiklikləri Təsdiqlə
|
||||||
|
|
||||||
|
|
||||||
@@ -186,11 +186,11 @@ account.adminSettings=Admin Paramterləri - İstifadəçilər Əlavə Et və Onl
|
|||||||
account.userControlSettings=İstifadəçi İdarəetmə Parametrləri
|
account.userControlSettings=İstifadəçi İdarəetmə Parametrləri
|
||||||
account.changeUsername=İstifadəçi Adını Dəyiş
|
account.changeUsername=İstifadəçi Adını Dəyiş
|
||||||
account.newUsername=Yeni İstifadəçi Adı
|
account.newUsername=Yeni İstifadəçi Adı
|
||||||
account.password=Təsdiqləmə Şifri
|
account.password=Təsdiqləmə Şifrəsi
|
||||||
account.oldPassword=Keçmiş Şifr
|
account.oldPassword=Keçmiş Şifrə
|
||||||
account.newPassword=Yeni Şifr
|
account.newPassword=Yeni Şifrə
|
||||||
account.changePassword=Şifri Dəyiş
|
account.changePassword=Şifrəni Dəyiş
|
||||||
account.confirmNewPassword=Yeni Şifri Təsdiqlə
|
account.confirmNewPassword=Yeni Şifrəni Təsdiqlə
|
||||||
account.signOut=Çıxış
|
account.signOut=Çıxış
|
||||||
account.yourApiKey=Sizin API Açarınız
|
account.yourApiKey=Sizin API Açarınız
|
||||||
account.syncTitle=Brauzer parametrlərini hesabla sinxronlaşdırın
|
account.syncTitle=Brauzer parametrlərini hesabla sinxronlaşdırın
|
||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=PDF-i Fəsillərə Əsasən Böl
|
|||||||
home.splitPdfByChapters.desc=Fəsil strukturuna əsasən PDF-i bir neçə fayla böl.
|
home.splitPdfByChapters.desc=Fəsil strukturuna əsasən PDF-i bir neçə fayla böl.
|
||||||
splitPdfByChapters.tags=böl,fəsillər,əlfəcinlər,nizamla
|
splitPdfByChapters.tags=böl,fəsillər,əlfəcinlər,nizamla
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Qabaqcıl Rəng Seçimləri
|
replace-color.title=Qabaqcıl Rəng Seçimləri
|
||||||
replace-color.header=PDF-də Rəngləri Dəyiş-Tərsinə Çevir
|
replace-color.header=PDF-də Rəngləri Dəyiş-Tərsinə Çevir
|
||||||
@@ -547,7 +543,7 @@ login.title=Daxil olun
|
|||||||
login.header=Daxil olun
|
login.header=Daxil olun
|
||||||
login.signin=Daxil olun
|
login.signin=Daxil olun
|
||||||
login.rememberme=Məni xatırla
|
login.rememberme=Məni xatırla
|
||||||
login.invalid=Etibarsız istifadəçi adı və ya şifr.
|
login.invalid=Etibarsız istifadəçi adı və ya şifrə.
|
||||||
login.locked=Sizin hesabınız kilidlənmişdir.
|
login.locked=Sizin hesabınız kilidlənmişdir.
|
||||||
login.signinTitle=Zəhmət olmasa, daxil olun
|
login.signinTitle=Zəhmət olmasa, daxil olun
|
||||||
login.ssoSignIn=Single Sign-on vasitəsilə daxil olun
|
login.ssoSignIn=Single Sign-on vasitəsilə daxil olun
|
||||||
@@ -585,8 +581,8 @@ showJS.submit=Göstər
|
|||||||
|
|
||||||
|
|
||||||
#pdfToSinglePage
|
#pdfToSinglePage
|
||||||
pdfToSinglePage.title=PDF-dən Tək Səhifəyə
|
pdfToSinglePage.title=PDF'dən Tək Səhifəyə
|
||||||
pdfToSinglePage.header=PDF-dən Tək Səhifəyə
|
pdfToSinglePage.header=PDF'dən Tək Səhifəyə
|
||||||
pdfToSinglePage.submit=Tək Səhifəyə Çevir
|
pdfToSinglePage.submit=Tək Səhifəyə Çevir
|
||||||
|
|
||||||
|
|
||||||
@@ -605,8 +601,8 @@ getPdfInfo.downloadJson=JSON yüklə
|
|||||||
|
|
||||||
|
|
||||||
#markdown-to-pdf
|
#markdown-to-pdf
|
||||||
MarkdownToPDF.title=Markdown-dan PDF-ə
|
MarkdownToPDF.title=Markdown'dan PDF'ə
|
||||||
MarkdownToPDF.header=Markdown-dan PDF-ə
|
MarkdownToPDF.header=Markdown'dan PDF'ə
|
||||||
MarkdownToPDF.submit=Çevir
|
MarkdownToPDF.submit=Çevir
|
||||||
MarkdownToPDF.help=İş davam edir
|
MarkdownToPDF.help=İş davam edir
|
||||||
MarkdownToPDF.credit=WeasyPrint İstifadə Edir
|
MarkdownToPDF.credit=WeasyPrint İstifadə Edir
|
||||||
@@ -621,8 +617,8 @@ URLToPDF.credit=WeasyPrint İstifadə Edir
|
|||||||
|
|
||||||
|
|
||||||
#html-to-pdf
|
#html-to-pdf
|
||||||
HTMLToPDF.title=HTML-dən PDF-ə
|
HTMLToPDF.title=HTML'dən PDF'ə
|
||||||
HTMLToPDF.header=HTML-dən PDF-ə
|
HTMLToPDF.header=HTML'dən PDF'ə
|
||||||
HTMLToPDF.help=HTML fayllarını və tərkibində mütləq html/css/images və s. olan ZIP fayllarını qəbul edir
|
HTMLToPDF.help=HTML fayllarını və tərkibində mütləq html/css/images və s. olan ZIP fayllarını qəbul edir
|
||||||
HTMLToPDF.submit=Çevir
|
HTMLToPDF.submit=Çevir
|
||||||
HTMLToPDF.credit=WeasyPrint İstifadə Edir
|
HTMLToPDF.credit=WeasyPrint İstifadə Edir
|
||||||
@@ -660,14 +656,14 @@ AddStampRequest.submit=Təsdiqlə
|
|||||||
|
|
||||||
|
|
||||||
#sanitizePDF
|
#sanitizePDF
|
||||||
sanitizePDF.title=PDF-i Təmizlə
|
sanitizePDF.title=PDF'i Təmizlə
|
||||||
sanitizePDF.header=PDF Faylını Təmizlə
|
sanitizePDF.header=PDF Faylını Təmizlə
|
||||||
sanitizePDF.selectText.1=JavaScript Fəaliyyətlərini Sil
|
sanitizePDF.selectText.1=JavaScript Fəaliyyətlərini Sil
|
||||||
sanitizePDF.selectText.2=Daxil Edilmiş Faylları Sil
|
sanitizePDF.selectText.2=Daxil Edilmiş Faylları Sil
|
||||||
sanitizePDF.selectText.3=Metadatanı Sil
|
sanitizePDF.selectText.3=Metadatanı Sil
|
||||||
sanitizePDF.selectText.4=Linkləri Sil
|
sanitizePDF.selectText.4=Linkləri Sil
|
||||||
sanitizePDF.selectText.5=Şriftləri Sil
|
sanitizePDF.selectText.5=Şriftləri Sil
|
||||||
sanitizePDF.submit=PDF-i Təmizlə
|
sanitizePDF.submit=PDF'i Təmizlə
|
||||||
|
|
||||||
|
|
||||||
#addPageNumbers
|
#addPageNumbers
|
||||||
@@ -687,7 +683,7 @@ addPageNumbers.submit=Səhifə Nömrələri əlavə edin
|
|||||||
|
|
||||||
#auto-rename
|
#auto-rename
|
||||||
auto-rename.title=Avtomatik Yenidən Adlandır
|
auto-rename.title=Avtomatik Yenidən Adlandır
|
||||||
auto-rename.header=Pdf-in Adını Avtomatik Yenidən Adlandır
|
auto-rename.header=Pdf'in Adını Avtomatik Yenidən Adlandır
|
||||||
auto-rename.submit=Avtomatik Yenidən Adlandır
|
auto-rename.submit=Avtomatik Yenidən Adlandır
|
||||||
|
|
||||||
|
|
||||||
@@ -702,7 +698,7 @@ adjustContrast.download=Yüklə
|
|||||||
|
|
||||||
#crop
|
#crop
|
||||||
crop.title=Kəs
|
crop.title=Kəs
|
||||||
crop.header=Pdf-ləri Kəs
|
crop.header=Pdf'ləri Kəs
|
||||||
crop.submit=Təsdiq Et
|
crop.submit=Təsdiq Et
|
||||||
|
|
||||||
|
|
||||||
@@ -726,8 +722,8 @@ pipeline.title=Pipeline
|
|||||||
|
|
||||||
|
|
||||||
#pageLayout
|
#pageLayout
|
||||||
pageLayout.title=Çoxsəhifəli Tərtibat
|
pageLayout.title=Çoxsəhifəli Sxem
|
||||||
pageLayout.header=Çoxsəhifəli Tərtibat
|
pageLayout.header=Çoxsəhifəli Sxem
|
||||||
pageLayout.pagesPerSheet=Vərəqdəki Səhifə Sayı:
|
pageLayout.pagesPerSheet=Vərəqdəki Səhifə Sayı:
|
||||||
pageLayout.addBorder=Çərçivə Əlavə Et
|
pageLayout.addBorder=Çərçivə Əlavə Et
|
||||||
pageLayout.submit=Təsdiq et
|
pageLayout.submit=Təsdiq et
|
||||||
@@ -743,22 +739,22 @@ scalePages.submit=Təsdiq edin
|
|||||||
|
|
||||||
|
|
||||||
#certSign
|
#certSign
|
||||||
certSign.title=Sertifikatla İmzala
|
certSign.title=Certificate Signing
|
||||||
certSign.header=PDF-i Sertifikatınızla İmzalayın (İşlənilir)
|
certSign.header=Sign a PDF with your certificate (Work in progress)
|
||||||
certSign.selectPDF=İmzalamaq üçün PDF Faylı seçin:
|
certSign.selectPDF=Select a PDF File for Signing:
|
||||||
certSign.jksNote=Note: Əgər sertifikatınızın tipi aşağıda göstərilməyibsə, zəhmət olmasa "Keytool command line tool" istifadə edərək onu "Java Keystroke" (.jks) faylına çevirin. Sonra, aşağıdan .jks faylını seçin.
|
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
|
||||||
certSign.selectKey=Şəxsi Açar faylınızı seçin (PKCS#8 format, .pem və ya .der ola bilər):
|
certSign.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
|
||||||
certSign.selectCert=Sertifikat faylınızı seçin (X.509 format, .pem və ya .der ola bilər):
|
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
|
||||||
certSign.selectP12=PKCS#12 Keystore Faylınızı seçin (.p12 və ya .pfx) (İstəyə bağlı, əgər təmin olunarsa, şəxsi açar və sertifikatınızı ehtiva etməlidir):
|
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
|
||||||
certSign.selectJKS=Java Keystore Faylınızı seçin (.jks və ya .keystore):
|
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||||
certSign.certType=Sertifikat Tipi
|
certSign.certType=Certificate Type
|
||||||
certSign.password=Keystore və ya Şəxsi Açar daxil edin (Əgər varsa):
|
certSign.password=Enter Your Keystore or Private Key Password (If Any):
|
||||||
certSign.showSig=İmzanı Göstər
|
certSign.showSig=Show Signature
|
||||||
certSign.reason=Səbəb
|
certSign.reason=Reason
|
||||||
certSign.location=Məkan
|
certSign.location=Location
|
||||||
certSign.name=Ad
|
certSign.name=Name
|
||||||
certSign.showLogo=Loqonu Göstər
|
certSign.showLogo=Show Logo
|
||||||
certSign.submit=PDF-i İmzala
|
certSign.submit=Sign PDF
|
||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
@@ -769,13 +765,13 @@ removeCertSign.submit=İmzanı silin
|
|||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Boş Səhifələri Sil
|
removeBlanks.title=Remove Blanks
|
||||||
removeBlanks.header=Boş SƏhifələri Silir
|
removeBlanks.header=Remove Blank Pages
|
||||||
removeBlanks.threshold=Minimal Piksel Bəyazlığı:
|
removeBlanks.threshold=Pixel Whiteness Threshold:
|
||||||
removeBlanks.thresholdDesc=Pikselin "Ağ" hesab olunması üçün minimal nə qədər bəyaz olmalı olduğunu təyin edin. 0 = Qara, 255 Ağappaq.
|
removeBlanks.thresholdDesc=Threshold for determining how white a white pixel must be to be classed as 'White'. 0 = Black, 255 pure white.
|
||||||
removeBlanks.whitePercent=Bəyaz Faizi (%):
|
removeBlanks.whitePercent=White Percent (%):
|
||||||
removeBlanks.whitePercentDesc=Silinmək üçün səhifənin neçə faizi "ağ" piksellərdən təşkil olunmalıdır
|
removeBlanks.whitePercentDesc=Percent of page that must be 'white' pixels to be removed
|
||||||
removeBlanks.submit=Boş Səhifələri Sil
|
removeBlanks.submit=Remove Blanks
|
||||||
|
|
||||||
|
|
||||||
#removeAnnotations
|
#removeAnnotations
|
||||||
@@ -785,16 +781,16 @@ removeAnnotations.submit=Sil
|
|||||||
|
|
||||||
|
|
||||||
#compare
|
#compare
|
||||||
compare.title=Müqayisə Et
|
compare.title=Compare
|
||||||
compare.header=PDF-ləri Müqayisə Et
|
compare.header=Compare PDFs
|
||||||
compare.highlightColor.1=Önə Çıxarma Rəngi 1:
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
compare.highlightColor.2=Önə Çıxarma Rəngi 2:
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Sənəd 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Sənəd 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Müqayisə Et
|
compare.submit=Compare
|
||||||
compare.complex.message=Fayllardan biri və ya ikisi də böyük fayldır. Müqayisə effektivliyi azala bilər.
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
compare.large.file.message=Fayllardan biri və ya ikisi də işləmək üçün çox böyükdür.
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
compare.no.text.message=Fayllardan birində və ya ikisində də mətn məzmunu yoxdur. Zəhmət olmasa, müqayisə üçün mətn məzmunlu PDF seçin.
|
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Kitabları və Komiksləri PDF-ə
|
BookToPDF.title=Kitabları və Komiksləri PDF-ə
|
||||||
@@ -822,12 +818,12 @@ sign.save=İmzanı yadda Saxla
|
|||||||
sign.personalSigs=Şəxsi İmzalar
|
sign.personalSigs=Şəxsi İmzalar
|
||||||
sign.sharedSigs=Paylaşılan İmzalar
|
sign.sharedSigs=Paylaşılan İmzalar
|
||||||
sign.noSavedSigs=Saxlanmış imza tapılmadı
|
sign.noSavedSigs=Saxlanmış imza tapılmadı
|
||||||
sign.addToAll=Bütün səhiflərə əlavə et
|
sign.addToAll=Add to all pages
|
||||||
sign.delete=Sil
|
sign.delete=Delete
|
||||||
sign.first=İlk səhifə
|
sign.first=First page
|
||||||
sign.last=Son səhifə
|
sign.last=Last page
|
||||||
sign.next=Növbəti səhifə
|
sign.next=Next page
|
||||||
sign.previous=Əvvəlki səhifə
|
sign.previous=Previous page
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
repair.title=Bərpa Et
|
repair.title=Bərpa Et
|
||||||
@@ -843,37 +839,37 @@ flatten.submit=Düzləşdirin
|
|||||||
|
|
||||||
|
|
||||||
#ScannerImageSplit
|
#ScannerImageSplit
|
||||||
ScannerImageSplit.selectText.1=Bucaq Aşağı Limiti:
|
ScannerImageSplit.selectText.1=Angle Threshold:
|
||||||
ScannerImageSplit.selectText.2=Şəklin fırladılması üçün lazım olan minimal mütləq bucağı təyin edir (defolt: 10).
|
ScannerImageSplit.selectText.2=Sets the minimum absolute angle required for the image to be rotated (default: 10).
|
||||||
ScannerImageSplit.selectText.3=Rəng Toleransı:
|
ScannerImageSplit.selectText.3=Tolerance:
|
||||||
ScannerImageSplit.selectText.4=Təxmin olunan arxaplan rənginin ətrafındakı rəng fərqliliyi intervalını təyin edir (defolt: 30).
|
ScannerImageSplit.selectText.4=Determines the range of color variation around the estimated background color (default: 30).
|
||||||
ScannerImageSplit.selectText.5=Minimal Sahə:
|
ScannerImageSplit.selectText.5=Minimum Area:
|
||||||
ScannerImageSplit.selectText.6=Foto üçün minimal sahənin aşağı limitini təyin edir (defolt: 10000).
|
ScannerImageSplit.selectText.6=Sets the minimum area threshold for a photo (default: 10000).
|
||||||
ScannerImageSplit.selectText.7=Minimal Kontur Sahəsi:
|
ScannerImageSplit.selectText.7=Minimum Contour Area:
|
||||||
ScannerImageSplit.selectText.8=Fotonun kontur sahəsi üçün minimal aşağı limiti təyin edir
|
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
||||||
ScannerImageSplit.selectText.9=Sərhəd Ölçüsü:
|
ScannerImageSplit.selectText.9=Border Size:
|
||||||
ScannerImageSplit.selectText.10=Faylda ağ sərhədlərin olmasının qarşısını almaq üçün əlavə ediləcək sərhədin ölçüsünü təyin edir (defolt: 1).
|
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
||||||
ScannerImageSplit.info=Python yüklənməyib. İşə salmaq üçün Python lazımdır.
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
ocr.title=OST (OCR) / Skan Təmizləmə
|
ocr.title=OCR / Scan Cleanup
|
||||||
ocr.header=Skanları Təmizlə / OST (Optik Simvol Tanınması)
|
ocr.header=Cleanup Scans / OCR (Optical Character Recognition)
|
||||||
ocr.selectText.1=PDF-də aşkar olunacaq dilləri seçin (Göstərilmiş dillər hazırda aşkar olunmuşlardır):
|
ocr.selectText.1=Select languages that are to be detected within the PDF (Ones listed are the ones currently detected):
|
||||||
ocr.selectText.2=OST-lənmiş PDF ilə yanaşı daxilində OST edilmiş mətn olan PDF yaradın
|
ocr.selectText.2=Produce text file containing OCR text alongside the OCR'ed PDF
|
||||||
ocr.selectText.3=Əyri skan olunmuş səhifələri yerinə fırladaraq düzəldin
|
ocr.selectText.3=Correct pages were scanned at a skewed angle by rotating them back into place
|
||||||
ocr.selectText.4=OST-in arxaplandakı artıq mətni aşkar etməsinin qarşısını almaq üçün səhifəni təmizləyin. (Çıxış dəyişmir)
|
ocr.selectText.4=Clean page so its less likely that OCR will find text in background noise. (No output change)
|
||||||
ocr.selectText.5=OST-in arxaplandakı artıq mətni aşkar etməsinin qarşısını almaq üçün səhifəni təmizləyin, təmizləməni çıxışa verilən faylda saxlayır.
|
ocr.selectText.5=Clean page so its less likely that OCR will find text in background noise, maintains cleanup in output.
|
||||||
ocr.selectText.6=Üzərində interaktiv yazı olan səhifələri nəzərə almır, yalnız şəkil olan səhifələri OST edir.
|
ocr.selectText.6=Ignores pages that have interactive text on them, only OCRs pages that are images
|
||||||
ocr.selectText.7=OST-ə məcbur et, bütün orijinal mətn elementlərini silərək hər səhifəni OST edir
|
ocr.selectText.7=Force OCR, will OCR Every page removing all original text elements
|
||||||
ocr.selectText.8=Normal (PDF-də mətn varsa, xəta verəcək)
|
ocr.selectText.8=Normal (Will error if PDF contains text)
|
||||||
ocr.selectText.9=Əlavə Parametrlər
|
ocr.selectText.9=Additional Settings
|
||||||
ocr.selectText.10=OST (OCR) Rejimi
|
ocr.selectText.10=OCR Mode
|
||||||
ocr.selectText.11=OST-dən sonra şəkilləri sil (BÜTÜN şəkilləri silir, ancaq çevirmə prosesinin bir hissəsi olduqda işə yarayır)
|
ocr.selectText.11=Remove images after OCR (Removes ALL images, only useful if part of conversion step)
|
||||||
ocr.selectText.12=Render Tipi (Qabaqcıl)
|
ocr.selectText.12=Render Type (Advanced)
|
||||||
ocr.help=Bunu digər dillər üçün necə istifadə etmək və/və ya docker-də istifadə etməmək üçün bu dokumentasiyanı oxuyun
|
ocr.help=Please read this documentation on how to use this for other languages and/or use not in docker
|
||||||
ocr.credit=Bu servis OST (OCR) üçün "OCRmyPDF" və "Tesseract" istifadə edir.
|
ocr.credit=This service uses qpdf and Tesseract for OCR.
|
||||||
ocr.submit=PDF-i OST ilə işlə
|
ocr.submit=Process PDF with OCR
|
||||||
|
|
||||||
|
|
||||||
#extractImages
|
#extractImages
|
||||||
@@ -894,15 +890,15 @@ fileToPDF.submit=PDF-ə Çevir
|
|||||||
|
|
||||||
|
|
||||||
#compress
|
#compress
|
||||||
compress.title=Sıxışdır
|
compress.title=Compress
|
||||||
compress.header=PDF-i Sıxışdır
|
compress.header=Compress PDF
|
||||||
compress.credit=Bu servis PDF sıxışdırılması/Optimizasiyası üçün Ghostscript istifadə edir.
|
compress.credit=This service uses qpdf for PDF Compress/Optimisation.
|
||||||
compress.selectText.1=Manual Mod - 1-dən 4-ə
|
compress.selectText.1=Manual Mode - From 1 to 4
|
||||||
compress.selectText.2=Optimizasiya səviyyəsi:
|
compress.selectText.2=Optimization level:
|
||||||
compress.selectText.3=4 (Mətn şəkilləri üçün yaxşı deyil)
|
compress.selectText.3=4 (Terrible for text images)
|
||||||
compress.selectText.4=Avto mod - PDF-in dəqiq ölçüsünü əldə etmək üçün keyfiyyəti avtomatik tənzimləyir
|
compress.selectText.4=Auto mode - Auto adjusts quality to get PDF to exact size
|
||||||
compress.selectText.5=Gözlənilən PDF Ölçüsü (məsələn, 25MB, 10.8MB, 25KB)
|
compress.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
|
||||||
compress.submit=Sıxışdır
|
compress.submit=Compress
|
||||||
|
|
||||||
|
|
||||||
#Add image
|
#Add image
|
||||||
@@ -923,35 +919,35 @@ merge.submit=Birləşdirin
|
|||||||
|
|
||||||
|
|
||||||
#pdfOrganiser
|
#pdfOrganiser
|
||||||
pdfOrganiser.title=Səhifə Tənzimləyicisi
|
pdfOrganiser.title=Page Organiser
|
||||||
pdfOrganiser.header=PDF Səhifə Tənzimləyicisi
|
pdfOrganiser.header=PDF Page Organiser
|
||||||
pdfOrganiser.submit=Səhifələri Yenidən Təşkil Edin
|
pdfOrganiser.submit=Rearrange Pages
|
||||||
pdfOrganiser.mode=Rejim
|
pdfOrganiser.mode=Mode
|
||||||
pdfOrganiser.mode.1=Fərdi Səhifə Düzülüşü
|
pdfOrganiser.mode.1=Custom Page Order
|
||||||
pdfOrganiser.mode.2=Tərs Düzülüş
|
pdfOrganiser.mode.2=Reverse Order
|
||||||
pdfOrganiser.mode.3=İkitərəfli Çeşidləmə
|
pdfOrganiser.mode.3=Duplex Sort
|
||||||
pdfOrganiser.mode.4=Kitabça Çeşidləmə
|
pdfOrganiser.mode.4=Booklet Sort
|
||||||
pdfOrganiser.mode.5=Yan Tikiş Kitabçasının Çeşidlənməsi
|
pdfOrganiser.mode.5=Side Stitch Booklet Sort
|
||||||
pdfOrganiser.mode.6=Tək-Cüt Bölünmə
|
pdfOrganiser.mode.6=Odd-Even Split
|
||||||
pdfOrganiser.mode.7=Birincini Sil
|
pdfOrganiser.mode.7=Remove First
|
||||||
pdfOrganiser.mode.8=Sonuncunu Sil
|
pdfOrganiser.mode.8=Remove Last
|
||||||
pdfOrganiser.mode.9=Birinci və Sonuncunu Sil
|
pdfOrganiser.mode.9=Remove First and Last
|
||||||
pdfOrganiser.mode.10=Tək-Cüt Birləşdirmə
|
pdfOrganiser.mode.10=Odd-Even Merge
|
||||||
pdfOrganiser.placeholder=(məs., 1,3,2 və ya 4-8,2,10-12 və ya 2n-1)
|
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
|
||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=PDF Multi-Alət
|
multiTool.title=PDF Multi Tool
|
||||||
multiTool.header=PDF Multi-Alət
|
multiTool.header=PDF Multi Tool
|
||||||
multiTool.uploadPrompts=Fayl Adı
|
multiTool.uploadPrompts=File Name
|
||||||
multiTool.selectAll=Hamısını Seç
|
multiTool.selectAll=Select All
|
||||||
multiTool.deselectAll=Hamısını Seçməni Ləğv Et
|
multiTool.deselectAll=Deselect All
|
||||||
multiTool.selectPages=Səhifə Seçimi
|
multiTool.selectPages=Page Select
|
||||||
multiTool.selectedPages=Seçilmiş Səhifələr
|
multiTool.selectedPages=Selected Pages
|
||||||
multiTool.page=Səhifə
|
multiTool.page=Page
|
||||||
multiTool.deleteSelected=Seçilmişi Sil
|
multiTool.deleteSelected=Delete Selected
|
||||||
multiTool.downloadAll=İxrac Et
|
multiTool.downloadAll=Export
|
||||||
multiTool.downloadSelected=Seçilmişi İxrac Et
|
multiTool.downloadSelected=Export Selected
|
||||||
|
|
||||||
multiTool.insertPageBreak=Insert Page Break
|
multiTool.insertPageBreak=Insert Page Break
|
||||||
multiTool.addFile=Add File
|
multiTool.addFile=Add File
|
||||||
@@ -961,22 +957,10 @@ multiTool.split=Split
|
|||||||
multiTool.moveLeft=Move Left
|
multiTool.moveLeft=Move Left
|
||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Seçilmiş Səhifə(lər)
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=Bu xüsusiyyət bizim <a href="{0}">multi-alət səhifə</a>mizdə də mövcuddur. Əlavə xüsusiyyətlər və səhifə-səhifə interfeys üçün sınaqdan keçirin!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=PDF-ə baxın
|
viewPdf.title=PDF-ə baxın
|
||||||
@@ -998,32 +982,32 @@ rotate.submit=Fırladın
|
|||||||
|
|
||||||
|
|
||||||
#split-pdfs
|
#split-pdfs
|
||||||
split.title=PDF-i Bölün
|
split.title=Split PDF
|
||||||
split.header=PDF-i Bölün
|
split.header=Split PDF
|
||||||
split.desc.1=Seçdiyiniz Nömrələr Bölmək İstədiyiniz Səhifə Nömrəsidir
|
split.desc.1=The numbers you select are the page number you wish to do a split on
|
||||||
split.desc.2=Beləliklə, 1,3,7-9 Seçimi 10 Səhifəlik Sənədi 6 Ayrı PDF-ə Böləcək:
|
split.desc.2=As such selecting 1,3,7-9 would split a 10 page document into 6 separate PDFS with:
|
||||||
split.desc.3=Sənəd #1: Səhifə 1
|
split.desc.3=Document #1: Page 1
|
||||||
split.desc.4=Sənəd #2: Səhifə 2 və 3
|
split.desc.4=Document #2: Page 2 and 3
|
||||||
split.desc.5=Sənəd #3: Səhifə 4, 5, 6 və 7
|
split.desc.5=Document #3: Page 4, 5, 6 and 7
|
||||||
split.desc.6=Sənəd #4: Səhifə 8
|
split.desc.6=Document #4: Page 8
|
||||||
split.desc.7=Sənəd #5: Səhifə 9
|
split.desc.7=Document #5: Page 9
|
||||||
split.desc.8=Sənəd #6: Səhifə 10
|
split.desc.8=Document #6: Page 10
|
||||||
split.splitPages=Bölünəcək Səhifələri Daxil Edin:
|
split.splitPages=Enter pages to split on:
|
||||||
split.submit=Bölün
|
split.submit=Split
|
||||||
|
|
||||||
|
|
||||||
#merge
|
#merge
|
||||||
imageToPDF.title=Şəkli PDF-ə
|
imageToPDF.title=Image to PDF
|
||||||
imageToPDF.header=Şəkli PDF-ə
|
imageToPDF.header=Image to PDF
|
||||||
imageToPDF.submit=Çevir
|
imageToPDF.submit=Convert
|
||||||
imageToPDF.selectLabel=Şəkil Uyğunluğu Seçimləri
|
imageToPDF.selectLabel=Image Fit Options
|
||||||
imageToPDF.fillPage=Səhifəni Doldur
|
imageToPDF.fillPage=Fill Page
|
||||||
imageToPDF.fitDocumentToImage=Şəklə Uyğun Səhifə
|
imageToPDF.fitDocumentToImage=Fit Page to Image
|
||||||
imageToPDF.maintainAspectRatio=Aspekt Nisbətlərini Qoruyun
|
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
|
||||||
imageToPDF.selectText.2=PDF-i Avtomatik Fırlat
|
imageToPDF.selectText.2=Auto rotate PDF
|
||||||
imageToPDF.selectText.3=Çoxsaylı Fayl Məntiqi (Yalnız Birdən Çox Şəkil İlə İşləyərkən Aktivdir)
|
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
|
||||||
imageToPDF.selectText.4=Tək Bir PDF-ə Birləşdir
|
imageToPDF.selectText.4=Merge into single PDF
|
||||||
imageToPDF.selectText.5=Ayrı PDF-lərə Çevirin
|
imageToPDF.selectText.5=Convert to separate PDFs
|
||||||
|
|
||||||
|
|
||||||
#pdfToImage
|
#pdfToImage
|
||||||
@@ -1042,98 +1026,97 @@ pdfToImage.info=Python Yüklü Deyil.WebP Çevirməsi Üçün Vacibdir
|
|||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
addPassword.title=Şifr Əlavə Et
|
addPassword.title=Add Password
|
||||||
addPassword.header=Şifr Əlavə Et (Şifrləmə)
|
addPassword.header=Add password (Encrypt)
|
||||||
addPassword.selectText.1=Şifrlənəcək PDF-i seç
|
addPassword.selectText.1=Select PDF to encrypt
|
||||||
addPassword.selectText.2=İstifadəçi Şifri
|
addPassword.selectText.2=User Password
|
||||||
addPassword.selectText.3=Şifrləmə Açarı Uzunluğu
|
addPassword.selectText.3=Encryption Key Length
|
||||||
addPassword.selectText.4=Böyük dəyərlər daha güclüdür, lakin kiçik dəyərlərin uyğunluğu yüksəkdir.
|
addPassword.selectText.4=Higher values are stronger, but lower values have better compatibility.
|
||||||
addPassword.selectText.5=Təyin olunacaq icazə (Sahib (Owner) Şifri ilə birgə istifadə olunması tövsiyə olunur.)
|
addPassword.selectText.5=Permissions to set (Recommended to be used along with Owner password)
|
||||||
addPassword.selectText.6=Sənədin strukturunun dəyişilməsinin qarşısını al
|
addPassword.selectText.6=Prevent assembly of document
|
||||||
addPassword.selectText.7=Məzmun xaric edilməsinin qarşısını al
|
addPassword.selectText.7=Prevent content extraction
|
||||||
addPassword.selectText.8=Əlçatanlıq üçün xaricetmənin qarşısını al
|
addPassword.selectText.8=Prevent extraction for accessibility
|
||||||
addPassword.selectText.9=Anketin doldurulmasının qarşısını al
|
addPassword.selectText.9=Prevent filling in form
|
||||||
addPassword.selectText.10=Modifikasiyanın qarşısını al
|
addPassword.selectText.10=Prevent modification
|
||||||
addPassword.selectText.11=Sitat modifikasiyasının qarşısını al
|
addPassword.selectText.11=Prevent annotation modification
|
||||||
addPassword.selectText.12=Çap etmənin qarşısını al
|
addPassword.selectText.12=Prevent printing
|
||||||
addPassword.selectText.13=Müxtəlif formatların çap edilməsinin qarşısını al
|
addPassword.selectText.13=Prevent printing different formats
|
||||||
addPassword.selectText.14=Sahib Şifri
|
addPassword.selectText.14=Owner Password
|
||||||
addPassword.selectText.15=Sənəd açıldıqdan sonra onunla nə edilə biləcəyini limitləndir (Bütün oxuyucular dəstəkləmir)
|
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||||
addPassword.selectText.16=Sənədin özünün açılmağını limitləndirir
|
addPassword.selectText.16=Restricts the opening of the document itself
|
||||||
addPassword.submit=Şifrlə
|
addPassword.submit=Encrypt
|
||||||
|
|
||||||
|
|
||||||
#watermark
|
#watermark
|
||||||
watermark.title=Watermark Əlavə Et
|
watermark.title=Add Watermark
|
||||||
watermark.header=Watermark Əlavə Et
|
watermark.header=Add Watermark
|
||||||
watermark.customColor=Fərdi Mətn Rəngi
|
watermark.selectText.1=Select PDF to add watermark to:
|
||||||
watermark.selectText.1=Watermark əlavə olunacaq PDF-i seç
|
watermark.selectText.2=Watermark Text:
|
||||||
watermark.selectText.2=Watermark Mətni:
|
watermark.selectText.3=Font Size:
|
||||||
watermark.selectText.3=Şrift Ölçüsü:
|
watermark.selectText.4=Rotation (0-360):
|
||||||
watermark.selectText.4=Fırlatma (0-360):
|
watermark.selectText.5=widthSpacer (Space between each watermark horizontally):
|
||||||
watermark.selectText.5=enBoşluq (Üfuqi olaraq watermark-lar arasındakı məsafə):
|
watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||||
watermark.selectText.6=uzunluqBoşluq (Şaquli olaraq watermark-lar arasındakı məsafə):
|
watermark.selectText.7=Opacity (0% - 100%):
|
||||||
watermark.selectText.7=Şəffaflıq (0% - 100%):
|
watermark.selectText.8=Watermark Type:
|
||||||
watermark.selectText.8=Watermark Tipi:
|
watermark.selectText.9=Watermark Image:
|
||||||
watermark.selectText.9=Watermark Şəkili:
|
watermark.selectText.10=Convert PDF to PDF-Image
|
||||||
watermark.selectText.10=PDF-i PDF-Şəkil-ə çevir
|
watermark.submit=Add Watermark
|
||||||
watermark.submit=Watermark Əlavə Et
|
watermark.type.1=Text
|
||||||
watermark.type.1=Mətn
|
watermark.type.2=Image
|
||||||
watermark.type.2=Şəkil
|
|
||||||
|
|
||||||
|
|
||||||
#Change permissions
|
#Change permissions
|
||||||
permissions.title=İcazələri Dəyişdir
|
permissions.title=Change Permissions
|
||||||
permissions.header=İcazələri Dəyişdir
|
permissions.header=Change Permissions
|
||||||
permissions.warning=Bu İcazələrin Dəyişməz Olması İlə Bağlı Xəbərdarlıq Edərək, Onları Parol Əlavə Et Səhifəsi Vasitəsilə Parolla Təyin Etmək Tövsiyə Olunur.
|
permissions.warning=Warning to have these permissions be unchangeable it is recommended to set them with a password via the add-password page
|
||||||
permissions.selectText.1=İcazələri Dəyişdirmək Üçün PDF-i Seç
|
permissions.selectText.1=Select PDF to change permissions
|
||||||
permissions.selectText.2=Tənzimlənmiş İcazələr
|
permissions.selectText.2=Permissions to set
|
||||||
permissions.selectText.3=Sənədin Yığılmasının Qarşısını Al
|
permissions.selectText.3=Prevent assembly of document
|
||||||
permissions.selectText.4=Məzmunun Çıxarılmasının Qarşısını Al
|
permissions.selectText.4=Prevent content extraction
|
||||||
permissions.selectText.5=Əlçatanlıq Üçün Çıxarılmasının Qarşısını Alın
|
permissions.selectText.5=Prevent extraction for accessibility
|
||||||
permissions.selectText.6=Formanın Doldurulmasının Qarşısını Alır
|
permissions.selectText.6=Prevent filling in form
|
||||||
permissions.selectText.7=Modifikasiyanın Qarşısını Al
|
permissions.selectText.7=Prevent modification
|
||||||
permissions.selectText.8=Annotasiyanın Dəyişdirilməsinin Qarşısını Almaq
|
permissions.selectText.8=Prevent annotation modification
|
||||||
permissions.selectText.9=Çapın Qarşısını Al
|
permissions.selectText.9=Prevent printing
|
||||||
permissions.selectText.10=Fərqli Formatlarda Çapın Qarşısını Al
|
permissions.selectText.10=Prevent printing different formats
|
||||||
permissions.submit=Dəyiş
|
permissions.submit=Change
|
||||||
|
|
||||||
|
|
||||||
#remove password
|
#remove password
|
||||||
removePassword.title=Şifri Sil
|
removePassword.title=Remove password
|
||||||
removePassword.header=Şifri Sil (Deşifr)
|
removePassword.header=Remove password (Decrypt)
|
||||||
removePassword.selectText.1=Deşifr Üçün PDF-i Seç
|
removePassword.selectText.1=Select PDF to Decrypt
|
||||||
removePassword.selectText.2=Şifr
|
removePassword.selectText.2=Password
|
||||||
removePassword.submit=Sil
|
removePassword.submit=Remove
|
||||||
|
|
||||||
|
|
||||||
#changeMetadata
|
#changeMetadata
|
||||||
changeMetadata.title=Metadata-nı Dəyiş
|
changeMetadata.title=Change Metadata
|
||||||
changeMetadata.header=Metadata-nı Dəyiş
|
changeMetadata.header=Change Metadata
|
||||||
changeMetadata.selectText.1=Dəyişmək istədiyiniz dəyişənləri redaktə edin
|
changeMetadata.selectText.1=Please edit the variables you wish to change
|
||||||
changeMetadata.selectText.2=Bütün Metadata-nı Sil
|
changeMetadata.selectText.2=Delete all metadata
|
||||||
changeMetadata.selectText.3=Fərdi Metadatanı göstərin:
|
changeMetadata.selectText.3=Show Custom Metadata:
|
||||||
changeMetadata.author=Müəllif:
|
changeMetadata.author=Author:
|
||||||
changeMetadata.creationDate=Yaradılma Tarixi (yyyy/MM/dd HH:mm:ss):
|
changeMetadata.creationDate=Creation Date (yyyy/MM/dd HH:mm:ss):
|
||||||
changeMetadata.creator=Yaradıcı:
|
changeMetadata.creator=Creator:
|
||||||
changeMetadata.keywords=Açar Sözlər:
|
changeMetadata.keywords=Keywords:
|
||||||
changeMetadata.modDate=Dəyişiklik Tarixi (yyyy/MM/dd HH:mm:ss):
|
changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss):
|
||||||
changeMetadata.producer=İstehsalçı:
|
changeMetadata.producer=Producer:
|
||||||
changeMetadata.subject=Mövzu:
|
changeMetadata.subject=Subject:
|
||||||
changeMetadata.trapped=Tələ:
|
changeMetadata.trapped=Trapped:
|
||||||
changeMetadata.selectText.4=Digər Metadata:
|
changeMetadata.selectText.4=Other Metadata:
|
||||||
changeMetadata.selectText.5=Xüsusi Metadata girişi əlavə edin
|
changeMetadata.selectText.5=Add Custom Metadata Entry
|
||||||
changeMetadata.submit=Dəyiş
|
changeMetadata.submit=Change
|
||||||
|
|
||||||
|
|
||||||
#pdfToPDFA
|
#pdfToPDFA
|
||||||
pdfToPDFA.title=PDF-i PDF/A-ya
|
pdfToPDFA.title=PDF To PDF/A
|
||||||
pdfToPDFA.header=PDF-i PDF/A-ya
|
pdfToPDFA.header=PDF To PDF/A
|
||||||
pdfToPDFA.credit=Bu Servis PDF/A Çevirmək Üçün ghostscript İşlədir
|
pdfToPDFA.credit=This service uses qpdf for PDF/A conversion
|
||||||
pdfToPDFA.submit=Çevir
|
pdfToPDFA.submit=Convert
|
||||||
pdfToPDFA.tip=Hazırda Birdən Çox Giriş Üçün İşləmir
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Çıxış Formatı
|
pdfToPDFA.outputFormat=Output format
|
||||||
pdfToPDFA.pdfWithDigitalSignature=PDF Rəqəmsal İmza Ehtiva Edir.Bu, növbəti addımda silinəcək.
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Səviyyəsi: Bölmə üçün istifadə ediləcə
|
|||||||
splitByChapters.desc.3=Metadatanı daxil edin: Əgər yoxlanılıbsa, orijinal PDF-in metadatası hər bir bölünmüş PDF-ə daxil ediləcək.
|
splitByChapters.desc.3=Metadatanı daxil edin: Əgər yoxlanılıbsa, orijinal PDF-in metadatası hər bir bölünmüş PDF-ə daxil ediləcək.
|
||||||
splitByChapters.desc.4=Allow Duplicates: Dublikatlara icazə verin: Əgər işarələnərsə, eyni səhifədə birdən çox bookmarka ayrı-ayrı PDF sənədləri yaratmağa icazə verin.
|
splitByChapters.desc.4=Allow Duplicates: Dublikatlara icazə verin: Əgər işarələnərsə, eyni səhifədə birdən çox bookmarka ayrı-ayrı PDF sənədləri yaratmağa icazə verin.
|
||||||
splitByChapters.submit=PDF-i Ayır
|
splitByChapters.submit=PDF-i Ayır
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Buraxılışlar
|
|
||||||
releases.title=Buraxılış Qeydləri
|
|
||||||
releases.header=Buraxılış Qeydləri
|
|
||||||
releases.current.version=Hazırki Buraxılış
|
|
||||||
releases.note=Buraxılış Qeydləri yalnız ingiliscə mövcuddur
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Разделете PDF по глави
|
|||||||
home.splitPdfByChapters.desc=Разделете PDF на множество файлове въз основа на неговата структура на глави.
|
home.splitPdfByChapters.desc=Разделете PDF на множество файлове въз основа на неговата структура на глави.
|
||||||
splitPdfByChapters.tags=разделяне, глави, отметки, организиране
|
splitPdfByChapters.tags=разделяне, глави, отметки, организиране
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Замени-инвертиране-на-цвят
|
replace-color.title=Замени-инвертиране-на-цвят
|
||||||
replace-color.header=Замяна-инвертиране на цвят PDF
|
replace-color.header=Замяна-инвертиране на цвят PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Шифроване
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Добавяне на воден знак
|
watermark.title=Добавяне на воден знак
|
||||||
watermark.header=Добавяне на воден знак
|
watermark.header=Добавяне на воден знак
|
||||||
watermark.customColor=Персонализиран цвят на текста
|
|
||||||
watermark.selectText.1=Изберете PDF, към който да добавите воден знак:
|
watermark.selectText.1=Изберете PDF, към който да добавите воден знак:
|
||||||
watermark.selectText.2=Текст на воден знак:
|
watermark.selectText.2=Текст на воден знак:
|
||||||
watermark.selectText.3=Размер на шрифта:
|
watermark.selectText.3=Размер на шрифта:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Ниво на отметка: Изберете нивот
|
|||||||
splitByChapters.desc.3=Включване на метаданни: Ако е отметнато, метаданните на оригиналния PDF ще бъдат включени във всеки разделен PDF.
|
splitByChapters.desc.3=Включване на метаданни: Ако е отметнато, метаданните на оригиналния PDF ще бъдат включени във всеки разделен PDF.
|
||||||
splitByChapters.desc.4=Разрешаване на дубликати: Ако е отметнато, позволява множество отметки на една и съща страница за създаване на отделни PDF файлове.
|
splitByChapters.desc.4=Разрешаване на дубликати: Ако е отметнато, позволява множество отметки на една и съща страница за създаване на отделни PDF файлове.
|
||||||
splitByChapters.submit=Разделяне на PDF
|
splitByChapters.submit=Разделяне на PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Divideix PDF per Capítols
|
|||||||
home.splitPdfByChapters.desc=Divideix un PDF en múltiples fitxers segons la seva estructura de capítols.
|
home.splitPdfByChapters.desc=Divideix un PDF en múltiples fitxers segons la seva estructura de capítols.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Reemplaça-Inverteix-Color
|
replace-color.title=Reemplaça-Inverteix-Color
|
||||||
replace-color.header=Reemplaça-Inverteix Color en PDF
|
replace-color.header=Reemplaça-Inverteix Color en PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Encripta
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Afegir Marca d'Aigua
|
watermark.title=Afegir Marca d'Aigua
|
||||||
watermark.header=Afegir Marca d'Aigua
|
watermark.header=Afegir Marca d'Aigua
|
||||||
watermark.customColor=Color de Text Personalitzat
|
|
||||||
watermark.selectText.1=Selecciona el PDF per afegir la Marca d'Aigua:
|
watermark.selectText.1=Selecciona el PDF per afegir la Marca d'Aigua:
|
||||||
watermark.selectText.2=Text de la Marca d'Aigua
|
watermark.selectText.2=Text de la Marca d'Aigua
|
||||||
watermark.selectText.3=Mida de la Font:
|
watermark.selectText.3=Mida de la Font:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Nivell de Marcadors: Tria el nivell de marcadors que s'ut
|
|||||||
splitByChapters.desc.3=Incloure Metadades: Si està marcat, les metadades del PDF original s'inclouran en cada PDF dividit.
|
splitByChapters.desc.3=Incloure Metadades: Si està marcat, les metadades del PDF original s'inclouran en cada PDF dividit.
|
||||||
splitByChapters.desc.4=Permetre Duplicats: Si està marcat, permet diversos marcadors a la mateixa pàgina per crear PDFs separats.
|
splitByChapters.desc.4=Permetre Duplicats: Si està marcat, permet diversos marcadors a la mateixa pàgina per crear PDFs separats.
|
||||||
splitByChapters.submit=Divideix PDF
|
splitByChapters.submit=Divideix PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Rozdělit PDF podle kapitol
|
|||||||
home.splitPdfByChapters.desc=Rozdělit PDF do více souborů na základě jeho struktury kapitol.
|
home.splitPdfByChapters.desc=Rozdělit PDF do více souborů na základě jeho struktury kapitol.
|
||||||
splitPdfByChapters.tags=rozdělení, kapitoly, zápisky, organizace
|
splitPdfByChapters.tags=rozdělení, kapitoly, zápisky, organizace
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Nahradit inverzní barvu PDF
|
replace-color.header=Nahradit inverzní barvu PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Šifrovat
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Přidat vodoznak
|
watermark.title=Přidat vodoznak
|
||||||
watermark.header=Přidat vodoznak
|
watermark.header=Přidat vodoznak
|
||||||
watermark.customColor=Vlastní barva textu
|
|
||||||
watermark.selectText.1=Vyberte PDF, ke kterému chcete přidat vodoznak:
|
watermark.selectText.1=Vyberte PDF, ke kterému chcete přidat vodoznak:
|
||||||
watermark.selectText.2=Text vodoznaku:
|
watermark.selectText.2=Text vodoznaku:
|
||||||
watermark.selectText.3=Velikost písma:
|
watermark.selectText.3=Velikost písma:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Úroveň záhlaví: Zvolte úroveň záhlaví pro použit
|
|||||||
splitByChapters.desc.3=Zahrnout metadatů: Pokud je zaškrtnuto, původní metadata PDF souboru budou zahrnuty do každého odděleného PDF souboru.
|
splitByChapters.desc.3=Zahrnout metadatů: Pokud je zaškrtnuto, původní metadata PDF souboru budou zahrnuty do každého odděleného PDF souboru.
|
||||||
splitByChapters.desc.4=Povolit duplicitní záznamy: Pokud je zaškrtnuto, návštěvníci mohou vytvořit samostatné PDF soubory z více záhlaví na stejné straně.
|
splitByChapters.desc.4=Povolit duplicitní záznamy: Pokud je zaškrtnuto, návštěvníci mohou vytvořit samostatné PDF soubory z více záhlaví na stejné straně.
|
||||||
splitByChapters.submit=Podělit se PDF
|
splitByChapters.submit=Podělit se PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Partitioner PDF efter kapitler
|
|||||||
home.splitPdfByChapters.desc=Partitioner en PDF i flere filer baseret på dens kapitelstruktur.
|
home.splitPdfByChapters.desc=Partitioner en PDF i flere filer baseret på dens kapitelstruktur.
|
||||||
splitPdfByChapters.tags=partitionering,kapitler,merker,organisering
|
splitPdfByChapters.tags=partitionering,kapitler,merker,organisering
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Erstat-omgivende Farve PDF
|
replace-color.header=Erstat-omgivende Farve PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Kryptér
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Tilføj Vandmærke
|
watermark.title=Tilføj Vandmærke
|
||||||
watermark.header=Tilføj Vandmærke
|
watermark.header=Tilføj Vandmærke
|
||||||
watermark.customColor=Brugerdefineret Tekstfarve
|
|
||||||
watermark.selectText.1=Vælg PDF til at tilføje vandmærke:
|
watermark.selectText.1=Vælg PDF til at tilføje vandmærke:
|
||||||
watermark.selectText.2=Vandmærketekst:
|
watermark.selectText.2=Vandmærketekst:
|
||||||
watermark.selectText.3=Skriftstørrelse:
|
watermark.selectText.3=Skriftstørrelse:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bogmærke niveau: Vælg nivået af bogmærker, der skal b
|
|||||||
splitByChapters.desc.3=Inkluder metadata: Hvis markeret, vil den originale PDF's metadata inkluderes i hver splitterdels PDF.
|
splitByChapters.desc.3=Inkluder metadata: Hvis markeret, vil den originale PDF's metadata inkluderes i hver splitterdels PDF.
|
||||||
splitByChapters.desc.4=Tillad duplikater: Hvis markeret, tillader det flere bogmærker på samme side til at oprette separate PDF'er.
|
splitByChapters.desc.4=Tillad duplikater: Hvis markeret, tillader det flere bogmærker på samme side til at oprette separate PDF'er.
|
||||||
splitByChapters.submit=Splitter PDF
|
splitByChapters.submit=Splitter PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ navbar.search=Suche
|
|||||||
navbar.sections.organize=Organisieren
|
navbar.sections.organize=Organisieren
|
||||||
navbar.sections.convertTo=In PDF konvertieren
|
navbar.sections.convertTo=In PDF konvertieren
|
||||||
navbar.sections.convertFrom=Konvertieren von PDF
|
navbar.sections.convertFrom=Konvertieren von PDF
|
||||||
navbar.sections.security=Signieren und Sicherheit
|
navbar.sections.security=Zeichen und Sicherheit
|
||||||
navbar.sections.advance=Erweiterte Funktionen
|
navbar.sections.advance=Fortschrittlich
|
||||||
navbar.sections.edit=Anzeigen und Bearbeiten
|
navbar.sections.edit=Anzeigen und Bearbeiten
|
||||||
navbar.sections.popular=Beliebt
|
navbar.sections.popular=Beliebt
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ database.fileNullOrEmpty=Datei darf nicht null oder leer sein
|
|||||||
database.failedImportFile=Dateiimport fehlgeschlagen
|
database.failedImportFile=Dateiimport fehlgeschlagen
|
||||||
|
|
||||||
session.expired=Ihre Sitzung ist abgelaufen. Bitte laden Sie die Seite neu und versuchen Sie es erneut.
|
session.expired=Ihre Sitzung ist abgelaufen. Bitte laden Sie die Seite neu und versuchen Sie es erneut.
|
||||||
session.refreshPage=Seite aktualisieren
|
session.refreshPage=Refresh Page
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=PDF-Datei nach Kapiteln aufteilen
|
|||||||
home.splitPdfByChapters.desc=Aufteilung einer PDF-Datei in mehrere Dateien auf Basis der Kapitelstruktur.
|
home.splitPdfByChapters.desc=Aufteilung einer PDF-Datei in mehrere Dateien auf Basis der Kapitelstruktur.
|
||||||
splitPdfByChapters.tags=aufteilen,kapitel,lesezeichen,organisieren
|
splitPdfByChapters.tags=aufteilen,kapitel,lesezeichen,organisieren
|
||||||
|
|
||||||
home.validateSignature.title=PDF-Signatur überprüfen
|
|
||||||
home.validateSignature.desc=Digitale Signaturen und Zertifikate in PDF-Dokumenten überprüfen
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,digitale signatur,signatur validieren,überprüfen,Zertifikat,cert
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Farbe Ersetzen-Invertieren
|
replace-color.title=Farbe Ersetzen-Invertieren
|
||||||
replace-color.header=Farb-PDF Ersetzen-Invertieren
|
replace-color.header=Farb-PDF Ersetzen-Invertieren
|
||||||
@@ -822,12 +818,12 @@ sign.save=Signature speichern
|
|||||||
sign.personalSigs=Persönliche Signaturen
|
sign.personalSigs=Persönliche Signaturen
|
||||||
sign.sharedSigs=Geteilte Signaturen
|
sign.sharedSigs=Geteilte Signaturen
|
||||||
sign.noSavedSigs=Es wurden keine gespeicherten Signaturen gefunden
|
sign.noSavedSigs=Es wurden keine gespeicherten Signaturen gefunden
|
||||||
sign.addToAll=Zu allen Seiten hinzufügen
|
sign.addToAll=Add to all pages
|
||||||
sign.delete=Löschen
|
sign.delete=Delete
|
||||||
sign.first=Erste Seite
|
sign.first=First page
|
||||||
sign.last=Letzte Seite
|
sign.last=Last page
|
||||||
sign.next=Nächste Seite
|
sign.next=Next page
|
||||||
sign.previous=Vorherige Seite
|
sign.previous=Previous page
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
repair.title=Reparieren
|
repair.title=Reparieren
|
||||||
@@ -953,27 +949,15 @@ multiTool.deleteSelected=Auswahl löschen
|
|||||||
multiTool.downloadAll=Downloaden
|
multiTool.downloadAll=Downloaden
|
||||||
multiTool.downloadSelected=Auswahl downloaden
|
multiTool.downloadSelected=Auswahl downloaden
|
||||||
|
|
||||||
multiTool.insertPageBreak=Seitenumbruch einfügen
|
multiTool.insertPageBreak=Insert Page Break
|
||||||
multiTool.addFile=Datei hinzufügen
|
multiTool.addFile=Add File
|
||||||
multiTool.rotateLeft=Nach links drehen
|
multiTool.rotateLeft=Rotate Left
|
||||||
multiTool.rotateRight=Nach rechts drehen
|
multiTool.rotateRight=Rotate Right
|
||||||
multiTool.split=Teilen
|
multiTool.split=Split
|
||||||
multiTool.moveLeft=Nach links verschieben
|
multiTool.moveLeft=Move Left
|
||||||
multiTool.moveRight=Nach rechts verschieben
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Löschen
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Ausgewählte Seite(n)
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Rückgängig machen
|
|
||||||
multiTool.redo=Wiederherstellen
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=Diese Funktion ist auch auf unserer <a href="{0}">PDF-Multitool-Seite</a> verfügbar. Probieren Sie sie aus, denn sie bietet eine verbesserte Benutzeroberfläche und zusätzliche Funktionen!
|
multiTool-advert.message=Diese Funktion ist auch auf unserer <a href="{0}">PDF-Multitool-Seite</a> verfügbar. Probieren Sie sie aus, denn sie bietet eine verbesserte Benutzeroberfläche und zusätzliche Funktionen!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Verschlüsseln
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Wasserzeichen hinzufügen
|
watermark.title=Wasserzeichen hinzufügen
|
||||||
watermark.header=Wasserzeichen hinzufügen
|
watermark.header=Wasserzeichen hinzufügen
|
||||||
watermark.customColor=Benutzerdefinierte Textfarbe
|
|
||||||
watermark.selectText.1=PDF auswählen, dem ein Wasserzeichen hinzugefügt werden soll:
|
watermark.selectText.1=PDF auswählen, dem ein Wasserzeichen hinzugefügt werden soll:
|
||||||
watermark.selectText.2=Wasserzeichen Text:
|
watermark.selectText.2=Wasserzeichen Text:
|
||||||
watermark.selectText.3=Schriftgröße:
|
watermark.selectText.3=Schriftgröße:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Lesezeichenebene: Wählen Sie die Ebene der Lesezeichen,
|
|||||||
splitByChapters.desc.3=Metadaten einschließen: Wenn diese Option aktiviert ist, werden die Metadaten der ursprünglichen PDF-Datei in jede aufgeteilte PDF-Datei übernommen.
|
splitByChapters.desc.3=Metadaten einschließen: Wenn diese Option aktiviert ist, werden die Metadaten der ursprünglichen PDF-Datei in jede aufgeteilte PDF-Datei übernommen.
|
||||||
splitByChapters.desc.4=Duplikate erlauben: Wenn diese Option aktiviert ist, können mehrere Lesezeichen auf derselben Seite separate PDF Dateien erstellen.
|
splitByChapters.desc.4=Duplikate erlauben: Wenn diese Option aktiviert ist, können mehrere Lesezeichen auf derselben Seite separate PDF Dateien erstellen.
|
||||||
splitByChapters.submit=PDF teilen
|
splitByChapters.submit=PDF teilen
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Klicken
|
|
||||||
fileChooser.or=oder
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Datei(en) hierhin Ziehen & Fallenlassen
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Veröffentlichungen
|
|
||||||
releases.title=Versionshinweise
|
|
||||||
releases.header=Versionshinweise
|
|
||||||
releases.current.version=Aktuelle Version
|
|
||||||
releases.note=Versionshinweise sind nur auf Englisch verfügbar
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=PDF-Signaturen überprüfen
|
|
||||||
validateSignature.header=Digitale Signaturen überprüfen
|
|
||||||
validateSignature.selectPDF=Signierte PDF-Datei auswählen
|
|
||||||
validateSignature.submit=Signaturen überprüfen
|
|
||||||
validateSignature.results=Gültigkeitsprüfungsergebnisse
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Unterzeichner
|
|
||||||
validateSignature.date=Datum
|
|
||||||
validateSignature.reason=Grund
|
|
||||||
validateSignature.location=Ort
|
|
||||||
validateSignature.noSignatures=Keine digitalen Signaturen in diesem Dokument gefunden
|
|
||||||
validateSignature.status.valid=Gültig
|
|
||||||
validateSignature.status.invalid=Ungültig
|
|
||||||
validateSignature.chain.invalid=Zertifikatskettenprüfung fehlgeschlagen - kann die Identität des Unterzeichners nicht verifizieren
|
|
||||||
validateSignature.trust.invalid=Zertifikat nicht im Truststore - Quelle kann nicht verifiziert werden
|
|
||||||
validateSignature.cert.expired=Zertifikat ist abgelaufen
|
|
||||||
validateSignature.cert.revoked=Zertifikat wurde widerrufen
|
|
||||||
validateSignature.signature.info=Signaturinformationen
|
|
||||||
validateSignature.signature=Signatur
|
|
||||||
validateSignature.signature.mathValid=Signatur ist mathematisch gültig ABER:
|
|
||||||
validateSignature.selectCustomCert=Benutzerdefinierte Zertifikatsdatei X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Zertifikat Details
|
|
||||||
validateSignature.cert.issuer=Aussteller
|
|
||||||
validateSignature.cert.subject=Betreff
|
|
||||||
validateSignature.cert.serialNumber=Seriennummer
|
|
||||||
validateSignature.cert.validFrom=Gültig von
|
|
||||||
validateSignature.cert.validUntil=Gültig bis
|
|
||||||
validateSignature.cert.algorithm=Algorithmus
|
|
||||||
validateSignature.cert.keySize=Schlüsselgröße
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Schlüsselverwendung
|
|
||||||
validateSignature.cert.selfSigned=Selbstsigniert
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Διχοτομία PDF ανά Περιγραφές
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=διχοτομία,περιγραφές,κεφάλαια,συνορία
|
splitPdfByChapters.tags=διχοτομία,περιγραφές,κεφάλαια,συνορία
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Αντικατάσταση-Αντίστροφη Παθωμένη Πίντσουρ
|
replace-color.header=Αντικατάσταση-Αντίστροφη Παθωμένη Πίντσουρ
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Κρυπτογράφηση
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Προσθήκη Υδατογραφήματος
|
watermark.title=Προσθήκη Υδατογραφήματος
|
||||||
watermark.header=Προσθήκη Υδατογραφήματος
|
watermark.header=Προσθήκη Υδατογραφήματος
|
||||||
watermark.customColor=Προσαρμοσμένο χρώμα κειμένου
|
|
||||||
watermark.selectText.1=Επιλέξτε PDF για την προσθήκη του υδατογραφήματος:
|
watermark.selectText.1=Επιλέξτε PDF για την προσθήκη του υδατογραφήματος:
|
||||||
watermark.selectText.2=Κείμενο Υδατογραφήματος:
|
watermark.selectText.2=Κείμενο Υδατογραφήματος:
|
||||||
watermark.selectText.3=Μέγεθος Κειμένου:
|
watermark.selectText.3=Μέγεθος Κειμένου:
|
||||||
watermark.selectText.4=Περιστροφή (0-360):
|
watermark.selectText.4=Περιστροφή (0-360):
|
||||||
watermark.selectText.5=Width Spacer (Κενό μεταξύ κάθε υδατογραφήματος οριζόντια):
|
watermark.selectText.5=widthSpacer (Κενό μεταξύ κάθε υδατογραφήματος οριζόντια):
|
||||||
watermark.selectText.6=Height Spacer (Κενό μεταξύ κάθε υδατογραφήματος κάθετα):
|
watermark.selectText.6=heightSpacer (Κενό μεταξύ κάθε υδατογραφήματος κάθετα):
|
||||||
watermark.selectText.7=Αδιαφάνεια (Opacity) (0% - 100%):
|
watermark.selectText.7=Αδιαφάνεια (Opacity) (0% - 100%):
|
||||||
watermark.selectText.8=Τύπος Υδατογραφήματος:
|
watermark.selectText.8=Τύπος Υδατογραφήματος:
|
||||||
watermark.selectText.9=Εικόνα Υδατογραφήματος:
|
watermark.selectText.9=Εικόνα Υδατογραφήματος:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Επίπεδο Σήμανσης Σκέψης: Επιλέ
|
|||||||
splitByChapters.desc.3=Πρόσθεση Metadata: Αν επεξεργαστείται, οι αρχικές metadata του PDF θα προστεθούν σε κάθε διαλυμένο PDF.
|
splitByChapters.desc.3=Πρόσθεση Metadata: Αν επεξεργαστείται, οι αρχικές metadata του PDF θα προστεθούν σε κάθε διαλυμένο PDF.
|
||||||
splitByChapters.desc.4=Διάλυση Παρόντων Τίτλων Επιπέδου: Αν επεξεργαστείται, επιτρέπει τη δημιουργία αποκοπών PDF με βάση πλήρως καθορισμένους σήμαντες έδρας.
|
splitByChapters.desc.4=Διάλυση Παρόντων Τίτλων Επιπέδου: Αν επεξεργαστείται, επιτρέπει τη δημιουργία αποκοπών PDF με βάση πλήρως καθορισμένους σήμαντες έδρας.
|
||||||
splitByChapters.submit=Διαλύστε το PDF
|
splitByChapters.submit=Διαλύστε το PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ joinDiscord=Join our Discord server
|
|||||||
seeDockerHub=See Docker Hub
|
seeDockerHub=See Docker Hub
|
||||||
visitGithub=Visit Github Repository
|
visitGithub=Visit Github Repository
|
||||||
donate=Donate
|
donate=Donate
|
||||||
color=Colour
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
pro=Pro
|
||||||
@@ -419,9 +419,9 @@ home.auto-rename.title=Auto Rename PDF File
|
|||||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||||
|
|
||||||
home.adjust-contrast.title=Adjust Colours/Contrast
|
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||||
adjust-contrast.tags=color-correction,tune,modify,enhance,colour-correction
|
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||||
|
|
||||||
home.crop.title=Crop PDF
|
home.crop.title=Crop PDF
|
||||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||||
@@ -488,11 +488,11 @@ overlay-pdfs.tags=Overlay
|
|||||||
|
|
||||||
home.split-by-sections.title=Split PDF by Sections
|
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.desc=Divide each page of a PDF into smaller horizontal and vertical sections
|
||||||
split-by-sections.tags=Section Split, Divide, Customize,Customise
|
split-by-sections.tags=Section Split, Divide, Customize
|
||||||
|
|
||||||
home.AddStampRequest.title=Add Stamp to PDF
|
home.AddStampRequest.title=Add Stamp to PDF
|
||||||
home.AddStampRequest.desc=Add text or add image stamps at set locations
|
home.AddStampRequest.desc=Add text or add image stamps at set locations
|
||||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize,Customise
|
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF to Book
|
home.PDFToBook.title=PDF to Book
|
||||||
@@ -512,27 +512,23 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Advanced Colour options
|
replace-color.title=Advanced Colour options
|
||||||
replace-color.header=Replace-Invert Colour PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Advanced Colour options
|
home.replaceColorPdf.title=Advanced Colour options
|
||||||
home.replaceColorPdf.desc=Replace colour for text and background in PDF and invert full colour of pdf to reduce file size
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Replace Colour,Page operations,Back end,server side
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Replace or Invert colour Options
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Default(Default high contrast colours)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Custom(Customised colours)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colours)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=High contrast colour options
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Choose text Colour
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Choose background Colour
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
@@ -655,7 +651,7 @@ AddStampRequest.position=Position
|
|||||||
AddStampRequest.overrideX=Override X Coordinate
|
AddStampRequest.overrideX=Override X Coordinate
|
||||||
AddStampRequest.overrideY=Override Y Coordinate
|
AddStampRequest.overrideY=Override Y Coordinate
|
||||||
AddStampRequest.customMargin=Custom Margin
|
AddStampRequest.customMargin=Custom Margin
|
||||||
AddStampRequest.customColor=Custom Text Colour
|
AddStampRequest.customColor=Custom Text Color
|
||||||
AddStampRequest.submit=Submit
|
AddStampRequest.submit=Submit
|
||||||
|
|
||||||
|
|
||||||
@@ -787,8 +783,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Compare
|
compare.title=Compare
|
||||||
compare.header=Compare PDFs
|
compare.header=Compare PDFs
|
||||||
compare.highlightColor.1=Highlight Colour 1:
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
compare.highlightColor.2=Highlight Colour 2:
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Compare
|
compare.submit=Compare
|
||||||
@@ -846,7 +842,7 @@ flatten.submit=Flatten
|
|||||||
ScannerImageSplit.selectText.1=Angle Threshold:
|
ScannerImageSplit.selectText.1=Angle Threshold:
|
||||||
ScannerImageSplit.selectText.2=Sets the minimum absolute angle required for the image to be rotated (default: 10).
|
ScannerImageSplit.selectText.2=Sets the minimum absolute angle required for the image to be rotated (default: 10).
|
||||||
ScannerImageSplit.selectText.3=Tolerance:
|
ScannerImageSplit.selectText.3=Tolerance:
|
||||||
ScannerImageSplit.selectText.4=Determines the range of colour variation around the estimated background colour (default: 30).
|
ScannerImageSplit.selectText.4=Determines the range of color variation around the estimated background color (default: 30).
|
||||||
ScannerImageSplit.selectText.5=Minimum Area:
|
ScannerImageSplit.selectText.5=Minimum Area:
|
||||||
ScannerImageSplit.selectText.6=Sets the minimum area threshold for a photo (default: 10000).
|
ScannerImageSplit.selectText.6=Sets the minimum area threshold for a photo (default: 10000).
|
||||||
ScannerImageSplit.selectText.7=Minimum Contour Area:
|
ScannerImageSplit.selectText.7=Minimum Contour Area:
|
||||||
@@ -898,7 +894,7 @@ compress.title=Compress
|
|||||||
compress.header=Compress PDF
|
compress.header=Compress PDF
|
||||||
compress.credit=This service uses qpdf for PDF Compress/Optimisation.
|
compress.credit=This service uses qpdf for PDF Compress/Optimisation.
|
||||||
compress.selectText.1=Manual Mode - From 1 to 4
|
compress.selectText.1=Manual Mode - From 1 to 4
|
||||||
compress.selectText.2=Optimisation level:
|
compress.selectText.2=Optimization level:
|
||||||
compress.selectText.3=4 (Terrible for text images)
|
compress.selectText.3=4 (Terrible for text images)
|
||||||
compress.selectText.4=Auto mode - Auto adjusts quality to get PDF to exact size
|
compress.selectText.4=Auto mode - Auto adjusts quality to get PDF to exact size
|
||||||
compress.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
|
compress.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Encrypt
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Add Watermark
|
watermark.title=Add Watermark
|
||||||
watermark.header=Add Watermark
|
watermark.header=Add Watermark
|
||||||
watermark.customColor=Custom Text Colour
|
|
||||||
watermark.selectText.1=Select PDF to add watermark to:
|
watermark.selectText.1=Select PDF to add watermark to:
|
||||||
watermark.selectText.2=Watermark Text:
|
watermark.selectText.2=Watermark Text:
|
||||||
watermark.selectText.3=Font Size:
|
watermark.selectText.3=Font Size:
|
||||||
watermark.selectText.4=Rotation (0-360):
|
watermark.selectText.4=Rotation (0-360):
|
||||||
watermark.selectText.5=Width Spacer (Space between each watermark horizontally):
|
watermark.selectText.5=widthSpacer (Space between each watermark horizontally):
|
||||||
watermark.selectText.6=Height Spacer (Space between each watermark vertically):
|
watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||||
watermark.selectText.7=Opacity (0% - 100%):
|
watermark.selectText.7=Opacity (0% - 100%):
|
||||||
watermark.selectText.8=Watermark Type:
|
watermark.selectText.8=Watermark Type:
|
||||||
watermark.selectText.9=Watermark Image:
|
watermark.selectText.9=Watermark Image:
|
||||||
@@ -1278,11 +1261,6 @@ splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata
|
|||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
#release notes
|
||||||
releases.footer=Releases
|
releases.footer=Releases
|
||||||
@@ -1290,38 +1268,3 @@ releases.title=Release Notes
|
|||||||
releases.header=Release Notes
|
releases.header=Release Notes
|
||||||
releases.current.version=Current Release
|
releases.current.version=Current Release
|
||||||
releases.note=Release notes are only available in English
|
releases.note=Release notes are only available in English
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Encrypt
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Add Watermark
|
watermark.title=Add Watermark
|
||||||
watermark.header=Add Watermark
|
watermark.header=Add Watermark
|
||||||
watermark.customColor=Custom Text Color
|
|
||||||
watermark.selectText.1=Select PDF to add watermark to:
|
watermark.selectText.1=Select PDF to add watermark to:
|
||||||
watermark.selectText.2=Watermark Text:
|
watermark.selectText.2=Watermark Text:
|
||||||
watermark.selectText.3=Font Size:
|
watermark.selectText.3=Font Size:
|
||||||
watermark.selectText.4=Rotation (0-360):
|
watermark.selectText.4=Rotation (0-360):
|
||||||
watermark.selectText.5=Width Spacer (Space between each watermark horizontally):
|
watermark.selectText.5=widthSpacer (Space between each watermark horizontally):
|
||||||
watermark.selectText.6=Height Spacer (Space between each watermark vertically):
|
watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||||
watermark.selectText.7=Opacity (0% - 100%):
|
watermark.selectText.7=Opacity (0% - 100%):
|
||||||
watermark.selectText.8=Watermark Type:
|
watermark.selectText.8=Watermark Type:
|
||||||
watermark.selectText.9=Watermark Image:
|
watermark.selectText.9=Watermark Image:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Dividir PDF por capítulos
|
|||||||
home.splitPdfByChapters.desc=Divida un PDF en varios archivos según su estructura de capítulos.
|
home.splitPdfByChapters.desc=Divida un PDF en varios archivos según su estructura de capítulos.
|
||||||
splitPdfByChapters.tags=dividir,capítulos,marcadores,organizar
|
splitPdfByChapters.tags=dividir,capítulos,marcadores,organizar
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Reemplazar-Invertir-Color
|
replace-color.title=Reemplazar-Invertir-Color
|
||||||
replace-color.header=Reemplazar-Invertir Color en PDF
|
replace-color.header=Reemplazar-Invertir Color en PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Encriptar
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Añadir marca de agua
|
watermark.title=Añadir marca de agua
|
||||||
watermark.header=Añadir marca de agua
|
watermark.header=Añadir marca de agua
|
||||||
watermark.customColor=Personalizar color de texto
|
|
||||||
watermark.selectText.1=Seleccionar PDF para añadir marca de agua:
|
watermark.selectText.1=Seleccionar PDF para añadir marca de agua:
|
||||||
watermark.selectText.2=Texto de la marca de agua:
|
watermark.selectText.2=Texto de la marca de agua:
|
||||||
watermark.selectText.3=Tamaño de la Fuente:
|
watermark.selectText.3=Tamaño de la Fuente:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Nivel de Marcador: Elige el nivel de marcadores para divi
|
|||||||
splitByChapters.desc.3=Incluir Metadatos: Si está seleccionado, los metadatos del PDF original se incluirán en cada PDF dividido.
|
splitByChapters.desc.3=Incluir Metadatos: Si está seleccionado, los metadatos del PDF original se incluirán en cada PDF dividido.
|
||||||
splitByChapters.desc.4=Permitir Duplicados: Si está seleccionado, permite que múltiples marcadores en la misma página creen archivos PDF separados.
|
splitByChapters.desc.4=Permitir Duplicados: Si está seleccionado, permite que múltiples marcadores en la misma página creen archivos PDF separados.
|
||||||
splitByChapters.submit=Dividir PDF
|
splitByChapters.submit=Dividir PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Enkriptatu
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Gehitu ur-marka
|
watermark.title=Gehitu ur-marka
|
||||||
watermark.header=Gehitu ur-marka
|
watermark.header=Gehitu ur-marka
|
||||||
watermark.customColor=Custom Text Color
|
|
||||||
watermark.selectText.1=Hautatu PDFa ur-marka gehitzeko:
|
watermark.selectText.1=Hautatu PDFa ur-marka gehitzeko:
|
||||||
watermark.selectText.2=Ur-markaren testua:
|
watermark.selectText.2=Ur-markaren testua:
|
||||||
watermark.selectText.3=Letra-tipoaren tamaina:
|
watermark.selectText.3=Letra-tipoaren tamaina:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Séparer un PDF par chapitres
|
|||||||
home.splitPdfByChapters.desc=Séparez un PDF en fichiers multiples en fonction de sa structure par chapitres.
|
home.splitPdfByChapters.desc=Séparez un PDF en fichiers multiples en fonction de sa structure par chapitres.
|
||||||
splitPdfByChapters.tags=séparer,chapitres,split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=séparer,chapitres,split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Remplacer-Inverser-Couleur
|
replace-color.title=Remplacer-Inverser-Couleur
|
||||||
replace-color.header=Remplacer-Inverser Couleur PDF
|
replace-color.header=Remplacer-Inverser Couleur PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Déplacer vers la gauche
|
|||||||
multiTool.moveRight=Déplacer vers la droite
|
multiTool.moveRight=Déplacer vers la droite
|
||||||
multiTool.delete=Supprimer
|
multiTool.delete=Supprimer
|
||||||
multiTool.dragDropMessage=Page(s) sélectionnées
|
multiTool.dragDropMessage=Page(s) sélectionnées
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=Cette fonctionnalité est aussi disponible dans la <a href="{0}">page de l'outil multifonction</a>. Allez-y pour une interface page par page améliorée et des fonctionnalités additionnelles !
|
multiTool-advert.message=Cette fonctionnalité est aussi disponible dans la <a href="{0}">page de l'outil multifonction</a>. Allez-y pour une interface page par page améliorée et des fonctionnalités additionnelles !
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Chiffrer
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Ajouter un filigrane
|
watermark.title=Ajouter un filigrane
|
||||||
watermark.header=Ajouter un filigrane
|
watermark.header=Ajouter un filigrane
|
||||||
watermark.customColor=Couleur de texte personnalisée
|
|
||||||
watermark.selectText.1=PDF auquel ajouter un filigrane
|
watermark.selectText.1=PDF auquel ajouter un filigrane
|
||||||
watermark.selectText.2=Texte du filigrane
|
watermark.selectText.2=Texte du filigrane
|
||||||
watermark.selectText.3=Taille de police
|
watermark.selectText.3=Taille de police
|
||||||
watermark.selectText.4=Rotation (de 0 à 360 degrés)
|
watermark.selectText.4=Rotation (de 0 à 360 degrés)
|
||||||
watermark.selectText.5=Width Spacer (espace entre chaque filigrane horizontalement)
|
watermark.selectText.5=widthSpacer (espace entre chaque filigrane horizontalement)
|
||||||
watermark.selectText.6=Height Spacer (espace entre chaque filigrane verticalement)
|
watermark.selectText.6=heightSpacer (espace entre chaque filigrane verticalement)
|
||||||
watermark.selectText.7=Opacité (de 0% à 100%)
|
watermark.selectText.7=Opacité (de 0% à 100%)
|
||||||
watermark.selectText.8=Type de filigrane
|
watermark.selectText.8=Type de filigrane
|
||||||
watermark.selectText.9=Image du filigrane
|
watermark.selectText.9=Image du filigrane
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Niveau de Signet : Choisissez le niveau de signets à uti
|
|||||||
splitByChapters.desc.3=Inclure les Métadonnées : Si coché, les métadonnées du PDF original seront incluses dans chaque PDF divisé.
|
splitByChapters.desc.3=Inclure les Métadonnées : Si coché, les métadonnées du PDF original seront incluses dans chaque PDF divisé.
|
||||||
splitByChapters.desc.4=Autoriser les Doublons : Si coché, permet à plusieurs signets sur la même page de créer des PDF séparés.
|
splitByChapters.desc.4=Autoriser les Doublons : Si coché, permet à plusieurs signets sur la même page de créer des PDF séparés.
|
||||||
splitByChapters.submit=Diviser le PDF
|
splitByChapters.submit=Diviser le PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,12 +1050,11 @@ addPassword.submit=Criptigh
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Cuir Uisce leis
|
watermark.title=Cuir Uisce leis
|
||||||
watermark.header=Cuir Uisce leis
|
watermark.header=Cuir Uisce leis
|
||||||
watermark.customColor=Dath Téacs Saincheaptha
|
|
||||||
watermark.selectText.1=Roghnaigh PDF chun comhartha uisce a chur leis:
|
watermark.selectText.1=Roghnaigh PDF chun comhartha uisce a chur leis:
|
||||||
watermark.selectText.2=Téacs Comhartha Uisce:
|
watermark.selectText.2=Téacs Comhartha Uisce:
|
||||||
watermark.selectText.3=Méid cló:
|
watermark.selectText.3=Méid cló:
|
||||||
watermark.selectText.4=Rothlú (0-360):
|
watermark.selectText.4=Rothlú (0-360):
|
||||||
watermark.selectText.5=Width Spacer (Spás idir gach comhartha uisce go cothrománach):
|
watermark.selectText.5=widthSpacer (Spás idir gach comhartha uisce go cothrománach):
|
||||||
watermark.selectText.6=spásaire airde (Spás idir gach comhartha uisce go hingearach):
|
watermark.selectText.6=spásaire airde (Spás idir gach comhartha uisce go hingearach):
|
||||||
watermark.selectText.7=Teimhneacht (0% - 100%):
|
watermark.selectText.7=Teimhneacht (0% - 100%):
|
||||||
watermark.selectText.8=Cineál Comhartha Uisce:
|
watermark.selectText.8=Cineál Comhartha Uisce:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=अध्यायों पर अलग-कर
|
|||||||
home.splitPdfByChapters.desc=पुस्तक के अध्याय की संरचना पर आधारित एक PDF को बहिन-भागों में विभाजित करें
|
home.splitPdfByChapters.desc=पुस्तक के अध्याय की संरचना पर आधारित एक PDF को बहिन-भागों में विभाजित करें
|
||||||
splitPdfByChapters.tags=विभाजन,अध्याय,पसंदीदा,रजैत
|
splitPdfByChapters.tags=विभाजन,अध्याय,पसंदीदा,रजैत
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=चित्र रंग परिवर्तन/उलटकर परिवर्तन PDF
|
replace-color.header=चित्र रंग परिवर्तन/उलटकर परिवर्तन PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=एन्क्रिप्ट करें
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=वॉटरमार्क जोड़ें
|
watermark.title=वॉटरमार्क जोड़ें
|
||||||
watermark.header=वॉटरमार्क जोड़ें
|
watermark.header=वॉटरमार्क जोड़ें
|
||||||
watermark.customColor=संवैधित टेक्स्ट रंग
|
|
||||||
watermark.selectText.1=वॉटरमार्क जोड़ने के लिए पीडीएफ चुनें:
|
watermark.selectText.1=वॉटरमार्क जोड़ने के लिए पीडीएफ चुनें:
|
||||||
watermark.selectText.2=वॉटरमार्क टेक्स्ट:
|
watermark.selectText.2=वॉटरमार्क टेक्स्ट:
|
||||||
watermark.selectText.3=फ़ॉन्ट साइज़:
|
watermark.selectText.3=फ़ॉन्ट साइज़:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=लेमैक्स स्तर: विभाजन
|
|||||||
splitByChapters.desc.3=मॉडेटरेट का शामिल करें: यदि सत्यापित किया जाता है, प्रारंभिक PDF की मॉडेटरेट को प्रत्येक विभाग PDF में शामिल किया जाएगा।
|
splitByChapters.desc.3=मॉडेटरेट का शामिल करें: यदि सत्यापित किया जाता है, प्रारंभिक PDF की मॉडेटरेट को प्रत्येक विभाग PDF में शामिल किया जाएगा।
|
||||||
splitByChapters.desc.4=यादृच्छिक पुनरावृत्ति अनुमोदित: यदि सत्यापित किया जाता है, एक ही पेज पर दोहरे मूल्यांकन पब्लिक पीड़एफ बनाने की संभावना देता है।
|
splitByChapters.desc.4=यादृच्छिक पुनरावृत्ति अनुमोदित: यदि सत्यापित किया जाता है, एक ही पेज पर दोहरे मूल्यांकन पब्लिक पीड़एफ बनाने की संभावना देता है।
|
||||||
splitByChapters.submit=PDF विभाजित
|
splitByChapters.submit=PDF विभाजित
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Podijeli PDF prema glavama
|
|||||||
home.splitPdfByChapters.desc=Podijeli PDF na više datoteka prema njegovom strukturnom obliku glava.
|
home.splitPdfByChapters.desc=Podijeli PDF na više datoteka prema njegovom strukturnom obliku glava.
|
||||||
splitPdfByChapters.tags=podjela, glave, markere, organizacija
|
splitPdfByChapters.tags=podjela, glave, markere, organizacija
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Zameni-inverziranje boja u PDF-u
|
replace-color.header=Zameni-inverziranje boja u PDF-u
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Šifriraj
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Dodaj vodeni žig
|
watermark.title=Dodaj vodeni žig
|
||||||
watermark.header=Dodaj vodeni žig
|
watermark.header=Dodaj vodeni žig
|
||||||
watermark.customColor=Prilagođena boja teksta
|
|
||||||
watermark.selectText.1=Izaberite PDF za dodavanje vodenog žiga:
|
watermark.selectText.1=Izaberite PDF za dodavanje vodenog žiga:
|
||||||
watermark.selectText.2=Tekst vodenog žiga:
|
watermark.selectText.2=Tekst vodenog žiga:
|
||||||
watermark.selectText.3=Veličina fonta:
|
watermark.selectText.3=Veličina fonta:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Nivo oznaka: Odaberite nivo oznaka koji će se koristiti
|
|||||||
splitByChapters.desc.3=Uključi metapodatke: Ako je pokušano, metapodaci iz originalne PDF datoteke će biti uključeni u svaku podijeljenu PDF datoteku.
|
splitByChapters.desc.3=Uključi metapodatke: Ako je pokušano, metapodaci iz originalne PDF datoteke će biti uključeni u svaku podijeljenu PDF datoteku.
|
||||||
splitByChapters.desc.4=Dopuštaj duplikate: Ako je ova opcija zaštićena, dozvoljava se da se na istoj strani mogu stvoriti posebne PDF datoteke s više oznaka.
|
splitByChapters.desc.4=Dopuštaj duplikate: Ako je ova opcija zaštićena, dozvoljava se da se na istoj strani mogu stvoriti posebne PDF datoteke s više oznaka.
|
||||||
splitByChapters.submit=Podijeli PDF
|
splitByChapters.submit=Podijeli PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=PDF felosztása fejezetek szerint
|
|||||||
home.splitPdfByChapters.desc=Fejezetei alapján egy PDF fájl több dokumentumba osztás.
|
home.splitPdfByChapters.desc=Fejezetei alapján egy PDF fájl több dokumentumba osztás.
|
||||||
splitPdfByChapters.tags=Osztás, fejezetek, jelezes, organizálás
|
splitPdfByChapters.tags=Osztás, fejezetek, jelezes, organizálás
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Visszaalakítás-összevétel a színekkel PDF-ben
|
replace-color.header=Visszaalakítás-összevétel a színekkel PDF-ben
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Titkosítás
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Vízjel hozzáadása
|
watermark.title=Vízjel hozzáadása
|
||||||
watermark.header=Vízjel hozzáadása
|
watermark.header=Vízjel hozzáadása
|
||||||
watermark.customColor=Egyéni szövegszín
|
|
||||||
watermark.selectText.1=Válassza ki a PDF-t, amelyhez vízjelet kíván hozzáadni:
|
watermark.selectText.1=Válassza ki a PDF-t, amelyhez vízjelet kíván hozzáadni:
|
||||||
watermark.selectText.2=Vízjel szövege:
|
watermark.selectText.2=Vízjel szövege:
|
||||||
watermark.selectText.3=Betűméret:
|
watermark.selectText.3=Betűméret:
|
||||||
watermark.selectText.4=Forgatás (0-360):
|
watermark.selectText.4=Forgatás (0-360):
|
||||||
watermark.selectText.5=Width Spacer (Hely a vízjelek között vízszintesen):
|
watermark.selectText.5=widthSpacer (Hely a vízjelek között vízszintesen):
|
||||||
watermark.selectText.6=Height Spacer (Hely a vízjelek között függőlegesen):
|
watermark.selectText.6=heightSpacer (Hely a vízjelek között függőlegesen):
|
||||||
watermark.selectText.7=Átlátszóság (0% - 100%):
|
watermark.selectText.7=Átlátszóság (0% - 100%):
|
||||||
watermark.selectText.8=Vízjel típusa:
|
watermark.selectText.8=Vízjel típusa:
|
||||||
watermark.selectText.9=Vízjel képe:
|
watermark.selectText.9=Vízjel képe:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Metaadatok belefoglalása: Ha bevanítva van, az eredeti PDF fájl metaadatai megtartódnak minden osztott fájlban.
|
splitByChapters.desc.3=Metaadatok belefoglalása: Ha bevanítva van, az eredeti PDF fájl metaadatai megtartódnak minden osztott fájlban.
|
||||||
splitByChapters.desc.4=Duplikációk engedélyezése: Ha bevanítva van, lehetővé teszi a megadott oldalon lévő több kijelzőszint alapján új PDF-ek létrehozása.
|
splitByChapters.desc.4=Duplikációk engedélyezése: Ha bevanítva van, lehetővé teszi a megadott oldalon lévő több kijelzőszint alapján új PDF-ek létrehozása.
|
||||||
splitByChapters.submit=PDF osztás
|
splitByChapters.submit=PDF osztás
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Pisahkan PDF berdasarkan Bab
|
|||||||
home.splitPdfByChapters.desc=Memisahkan PDF menjadi beberapa file berdasarkan struktur babnya.
|
home.splitPdfByChapters.desc=Memisahkan PDF menjadi beberapa file berdasarkan struktur babnya.
|
||||||
splitPdfByChapters.tags=pemisahan,bab,bookmark,atur
|
splitPdfByChapters.tags=pemisahan,bab,bookmark,atur
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Ganti-Inversi-Warna
|
replace-color.title=Ganti-Inversi-Warna
|
||||||
replace-color.header=Ganti-Inversi Warna PDF
|
replace-color.header=Ganti-Inversi Warna PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Enkripsi
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Tambahkan Watermark
|
watermark.title=Tambahkan Watermark
|
||||||
watermark.header=Tambahkan Watermark
|
watermark.header=Tambahkan Watermark
|
||||||
watermark.customColor=Warna Teks Kustom
|
|
||||||
watermark.selectText.1=Pilih PDF untuk menambahkan watermark:
|
watermark.selectText.1=Pilih PDF untuk menambahkan watermark:
|
||||||
watermark.selectText.2=Text Watermark:
|
watermark.selectText.2=Text Watermark:
|
||||||
watermark.selectText.3=Ukuran Huruf:
|
watermark.selectText.3=Ukuran Huruf:
|
||||||
watermark.selectText.4=Rotasi (0-360):
|
watermark.selectText.4=Rotasi (0-360):
|
||||||
watermark.selectText.5=Width Spacer (Spasi diantara setiap watermark horisontal):
|
watermark.selectText.5=widthSpacer (Spasi diantara setiap watermark horisontal):
|
||||||
watermark.selectText.6=Height Spacer (Spasi diantara setiap watermark vertikal):
|
watermark.selectText.6=heightSpacer (Spasi diantara setiap watermark vertikal):
|
||||||
watermark.selectText.7=Kejernihan (0% - 100%):
|
watermark.selectText.7=Kejernihan (0% - 100%):
|
||||||
watermark.selectText.8=Tipe Watermark:
|
watermark.selectText.8=Tipe Watermark:
|
||||||
watermark.selectText.9=Gambar Watermark:
|
watermark.selectText.9=Gambar Watermark:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Tingkatan Markah: Pilih tingkatan markah yang digunakan u
|
|||||||
splitByChapters.desc.3=Termasuk Metadata: Jika dicentang, metadata asli PDF akan disertakan dalam setiap PDF yang dibagi.
|
splitByChapters.desc.3=Termasuk Metadata: Jika dicentang, metadata asli PDF akan disertakan dalam setiap PDF yang dibagi.
|
||||||
splitByChapters.desc.4=Izinkan Duplikat: Jika dicentang, mengizinkan beberapa markah pada halaman yang sama untuk membuat PDF terpisah.
|
splitByChapters.desc.4=Izinkan Duplikat: Jika dicentang, mengizinkan beberapa markah pada halaman yang sama untuk membuat PDF terpisah.
|
||||||
splitByChapters.submit=Pecah PDF
|
splitByChapters.submit=Pecah PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Dividi PDF per capitoli
|
|||||||
home.splitPdfByChapters.desc=Dividi un PDF in più file in base alla struttura dei capitoli.
|
home.splitPdfByChapters.desc=Dividi un PDF in più file in base alla struttura dei capitoli.
|
||||||
splitPdfByChapters.tags=dividi, capitoli, segnalibri, organizza
|
splitPdfByChapters.tags=dividi, capitoli, segnalibri, organizza
|
||||||
|
|
||||||
home.validateSignature.title=Convalida la firma PDF
|
|
||||||
home.validateSignature.desc=Verificare le firme digitali e i certificati nei documenti PDF
|
|
||||||
validateSignature.tags=firma,verifica,convalida,pdf,certificato,firma digitale,convalida firma,convalida certificato
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Sostituisci-Inverti-Colore
|
replace-color.title=Sostituisci-Inverti-Colore
|
||||||
replace-color.header=Sostituisci-Inverti colore PDF
|
replace-color.header=Sostituisci-Inverti colore PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Sposta a sinistra
|
|||||||
multiTool.moveRight=Sposta a destra
|
multiTool.moveRight=Sposta a destra
|
||||||
multiTool.delete=Elimina
|
multiTool.delete=Elimina
|
||||||
multiTool.dragDropMessage=Pagina(e) selezionata(e)
|
multiTool.dragDropMessage=Pagina(e) selezionata(e)
|
||||||
multiTool.undo=Annulla
|
|
||||||
multiTool.redo=Rifai
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=Questo file è protetto da password. Inserisci la password:
|
|
||||||
decrypt.cancelled=Operazione annullata per il PDF: {0}
|
|
||||||
decrypt.noPassword=Nessuna password fornita per il PDF crittografato: {0}
|
|
||||||
decrypt.invalidPassword=Riprova con la password corretta.
|
|
||||||
decrypt.invalidPasswordHeader=Password errata o crittografia non supportata per il PDF: {0}
|
|
||||||
decrypt.unexpectedError=Si è verificato un errore durante l'elaborazione del file. Riprova..
|
|
||||||
decrypt.serverError=Errore del server durante la decrittazione: {0}
|
|
||||||
decrypt.success=File decrittografato con successo.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=Questa funzione è disponibile anche nella nostra <a href="{0}">pagina multi-strumento</a>. Scoprila per un'interfaccia utente pagina per pagina migliorata e funzionalità aggiuntive!
|
multiTool-advert.message=Questa funzione è disponibile anche nella nostra <a href="{0}">pagina multi-strumento</a>. Scoprila per un'interfaccia utente pagina per pagina migliorata e funzionalità aggiuntive!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Crittografa
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Aggiungi Filigrana
|
watermark.title=Aggiungi Filigrana
|
||||||
watermark.header=Aggiungi filigrana
|
watermark.header=Aggiungi filigrana
|
||||||
watermark.customColor=Colore testo personalizzato
|
|
||||||
watermark.selectText.1=Seleziona PDF a cui aggiungere la filigrana:
|
watermark.selectText.1=Seleziona PDF a cui aggiungere la filigrana:
|
||||||
watermark.selectText.2=Testo:
|
watermark.selectText.2=Testo:
|
||||||
watermark.selectText.3=Dimensione carattere:
|
watermark.selectText.3=Dimensione carattere:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Livello segnalibro: seleziona il livello dei segnalibri d
|
|||||||
splitByChapters.desc.3=Includi metadati: se selezionato, i metadati del PDF originale verranno inclusi in ogni PDF diviso.
|
splitByChapters.desc.3=Includi metadati: se selezionato, i metadati del PDF originale verranno inclusi in ogni PDF diviso.
|
||||||
splitByChapters.desc.4=Consenti duplicati: se selezionata, consente più segnalibri sulla stessa pagina per creare PDF separati.
|
splitByChapters.desc.4=Consenti duplicati: se selezionata, consente più segnalibri sulla stessa pagina per creare PDF separati.
|
||||||
splitByChapters.submit=Dividi PDF
|
splitByChapters.submit=Dividi PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Clicca
|
|
||||||
fileChooser.or=o
|
|
||||||
fileChooser.dragAndDrop=Trascina & Rilascia
|
|
||||||
fileChooser.hoveredDragAndDrop=Trascina & rilascia i file qui
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Rilasci
|
|
||||||
releases.title=Note di rilascio
|
|
||||||
releases.header=Note di rilascio
|
|
||||||
releases.current.version=Rilascio corrente
|
|
||||||
releases.note=Le note di rilascio sono disponibili solo in inglese
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validare le firme PDF
|
|
||||||
validateSignature.header=Convalidare le firme digitali
|
|
||||||
validateSignature.selectPDF=Seleziona il file PDF firmato
|
|
||||||
validateSignature.submit=Convalida firme
|
|
||||||
validateSignature.results=Risultati di convalida
|
|
||||||
validateSignature.status=Stato
|
|
||||||
validateSignature.signer=Firmatario
|
|
||||||
validateSignature.date=Data
|
|
||||||
validateSignature.reason=Ragione
|
|
||||||
validateSignature.location=Posizione
|
|
||||||
validateSignature.noSignatures=Nessuna firma digitale trovata in questo documento
|
|
||||||
validateSignature.status.valid=Valida
|
|
||||||
validateSignature.status.invalid=Invalida
|
|
||||||
validateSignature.chain.invalid=Convalida della catena di certificati non riuscita: impossibile verificare l'identità del firmatario
|
|
||||||
validateSignature.trust.invalid=Certificato non presente nell'archivio attendibile: la fonte non può essere verificata
|
|
||||||
validateSignature.cert.expired=Il certificato è scaduto
|
|
||||||
validateSignature.cert.revoked=Il certificato è stato revocato
|
|
||||||
validateSignature.signature.info=Informazioni sulla firma
|
|
||||||
validateSignature.signature=Firma
|
|
||||||
validateSignature.signature.mathValid=La firma è matematicamente valida MA:
|
|
||||||
validateSignature.selectCustomCert=File di certificato personalizzato X.509 (opzionale)
|
|
||||||
validateSignature.cert.info=Dettagli del certificato
|
|
||||||
validateSignature.cert.issuer=Emittente
|
|
||||||
validateSignature.cert.subject=Soggetto
|
|
||||||
validateSignature.cert.serialNumber=Numero di serie
|
|
||||||
validateSignature.cert.validFrom=Valido da
|
|
||||||
validateSignature.cert.validUntil=Valido fino a
|
|
||||||
validateSignature.cert.algorithm=Algoritmo
|
|
||||||
validateSignature.cert.keySize=Dimensione chiave
|
|
||||||
validateSignature.cert.version=Versione
|
|
||||||
validateSignature.cert.keyUsage=Utilizzo della chiave
|
|
||||||
validateSignature.cert.selfSigned=Autofirmato
|
|
||||||
validateSignature.cert.bits=bit
|
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ userNotFoundMessage=ユーザーが見つかりません。
|
|||||||
incorrectPasswordMessage=現在のパスワードが正しくありません。
|
incorrectPasswordMessage=現在のパスワードが正しくありません。
|
||||||
usernameExistsMessage=新しいユーザー名はすでに存在します。
|
usernameExistsMessage=新しいユーザー名はすでに存在します。
|
||||||
invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
|
invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
|
||||||
invalidPasswordMessage=パスワードは空にすることはできません。また、先頭・末尾にスペースを含めることもできません。
|
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
||||||
confirmPasswordErrorMessage=新しいパスワードと新しいパスワードの確認は一致する必要があります。
|
confirmPasswordErrorMessage=新しいパスワードと新しいパスワードの確認は一致する必要があります。
|
||||||
deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
|
deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
|
||||||
deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
|
deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
|
||||||
downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
|
downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
|
||||||
disabledCurrentUserMessage=現在のユーザーを無効にすることはできません
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=現在のユーザーの役割をダウングレードできません。したがって、現在のユーザーは表示されません。
|
downgradeCurrentUserLongMessage=現在のユーザーの役割をダウングレードできません。したがって、現在のユーザーは表示されません。
|
||||||
userAlreadyExistsOAuthMessage=ユーザーは既にOAuth2ユーザーとして存在します。
|
userAlreadyExistsOAuthMessage=ユーザーは既にOAuth2ユーザーとして存在します。
|
||||||
userAlreadyExistsWebMessage=ユーザーは既にWebユーザーとして存在します。
|
userAlreadyExistsWebMessage=ユーザーは既にWebユーザーとして存在します。
|
||||||
@@ -76,12 +76,12 @@ donate=寄付する
|
|||||||
color=色
|
color=色
|
||||||
sponsor=スポンサー
|
sponsor=スポンサー
|
||||||
info=Info
|
info=Info
|
||||||
pro=pro
|
pro=Pro
|
||||||
page=ページ
|
page=Page
|
||||||
pages=ページ
|
pages=Pages
|
||||||
loading=読込中...
|
loading=Loading...
|
||||||
addToDoc=ドキュメントに追加
|
addToDoc=Add to Document
|
||||||
reset=リセット
|
reset=Reset
|
||||||
|
|
||||||
legal.privacy=プライバシーポリシー
|
legal.privacy=プライバシーポリシー
|
||||||
legal.terms=利用規約
|
legal.terms=利用規約
|
||||||
@@ -92,7 +92,7 @@ legal.impressum=著作権利者情報
|
|||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=パイプラインメニュー (Beta)
|
pipeline.header=パイプラインメニュー (Alpha)
|
||||||
pipeline.uploadButton=カスタムのアップロード
|
pipeline.uploadButton=カスタムのアップロード
|
||||||
pipeline.configureButton=設定
|
pipeline.configureButton=設定
|
||||||
pipeline.defaultOption=カスタム
|
pipeline.defaultOption=カスタム
|
||||||
@@ -117,21 +117,21 @@ pipelineOptions.validateButton=検証
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Proにアップグレード
|
enterpriseEdition.button=Upgrade to Pro
|
||||||
enterpriseEdition.warning=この機能はProユーザーのみが利用できます。
|
enterpriseEdition.warning=This feature is only available to Pro users.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Proは、YAML構成ファイルやその他のSSO機能をサポートしています。
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
||||||
enterpriseEdition.ssoAdvert=より多くのユーザー管理機能をお探しですか? Stirling PDF Proをご覧ください
|
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Stirling PDFをもっと良くしたいですか?
|
analytics.title=Do you want make Stirling PDF better?
|
||||||
analytics.paragraph1=Stirling PDFでは、製品の改善に役立つ分析機能をオプトインしています。個人情報やファイルの内容を追跡することはありません。
|
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
||||||
analytics.paragraph2=Stirling-PDFの成長を支援しユーザーをより深く理解できるように分析を有効にすることを検討してください。
|
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
||||||
analytics.enable=分析を有効にする
|
analytics.enable=Enable analytics
|
||||||
analytics.disable=分析を無効にする
|
analytics.disable=Disable analytics
|
||||||
analytics.settings=config/settings.ymlファイルでアナリティクスの設定を変更できます。
|
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -142,14 +142,14 @@ navbar.language=言語
|
|||||||
navbar.settings=設定
|
navbar.settings=設定
|
||||||
navbar.allTools=ツール
|
navbar.allTools=ツール
|
||||||
navbar.multiTool=マルチツール
|
navbar.multiTool=マルチツール
|
||||||
navbar.search=検索
|
navbar.search=Search
|
||||||
navbar.sections.organize=整理
|
navbar.sections.organize=整理
|
||||||
navbar.sections.convertTo=PDFへ変換
|
navbar.sections.convertTo=PDFへ変換
|
||||||
navbar.sections.convertFrom=PDFから変換
|
navbar.sections.convertFrom=PDFから変換
|
||||||
navbar.sections.security=署名とセキュリティ
|
navbar.sections.security=署名とセキュリティ
|
||||||
navbar.sections.advance=アドバンスド
|
navbar.sections.advance=アドバンスド
|
||||||
navbar.sections.edit=閲覧と編集
|
navbar.sections.edit=閲覧と編集
|
||||||
navbar.sections.popular=人気
|
navbar.sections.popular=Popular
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -208,7 +208,7 @@ adminUserSettings.user=ユーザー
|
|||||||
adminUserSettings.addUser=新しいユーザを追加
|
adminUserSettings.addUser=新しいユーザを追加
|
||||||
adminUserSettings.deleteUser=ユーザの削除
|
adminUserSettings.deleteUser=ユーザの削除
|
||||||
adminUserSettings.confirmDeleteUser=ユーザを本当に削除しますか?
|
adminUserSettings.confirmDeleteUser=ユーザを本当に削除しますか?
|
||||||
adminUserSettings.confirmChangeUserStatus=ユーザーを無効/有効にする必要がありますか?
|
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
||||||
adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
|
adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
|
||||||
adminUserSettings.roles=役割
|
adminUserSettings.roles=役割
|
||||||
adminUserSettings.role=役割
|
adminUserSettings.role=役割
|
||||||
@@ -247,8 +247,8 @@ database.fileNotFound=ファイルが見つかりません
|
|||||||
database.fileNullOrEmpty=ファイルは null または空であってはなりません
|
database.fileNullOrEmpty=ファイルは null または空であってはなりません
|
||||||
database.failedImportFile=ファイルのインポートに失敗
|
database.failedImportFile=ファイルのインポートに失敗
|
||||||
|
|
||||||
session.expired=セッションが期限切れです。ページを更新してもう一度お試しください。
|
session.expired=Your session has expired. Please refresh the page and try again.
|
||||||
session.refreshPage=ページを更新
|
session.refreshPage=Refresh Page
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -488,52 +488,48 @@ overlay-pdfs.tags=Overlay
|
|||||||
|
|
||||||
home.split-by-sections.title=PDFをセクションで分割
|
home.split-by-sections.title=PDFをセクションで分割
|
||||||
home.split-by-sections.desc=PDFの各ページを縦横に分割します。
|
home.split-by-sections.desc=PDFの各ページを縦横に分割します。
|
||||||
split-by-sections.tags=Section Split, Divide, Customize,Customise
|
split-by-sections.tags=Section Split, Divide, Customize
|
||||||
|
|
||||||
home.AddStampRequest.title=PDFにスタンプを追加
|
home.AddStampRequest.title=PDFにスタンプを追加
|
||||||
home.AddStampRequest.desc=設定した位置にテキストや画像のスタンプを追加できます
|
home.AddStampRequest.desc=設定した位置にテキストや画像のスタンプを追加できます
|
||||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize,Customise
|
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDFを書籍に変換
|
home.PDFToBook.title=PDFを書籍に変換
|
||||||
home.PDFToBook.desc=calibreを使用してPDFを書籍/コミック形式に変換します
|
home.PDFToBook.desc=calibreを使用してPDFを書籍/コミック形式に変換します
|
||||||
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
|
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.BookToPDF.title=PDFを書籍に変換
|
home.BookToPDF.title=PDFを書籍に変換
|
||||||
home.BookToPDF.desc=calibreを使用してPDFを書籍/コミック形式に変換します
|
home.BookToPDF.desc=calibreを使用してPDFを書籍/コミック形式に変換します
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
|
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=画像の削除
|
home.removeImagePdf.title=画像の削除
|
||||||
home.removeImagePdf.desc=PDFから画像を削除してファイルサイズを小さくします
|
home.removeImagePdf.desc=PDFから画像を削除してファイルサイズを小さくします
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=PDFをチャプターごとに分割
|
home.splitPdfByChapters.title=Split PDF by Chapters
|
||||||
home.splitPdfByChapters.desc=チャプターの構造に基づいてPDFを複数のファイルに分割します
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=PDF署名の検証
|
|
||||||
home.validateSignature.desc=PDF文書のデジタル署名と証明書を検証します
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=色の置換・反転
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=PDFの色の置換・反転
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=色の置換と反転
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=PDF内のテキストと背景の色を置き換え、PDFのフルカラーを反転してファイルサイズを縮小します。
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=色の置換または反転オプション
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=デフォルト(デフォルトの高コントラスト色)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=カスタム(カスタマイズされた色)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=フル反転(すべての色を反転)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=高コントラストカラーオプション
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=黒背景に白文字
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=白背景に黒文字
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=黒背景に黄色文字
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=黒背景に緑文字
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=テキストの色を選択
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=背景色を選択
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=置換
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -560,9 +556,9 @@ login.oauth2AccessDenied=アクセス拒否
|
|||||||
login.oauth2InvalidTokenResponse=無効なトークン応答
|
login.oauth2InvalidTokenResponse=無効なトークン応答
|
||||||
login.oauth2InvalidIdToken=無効なIDトークン
|
login.oauth2InvalidIdToken=無効なIDトークン
|
||||||
login.userIsDisabled=ユーザーは非アクティブ化されており、現在このユーザー名でのログインはブロックされています。管理者に連絡してください。
|
login.userIsDisabled=ユーザーは非アクティブ化されており、現在このユーザー名でのログインはブロックされています。管理者に連絡してください。
|
||||||
login.alreadyLoggedIn=すでにログインしています
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=デバイスからログアウトしてもう一度お試しください。
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=アクティブなセッションが多すぎます
|
login.toManySessions=You have too many active sessions
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自動塗りつぶし
|
autoRedact.title=自動塗りつぶし
|
||||||
@@ -578,8 +574,8 @@ autoRedact.submitButton=送信
|
|||||||
|
|
||||||
|
|
||||||
#showJS
|
#showJS
|
||||||
showJS.title=Javascriptを表示
|
showJS.title=JavaScriptを表示
|
||||||
showJS.header=Javascriptを表示
|
showJS.header=JavaScriptを表示
|
||||||
showJS.downloadJS=Javascriptをダウンロード
|
showJS.downloadJS=Javascriptをダウンロード
|
||||||
showJS.submit=表示
|
showJS.submit=表示
|
||||||
|
|
||||||
@@ -757,7 +753,7 @@ certSign.showSig=署名を表示
|
|||||||
certSign.reason=理由
|
certSign.reason=理由
|
||||||
certSign.location=場所
|
certSign.location=場所
|
||||||
certSign.name=名前
|
certSign.name=名前
|
||||||
certSign.showLogo=ロゴを表示
|
certSign.showLogo=Show Logo
|
||||||
certSign.submit=PDFに署名
|
certSign.submit=PDFに署名
|
||||||
|
|
||||||
|
|
||||||
@@ -792,9 +788,9 @@ compare.highlightColor.2=ハイライトカラー 2:
|
|||||||
compare.document.1=ドキュメント 1
|
compare.document.1=ドキュメント 1
|
||||||
compare.document.2=ドキュメント 2
|
compare.document.2=ドキュメント 2
|
||||||
compare.submit=比較
|
compare.submit=比較
|
||||||
compare.complex.message=提供された文書の一方または両方が大きなファイルであるため、比較の精度が低下する可能性があります。
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
compare.large.file.message=提供された文書の1つまたは両方が大きすぎて処理できません
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
compare.no.text.message=選択したPDFの1つまたは両方にテキストコンテンツがありません。比較するには、テキストを含むPDFを選択してください。
|
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=書籍やコミックをPDFに変換
|
BookToPDF.title=書籍やコミックをPDFに変換
|
||||||
@@ -803,8 +799,8 @@ BookToPDF.credit=calibreを使用
|
|||||||
BookToPDF.submit=変換
|
BookToPDF.submit=変換
|
||||||
|
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDFを書籍に変換
|
PDFToBook.title=書籍をPDFに変換
|
||||||
PDFToBook.header=PDFを書籍に変換
|
PDFToBook.header=書籍をPDFに変換
|
||||||
PDFToBook.selectText.1=フォーマット
|
PDFToBook.selectText.1=フォーマット
|
||||||
PDFToBook.credit=calibreを使用
|
PDFToBook.credit=calibreを使用
|
||||||
PDFToBook.submit=変換
|
PDFToBook.submit=変換
|
||||||
@@ -817,17 +813,17 @@ sign.draw=署名を書く
|
|||||||
sign.text=テキスト入力
|
sign.text=テキスト入力
|
||||||
sign.clear=クリア
|
sign.clear=クリア
|
||||||
sign.add=追加
|
sign.add=追加
|
||||||
sign.saved=保存された署名
|
sign.saved=Saved Signatures
|
||||||
sign.save=署名を保存
|
sign.save=Save Signature
|
||||||
sign.personalSigs=個人署名
|
sign.personalSigs=Personal Signatures
|
||||||
sign.sharedSigs=共有署名
|
sign.sharedSigs=Shared Signatures
|
||||||
sign.noSavedSigs=保存された署名が見つかりません
|
sign.noSavedSigs=No saved signatures found
|
||||||
sign.addToAll=すべてのページに追加
|
sign.addToAll=Add to all pages
|
||||||
sign.delete=削除
|
sign.delete=Delete
|
||||||
sign.first=最初のページ
|
sign.first=First page
|
||||||
sign.last=最後のページ
|
sign.last=Last page
|
||||||
sign.next=次のページ
|
sign.next=Next page
|
||||||
sign.previous=前のページ
|
sign.previous=Previous page
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
repair.title=修復
|
repair.title=修復
|
||||||
@@ -944,39 +940,27 @@ pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1)
|
|||||||
multiTool.title=PDFマルチツール
|
multiTool.title=PDFマルチツール
|
||||||
multiTool.header=PDFマルチツール
|
multiTool.header=PDFマルチツール
|
||||||
multiTool.uploadPrompts=ファイル名
|
multiTool.uploadPrompts=ファイル名
|
||||||
multiTool.selectAll=すべて選択
|
multiTool.selectAll=Select All
|
||||||
multiTool.deselectAll=選択を解除
|
multiTool.deselectAll=Deselect All
|
||||||
multiTool.selectPages=ページ選択
|
multiTool.selectPages=Page Select
|
||||||
multiTool.selectedPages=選択したページ
|
multiTool.selectedPages=Selected Pages
|
||||||
multiTool.page=ページ
|
multiTool.page=Page
|
||||||
multiTool.deleteSelected=選択項目を削除
|
multiTool.deleteSelected=Delete Selected
|
||||||
multiTool.downloadAll=エクスポート
|
multiTool.downloadAll=Export
|
||||||
multiTool.downloadSelected=選択項目をエクスポート
|
multiTool.downloadSelected=Export Selected
|
||||||
|
|
||||||
multiTool.insertPageBreak=改ページを挿入
|
multiTool.insertPageBreak=Insert Page Break
|
||||||
multiTool.addFile=ファイルを追加
|
multiTool.addFile=Add File
|
||||||
multiTool.rotateLeft=左回転
|
multiTool.rotateLeft=Rotate Left
|
||||||
multiTool.rotateRight=右回転
|
multiTool.rotateRight=Rotate Right
|
||||||
multiTool.split=分割
|
multiTool.split=Split
|
||||||
multiTool.moveLeft=左に移動
|
multiTool.moveLeft=Move Left
|
||||||
multiTool.moveRight=右に移動
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=削除
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=選択されたページ
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=元に戻す
|
|
||||||
multiTool.redo=やり直す
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=このファイルはパスワードで保護されています。パスワードを入力してください:
|
|
||||||
decrypt.cancelled=PDFの操作がキャンセルされました: {0}
|
|
||||||
decrypt.noPassword=暗号化されたPDFにパスワードが指定されていません: {0}
|
|
||||||
decrypt.invalidPassword=正しいパスワードでもう一度お試しください。
|
|
||||||
decrypt.invalidPasswordHeader=PDFのパスワードが正しくないか、暗号化がサポートされていません: {0}
|
|
||||||
decrypt.unexpectedError=ファイルの処理中にエラーが発生しました。もう一度お試しください。
|
|
||||||
decrypt.serverError=復号化中にサーバーエラーが発生しました: {0}
|
|
||||||
decrypt.success=ファイルの暗号化が正常に完了しました。
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=この機能は、<a href="{0}">マルチツール</a>でもご利用いただけます。強化されたページごとのUIと追加機能についてはこちらをご覧ください。
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=PDFを表示
|
viewPdf.title=PDFを表示
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=暗号化
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=透かしの追加
|
watermark.title=透かしの追加
|
||||||
watermark.header=透かしの追加
|
watermark.header=透かしの追加
|
||||||
watermark.customColor=文字色のカスタム
|
|
||||||
watermark.selectText.1=透かしを追加するPDFを選択:
|
watermark.selectText.1=透かしを追加するPDFを選択:
|
||||||
watermark.selectText.2=透かしのテキスト:
|
watermark.selectText.2=透かしのテキスト:
|
||||||
watermark.selectText.3=文字サイズ:
|
watermark.selectText.3=文字サイズ:
|
||||||
@@ -1132,7 +1115,7 @@ pdfToPDFA.header=PDFをPDF/Aに変換
|
|||||||
pdfToPDFA.credit=本サービスはPDF/Aの変換にqpdfを使用しています。
|
pdfToPDFA.credit=本サービスはPDF/Aの変換にqpdfを使用しています。
|
||||||
pdfToPDFA.submit=変換
|
pdfToPDFA.submit=変換
|
||||||
pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
|
pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
|
||||||
pdfToPDFA.outputFormat=出力形式
|
pdfToPDFA.outputFormat=Output format
|
||||||
pdfToPDFA.pdfWithDigitalSignature=PDF にはデジタル署名が含まれています。これは次の手順で削除されます。
|
pdfToPDFA.pdfWithDigitalSignature=PDF にはデジタル署名が含まれています。これは次の手順で削除されます。
|
||||||
|
|
||||||
|
|
||||||
@@ -1238,8 +1221,8 @@ licenses.license=ライセンス
|
|||||||
survey.nav=アンケート
|
survey.nav=アンケート
|
||||||
survey.title=Stirling-PDFのアンケート
|
survey.title=Stirling-PDFのアンケート
|
||||||
survey.description=Stirling-PDFには追跡機能がないため、Stirling-PDFをより良くするために皆様の意見を聞かせてください!
|
survey.description=Stirling-PDFには追跡機能がないため、Stirling-PDFをより良くするために皆様の意見を聞かせてください!
|
||||||
survey.changes=Stirling-PDFは前回の調査から変更されました。詳細についてはこちらのブログ投稿をご覧ください。
|
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
||||||
survey.changes2=これらの変更により私たちは有償のビジネスサポートと資金援助を受けています
|
survey.changes2=With these changes we are getting paid business support and funding
|
||||||
survey.please=アンケートにご協力ください!
|
survey.please=アンケートにご協力ください!
|
||||||
survey.disabled=(アンケートのポップアップは、次の更新では無効になりますが、ページの下部に表示されます。)
|
survey.disabled=(アンケートのポップアップは、次の更新では無効になりますが、ページの下部に表示されます。)
|
||||||
survey.button=アンケートに答える
|
survey.button=アンケートに答える
|
||||||
@@ -1267,61 +1250,13 @@ removeImage.removeImage=画像の削除
|
|||||||
removeImage.submit=画像を削除
|
removeImage.submit=画像を削除
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=PDFをチャプターごとに分割
|
splitByChapters.title=Split PDF by Chapters
|
||||||
splitByChapters.header=PDFをチャプターごとに分割
|
splitByChapters.header=Split PDF by Chapters
|
||||||
splitByChapters.bookmarkLevel=ブックマークレベル
|
splitByChapters.bookmarkLevel=Bookmark Level
|
||||||
splitByChapters.includeMetadata=メタデータを含める
|
splitByChapters.includeMetadata=Include Metadata
|
||||||
splitByChapters.allowDuplicates=重複を許可する
|
splitByChapters.allowDuplicates=Allow Duplicates
|
||||||
splitByChapters.desc.1=このツールは、チャプター構造に基づいてPDFファイルを複数のPDFに分割します。
|
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
||||||
splitByChapters.desc.2=ブックマークレベル:分割に使用するブックマークのレベルを選択します(最上位レベルの場合は0、第2レベルの場合は1など)。
|
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
||||||
splitByChapters.desc.3=メタデータを含める:チェックすると、元のPDFのメタデータが各分割PDFに含まれます。
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=重複を許可:チェックすると同じページ上の複数のブックマークから個別のPDFを作成できます。
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=PDFを分割
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=クリック
|
|
||||||
fileChooser.or=または
|
|
||||||
fileChooser.dragAndDrop=ドラッグ&ドロップ
|
|
||||||
fileChooser.hoveredDragAndDrop=ファイルをここにドラッグ&ドロップ
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=リリース
|
|
||||||
releases.title=リリースノート
|
|
||||||
releases.header=リリースノート
|
|
||||||
releases.current.version=現在のリリース
|
|
||||||
releases.note=リリースノートは英語でのみで提供されています
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=PDF署名の検証
|
|
||||||
validateSignature.header=デジタル署名の検証
|
|
||||||
validateSignature.selectPDF=署名済みPDFファイルを選択
|
|
||||||
validateSignature.submit=署名の検証
|
|
||||||
validateSignature.results=検証結果
|
|
||||||
validateSignature.status=状態
|
|
||||||
validateSignature.signer=署名者
|
|
||||||
validateSignature.date=日付
|
|
||||||
validateSignature.reason=理由
|
|
||||||
validateSignature.location=場所
|
|
||||||
validateSignature.noSignatures=この文書にはデジタル署名が見つかりません
|
|
||||||
validateSignature.status.valid=有効
|
|
||||||
validateSignature.status.invalid=無効
|
|
||||||
validateSignature.chain.invalid=証明書チェーンの検証に失敗しました - 署名者の身元を確認できません
|
|
||||||
validateSignature.trust.invalid=証明書が信頼ストアにありません - ソースを検証できません
|
|
||||||
validateSignature.cert.expired=証明書の有効期限が切れています
|
|
||||||
validateSignature.cert.revoked=証明書は取り消されました
|
|
||||||
validateSignature.signature.info=署名情報
|
|
||||||
validateSignature.signature=署名
|
|
||||||
validateSignature.signature.mathValid=署名は数学的には有効ですが:
|
|
||||||
validateSignature.selectCustomCert=カスタム証明書ファイル X.509 (オプション)
|
|
||||||
validateSignature.cert.info=証明書の詳細
|
|
||||||
validateSignature.cert.issuer=発行者
|
|
||||||
validateSignature.cert.subject=主題
|
|
||||||
validateSignature.cert.serialNumber=シリアルナンバー
|
|
||||||
validateSignature.cert.validFrom=有効開始日
|
|
||||||
validateSignature.cert.validUntil=有効期限
|
|
||||||
validateSignature.cert.algorithm=アルゴリズム
|
|
||||||
validateSignature.cert.keySize=キーサイズ
|
|
||||||
validateSignature.cert.version=バージョン
|
|
||||||
validateSignature.cert.keyUsage=キーの使用法
|
|
||||||
validateSignature.cert.selfSigned=自己署名
|
|
||||||
validateSignature.cert.bits=ビット
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=챕터별로 PDF 분할
|
|||||||
home.splitPdfByChapters.desc=PDF를 여러 파일로 나눕니다. 각 장의 구조에 따라.
|
home.splitPdfByChapters.desc=PDF를 여러 파일로 나눕니다. 각 장의 구조에 따라.
|
||||||
splitPdfByChapters.tags=분할, 챕터, 북마크, 조직화
|
splitPdfByChapters.tags=분할, 챕터, 북마크, 조직화
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=색상 교체/반전 PDF
|
replace-color.header=색상 교체/반전 PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=암호화
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=워터마크 추가
|
watermark.title=워터마크 추가
|
||||||
watermark.header=워터마크 추가
|
watermark.header=워터마크 추가
|
||||||
watermark.customColor=사용자 정의 텍스트 색상
|
|
||||||
watermark.selectText.1=워터마크를 추가할 PDF 선택:
|
watermark.selectText.1=워터마크를 추가할 PDF 선택:
|
||||||
watermark.selectText.2=워터마크 텍스트:
|
watermark.selectText.2=워터마크 텍스트:
|
||||||
watermark.selectText.3=폰트 크기:
|
watermark.selectText.3=폰트 크기:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=북마크 레벨: 분할에 사용할 북마크 레벨을
|
|||||||
splitByChapters.desc.3=메타데이터 포함: 체크하면 각 분할된 PDF에는 원본 PDF의 메타데이터가 포함됩니다.
|
splitByChapters.desc.3=메타데이터 포함: 체크하면 각 분할된 PDF에는 원본 PDF의 메타데이터가 포함됩니다.
|
||||||
splitByChapters.desc.4=중복 허용: 중복 북마크가 있는 같은 페이지에 여러 번 분할 PDF를 생성합니다.
|
splitByChapters.desc.4=중복 허용: 중복 북마크가 있는 같은 페이지에 여러 번 분할 PDF를 생성합니다.
|
||||||
splitByChapters.submit=PDF 분할
|
splitByChapters.submit=PDF 분할
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=PDF op hoofdstukken splitsen
|
|||||||
home.splitPdfByChapters.desc=Splits een PDF op basis van zijn hoofdstukstructuur in meerdere bestanden.
|
home.splitPdfByChapters.desc=Splits een PDF op basis van zijn hoofdstukstructuur in meerdere bestanden.
|
||||||
splitPdfByChapters.tags=splitsen, hoofdstukken, bookmarks, organiseren
|
splitPdfByChapters.tags=splitsen, hoofdstukken, bookmarks, organiseren
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Kleur-instellingen voor PDF's
|
replace-color.header=Kleur-instellingen voor PDF's
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Versleutelen
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Watermerk toevoegen
|
watermark.title=Watermerk toevoegen
|
||||||
watermark.header=Watermerk toevoegen
|
watermark.header=Watermerk toevoegen
|
||||||
watermark.customColor=Aangepaste tekstkleur
|
|
||||||
watermark.selectText.1=Selecteer PDF om watermerk toe te voegen:
|
watermark.selectText.1=Selecteer PDF om watermerk toe te voegen:
|
||||||
watermark.selectText.2=Watermerk tekst:
|
watermark.selectText.2=Watermerk tekst:
|
||||||
watermark.selectText.3=Tekengrootte:
|
watermark.selectText.3=Tekengrootte:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Boekmarkeer niveau: Kies het boekmarkeer niveau om te geb
|
|||||||
splitByChapters.desc.3=Metadata inclusief: Als gecijfeld, de originele PDF's metadata wordt ingevoegd in elk gesplitst PDF-bestand.
|
splitByChapters.desc.3=Metadata inclusief: Als gecijfeld, de originele PDF's metadata wordt ingevoegd in elk gesplitst PDF-bestand.
|
||||||
splitByChapters.desc.4=Dubbele items toestaan: Als gecijfeld, zorgen multiple boekmarkeersymboolen op dezelfde pagina voor het maken van aparte PDF-bestanden.
|
splitByChapters.desc.4=Dubbele items toestaan: Als gecijfeld, zorgen multiple boekmarkeersymboolen op dezelfde pagina voor het maken van aparte PDF-bestanden.
|
||||||
splitByChapters.submit=PDF splitsen
|
splitByChapters.submit=PDF splitsen
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Krypter
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Legg til vannmerke
|
watermark.title=Legg til vannmerke
|
||||||
watermark.header=Legg til vannmerke
|
watermark.header=Legg til vannmerke
|
||||||
watermark.customColor=Tilpasset Tekstfarge
|
|
||||||
watermark.selectText.1=Velg PDF-fil å legge til vannmerke på:
|
watermark.selectText.1=Velg PDF-fil å legge til vannmerke på:
|
||||||
watermark.selectText.2=Vannmerketekst:
|
watermark.selectText.2=Vannmerketekst:
|
||||||
watermark.selectText.3=Skriftstørrelse:
|
watermark.selectText.3=Skriftstørrelse:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
65
src/main/resources/messages_pl_PL.properties
Normal file → Executable file
65
src/main/resources/messages_pl_PL.properties
Normal file → Executable file
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Podziel PDF według rozdziałów
|
|||||||
home.splitPdfByChapters.desc=Podział pliku PDF na wiele plików na podstawie struktury rozdziałów.
|
home.splitPdfByChapters.desc=Podział pliku PDF na wiele plików na podstawie struktury rozdziałów.
|
||||||
splitPdfByChapters.tags=podział, rozdziały, zakładki, porządkowanie, organizacja
|
splitPdfByChapters.tags=podział, rozdziały, zakładki, porządkowanie, organizacja
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Zamień-Odwróć-Kolor
|
replace-color.title=Zamień-Odwróć-Kolor
|
||||||
replace-color.header=Zamień-Odwróć kolor PDF
|
replace-color.header=Zamień-Odwróć kolor PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Zablokuj
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Dodaj znak wodny
|
watermark.title=Dodaj znak wodny
|
||||||
watermark.header=Dodaj znak wodny
|
watermark.header=Dodaj znak wodny
|
||||||
watermark.customColor=Własny kolor tekstu
|
|
||||||
watermark.selectText.1=Wybierz dokument PDF, do którego chcesz dodać znak wodny:
|
watermark.selectText.1=Wybierz dokument PDF, do którego chcesz dodać znak wodny:
|
||||||
watermark.selectText.2=Treść znaku wodnego:
|
watermark.selectText.2=Treść znaku wodnego:
|
||||||
watermark.selectText.3=Rozmiar czcionki:
|
watermark.selectText.3=Rozmiar czcionki:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Poziom Zakładek: Wybierz poziom zakładek, który ma zos
|
|||||||
splitByChapters.desc.3=Dołącz Metadane: Jeśli opcja ta jest zaznaczona, metadane oryginalnego pliku PDF zostaną uwzględnione w każdym rozdzielonych plików PDF.
|
splitByChapters.desc.3=Dołącz Metadane: Jeśli opcja ta jest zaznaczona, metadane oryginalnego pliku PDF zostaną uwzględnione w każdym rozdzielonych plików PDF.
|
||||||
splitByChapters.desc.4=Zezwól na Duplikaty: Jeśli ta opcja jest zaznaczona, pozwala na tworzenie oddzielnych plików PDF przez wiele zakładek na tej samej stronie.
|
splitByChapters.desc.4=Zezwól na Duplikaty: Jeśli ta opcja jest zaznaczona, pozwala na tworzenie oddzielnych plików PDF przez wiele zakładek na tej samej stronie.
|
||||||
splitByChapters.submit=Podziel PDF
|
splitByChapters.submit=Podziel PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Dividir PDF por Capítulos
|
|||||||
home.splitPdfByChapters.desc=Divida um PDF em vários arquivos com base na estrutura dos capítulos.
|
home.splitPdfByChapters.desc=Divida um PDF em vários arquivos com base na estrutura dos capítulos.
|
||||||
splitPdfByChapters.tags=dividir,capítulos,marcadores,organizar
|
splitPdfByChapters.tags=dividir,capítulos,marcadores,organizar
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Substituir-Inverter Cor do PDF
|
replace-color.header=Substituir-Inverter Cor do PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Proteger
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Adicionar Marca d'Água
|
watermark.title=Adicionar Marca d'Água
|
||||||
watermark.header=Adicionar Marca d'Água
|
watermark.header=Adicionar Marca d'Água
|
||||||
watermark.customColor=Personalizar a cor do texto
|
|
||||||
watermark.selectText.1=Seleccione o PDF para Adicionar a 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.2=Texto da Marca d'Água
|
||||||
watermark.selectText.3=Tamanho da Fonte
|
watermark.selectText.3=Tamanho da Fonte
|
||||||
watermark.selectText.4=Rotação (0-360)
|
watermark.selectText.4=Rotação (0-360)
|
||||||
watermark.selectText.5=Espaçamento Horizontal (Width Spacer)
|
watermark.selectText.5=Espaçamento Horizontal (widthSpacer)
|
||||||
watermark.selectText.6=Espaçamento Vertical (Height Spacer)
|
watermark.selectText.6=Espaçamento Vertical (heightSpacer)
|
||||||
watermark.selectText.7=Opacidade (0% - 100%)
|
watermark.selectText.7=Opacidade (0% - 100%)
|
||||||
watermark.selectText.8=Tipo de Marca d'Água
|
watermark.selectText.8=Tipo de Marca d'Água
|
||||||
watermark.selectText.9=Imagem da Marca d'Água
|
watermark.selectText.9=Imagem da Marca d'Água
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Nível de Anotações: Escolha o nível das anotações a
|
|||||||
splitByChapters.desc.3=Inclua Metadados: Se marcado, os metadados originais do PDF serão incluídos em cada PDF dividido.
|
splitByChapters.desc.3=Inclua Metadados: Se marcado, os metadados originais do PDF serão incluídos em cada PDF dividido.
|
||||||
splitByChapters.desc.4=Permitir Duplicatas: Se marcado, permite a criação de vários bookmarks na mesma página para criar separadamente vários PDFs.
|
splitByChapters.desc.4=Permitir Duplicatas: Se marcado, permite a criação de vários bookmarks na mesma página para criar separadamente vários PDFs.
|
||||||
splitByChapters.submit=Dividir o PDF
|
splitByChapters.submit=Dividir o PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Criptează
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Adaugă Filigran
|
watermark.title=Adaugă Filigran
|
||||||
watermark.header=Adaugă Filigran
|
watermark.header=Adaugă Filigran
|
||||||
watermark.customColor=Culoare Text Personalizată
|
|
||||||
watermark.selectText.1=Selectează PDF-ul la care să adaugi filigranul:
|
watermark.selectText.1=Selectează PDF-ul la care să adaugi filigranul:
|
||||||
watermark.selectText.2=Textul Filigranului:
|
watermark.selectText.2=Textul Filigranului:
|
||||||
watermark.selectText.3=Mărimea fontului:
|
watermark.selectText.3=Mărimea fontului:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Разделить PDF по разделам
|
|||||||
home.splitPdfByChapters.desc=Разделите PDF на несколько файлов на основе структуры его разделов
|
home.splitPdfByChapters.desc=Разделите PDF на несколько файлов на основе структуры его разделов
|
||||||
splitPdfByChapters.tags=разделение, разделы, закладки, организация
|
splitPdfByChapters.tags=разделение, разделы, закладки, организация
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Заменить-Обратное изменение цвета PDF
|
replace-color.header=Заменить-Обратное изменение цвета PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Шифровать
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Добавить водяной знак
|
watermark.title=Добавить водяной знак
|
||||||
watermark.header=Добавить водяной знак
|
watermark.header=Добавить водяной знак
|
||||||
watermark.customColor=Настроенный цвет текста
|
|
||||||
watermark.selectText.1=Выберите PDF, чтобы добавить водяной знак:
|
watermark.selectText.1=Выберите PDF, чтобы добавить водяной знак:
|
||||||
watermark.selectText.2=Текст водяного знака:
|
watermark.selectText.2=Текст водяного знака:
|
||||||
watermark.selectText.3=Размер шрифта:
|
watermark.selectText.3=Размер шрифта:
|
||||||
watermark.selectText.4=Поворот (0-360):
|
watermark.selectText.4=Поворот (0-360):
|
||||||
watermark.selectText.5=Width Spacer (пробел между каждым водяным знаком по горизонтали):
|
watermark.selectText.5=widthSpacer (пробел между каждым водяным знаком по горизонтали):
|
||||||
watermark.selectText.6=Height Spacer (пробел между каждым водяным знаком по вертикали):
|
watermark.selectText.6=heightSpacer (пробел между каждым водяным знаком по вертикали):
|
||||||
watermark.selectText.7=Непрозрачность (0% - 100%):
|
watermark.selectText.7=Непрозрачность (0% - 100%):
|
||||||
watermark.selectText.8=Тип водяного знака:
|
watermark.selectText.8=Тип водяного знака:
|
||||||
watermark.selectText.9=Изображение водяного знака:
|
watermark.selectText.9=Изображение водяного знака:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Уровень закладки: выберите уро
|
|||||||
splitByChapters.desc.3=Включить метаданные: если эта опция отмечена, метаданные исходного PDF будут включены в каждый разбитый PDF.
|
splitByChapters.desc.3=Включить метаданные: если эта опция отмечена, метаданные исходного PDF будут включены в каждый разбитый PDF.
|
||||||
splitByChapters.desc.4=Позволять дубликаты: если эта опция отмечена, на одной странице могут быть созданы несколько PDF из-за нескольких одинаковых закладок.
|
splitByChapters.desc.4=Позволять дубликаты: если эта опция отмечена, на одной странице могут быть созданы несколько PDF из-за нескольких одинаковых закладок.
|
||||||
splitByChapters.submit=Разделить PDF
|
splitByChapters.submit=Разделить PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Zašifrovať
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Pridať vodotlač
|
watermark.title=Pridať vodotlač
|
||||||
watermark.header=Pridať vodotlač
|
watermark.header=Pridať vodotlač
|
||||||
watermark.customColor=Vlastná farba textu
|
|
||||||
watermark.selectText.1=Vyberte PDF, do ktorého chcete pridať vodotlač:
|
watermark.selectText.1=Vyberte PDF, do ktorého chcete pridať vodotlač:
|
||||||
watermark.selectText.2=Text vodotlače:
|
watermark.selectText.2=Text vodotlače:
|
||||||
watermark.selectText.3=Veľkosť písma:
|
watermark.selectText.3=Veľkosť písma:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Enkriptuj
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Dodaj vodeni žig
|
watermark.title=Dodaj vodeni žig
|
||||||
watermark.header=Dodaj vodeni žig
|
watermark.header=Dodaj vodeni žig
|
||||||
watermark.customColor=Custom Text Color
|
|
||||||
watermark.selectText.1=Izaberite PDF za dodavanje vodenog žiga:
|
watermark.selectText.1=Izaberite PDF za dodavanje vodenog žiga:
|
||||||
watermark.selectText.2=Tekst vodenog žiga:
|
watermark.selectText.2=Tekst vodenog žiga:
|
||||||
watermark.selectText.3=Veličina fonta:
|
watermark.selectText.3=Veličina fonta:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Dela upp PDF efter kapitel
|
|||||||
home.splitPdfByChapters.desc=Dela upp en PDF till flera filer baserat på dess kapitelstruktur.
|
home.splitPdfByChapters.desc=Dela upp en PDF till flera filer baserat på dess kapitelstruktur.
|
||||||
splitPdfByChapters.tags=dela,kapitel,bokmärken,organisera
|
splitPdfByChapters.tags=dela,kapitel,bokmärken,organisera
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Ersätt-Invertera färg på PDF
|
replace-color.header=Ersätt-Invertera färg på PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Kryptera
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Lägg till vattenstämpel
|
watermark.title=Lägg till vattenstämpel
|
||||||
watermark.header=Lägg till vattenstämpel
|
watermark.header=Lägg till vattenstämpel
|
||||||
watermark.customColor=Anpassad textfärg
|
|
||||||
watermark.selectText.1=Välj PDF för att lägga till vattenstämpel till:
|
watermark.selectText.1=Välj PDF för att lägga till vattenstämpel till:
|
||||||
watermark.selectText.2=Vattenmärkestext:
|
watermark.selectText.2=Vattenmärkestext:
|
||||||
watermark.selectText.3=Teckenstorlek:
|
watermark.selectText.3=Teckenstorlek:
|
||||||
watermark.selectText.4=Vändning (0-360):
|
watermark.selectText.4=Vändning (0-360):
|
||||||
watermark.selectText.5=Width Spacer (mellanrum mellan varje vattenstämpel horisontellt):
|
watermark.selectText.5=widthSpacer (mellanrum mellan varje vattenstämpel horisontellt):
|
||||||
watermark.selectText.6=Height Spacer (mellanrum mellan varje vattenstämpel vertikalt):
|
watermark.selectText.6=heightSpacer (mellanrum mellan varje vattenstämpel vertikalt):
|
||||||
watermark.selectText.7=Opacitet (0% - 100%):
|
watermark.selectText.7=Opacitet (0% - 100%):
|
||||||
watermark.selectText.8=Vattenstämpeltyp:
|
watermark.selectText.8=Vattenstämpeltyp:
|
||||||
watermark.selectText.9=Vattenstämpelbild:
|
watermark.selectText.9=Vattenstämpelbild:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bokmärkesnivå: Välj nivån av bokmärken att använda
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Tillåt duplicieringar: Om kryssrutan är markerad tillåts flera bokmärken på samma sida skapa individuella PDF:er.
|
splitByChapters.desc.4=Tillåt duplicieringar: Om kryssrutan är markerad tillåts flera bokmärken på samma sida skapa individuella PDF:er.
|
||||||
splitByChapters.submit=Dela upp PDF
|
splitByChapters.submit=Dela upp PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=เข้ารหัส
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=เพิ่มลายน้ำ
|
watermark.title=เพิ่มลายน้ำ
|
||||||
watermark.header=เพิ่มลายน้ำ
|
watermark.header=เพิ่มลายน้ำ
|
||||||
watermark.customColor=สีข้อความที่กำหนดเอง
|
|
||||||
watermark.selectText.1=เลือก PDF เพื่อเพิ่มลายน้ำ:
|
watermark.selectText.1=เลือก PDF เพื่อเพิ่มลายน้ำ:
|
||||||
watermark.selectText.2=ข้อความลายน้ำ:
|
watermark.selectText.2=ข้อความลายน้ำ:
|
||||||
watermark.selectText.3=ขนาดฟอนต์:
|
watermark.selectText.3=ขนาดฟอนต์:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=ระดับบุคคลที่ได้รับ
|
|||||||
splitByChapters.desc.3=รวมข้อมูลเสริม: หากถูกเลือก ข้อมูลเสริมของไฟล์ PDF ที่เดิมจะถูกรวมอยู่ในแต่ละไฟล์ที่แบ่งออก
|
splitByChapters.desc.3=รวมข้อมูลเสริม: หากถูกเลือก ข้อมูลเสริมของไฟล์ PDF ที่เดิมจะถูกรวมอยู่ในแต่ละไฟล์ที่แบ่งออก
|
||||||
splitByChapters.desc.4=อนุญาตให้มีการซ้ำ: หากถูกเลือก จะทำให้สามารถสร้างไฟล์ PDF แยกออกมาจากหน้าเดียวกันได้หลายรายการ
|
splitByChapters.desc.4=อนุญาตให้มีการซ้ำ: หากถูกเลือก จะทำให้สามารถสร้างไฟล์ PDF แยกออกมาจากหน้าเดียวกันได้หลายรายการ
|
||||||
splitByChapters.submit=แบ่งไฟล์ PDF
|
splitByChapters.submit=แบ่งไฟล์ PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Şifrele
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Filigran Ekle
|
watermark.title=Filigran Ekle
|
||||||
watermark.header=Filigran Ekle
|
watermark.header=Filigran Ekle
|
||||||
watermark.customColor=Özel Metin Rengi
|
|
||||||
watermark.selectText.1=Filigran eklemek için PDF seçin:
|
watermark.selectText.1=Filigran eklemek için PDF seçin:
|
||||||
watermark.selectText.2=Filigran Metni:
|
watermark.selectText.2=Filigran Metni:
|
||||||
watermark.selectText.3=Yazı Boyutu:
|
watermark.selectText.3=Yazı Boyutu:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=Шифрувати
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Додати водяний знак
|
watermark.title=Додати водяний знак
|
||||||
watermark.header=Додати водяний знак
|
watermark.header=Додати водяний знак
|
||||||
watermark.customColor=Користувацький колір тексту
|
|
||||||
watermark.selectText.1=Виберіть PDF, щоб додати водяний знак:
|
watermark.selectText.1=Виберіть PDF, щоб додати водяний знак:
|
||||||
watermark.selectText.2=Текст водяного знаку:
|
watermark.selectText.2=Текст водяного знаку:
|
||||||
watermark.selectText.3=Розмір шрифту:
|
watermark.selectText.3=Розмір шрифту:
|
||||||
watermark.selectText.4=Обертання (0-360):
|
watermark.selectText.4=Обертання (0-360):
|
||||||
watermark.selectText.5=Width Spacer (проміжок між кожним водяним знаком по горизонталі):
|
watermark.selectText.5=widthSpacer (проміжок між кожним водяним знаком по горизонталі):
|
||||||
watermark.selectText.6=Height Spacer (проміжок між кожним водяним знаком по вертикалі):
|
watermark.selectText.6=heightSpacer (проміжок між кожним водяним знаком по вертикалі):
|
||||||
watermark.selectText.7=Непрозорість (0% - 100%):
|
watermark.selectText.7=Непрозорість (0% - 100%):
|
||||||
watermark.selectText.8=Тип водяного знаку:
|
watermark.selectText.8=Тип водяного знаку:
|
||||||
watermark.selectText.9=Зображення водяного знаку:
|
watermark.selectText.9=Зображення водяного знаку:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=Split PDF by Chapters
|
|||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=Mã hóa
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=Thêm hình mờ
|
watermark.title=Thêm hình mờ
|
||||||
watermark.header=Thêm hình mờ
|
watermark.header=Thêm hình mờ
|
||||||
watermark.customColor=Màu văn bản tùy chỉnh
|
|
||||||
watermark.selectText.1=Chọn PDF để thêm hình mờ:
|
watermark.selectText.1=Chọn PDF để thêm hình mờ:
|
||||||
watermark.selectText.2=Văn bản hình mờ:
|
watermark.selectText.2=Văn bản hình mờ:
|
||||||
watermark.selectText.3=Cỡ chữ:
|
watermark.selectText.3=Cỡ chữ:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
###########
|
###########
|
||||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||||
language.direction=ltr
|
language.direction=ltr
|
||||||
addPageNumbers.fontSize=字体大小
|
addPageNumbers.fontSize=Font Size
|
||||||
addPageNumbers.fontName=字体名称
|
addPageNumbers.fontName=Font Name
|
||||||
pdfPrompt=选择PDF
|
pdfPrompt=选择PDF
|
||||||
multiPdfPrompt=选择多个PDF(2个或更多)
|
multiPdfPrompt=选择多个PDF(2个或更多)
|
||||||
multiPdfDropPrompt=选择(或拖拽)所需的PDF
|
multiPdfDropPrompt=选择(或拖拽)所需的PDF
|
||||||
@@ -79,14 +79,14 @@ info=信息
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=加载中...
|
loading=Loading...
|
||||||
addToDoc=Add to Document
|
addToDoc=Add to Document
|
||||||
reset=重置
|
reset=Reset
|
||||||
|
|
||||||
legal.privacy=隐私政策
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=服务条款
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=无障碍
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Cookie 政策
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=Impressum
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
@@ -117,8 +117,8 @@ pipelineOptions.validateButton=验证
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=升级到 Pro 版本
|
enterpriseEdition.button=Upgrade to Pro
|
||||||
enterpriseEdition.warning=此功能仅适用于 Pro 版本
|
enterpriseEdition.warning=This feature is only available to Pro users.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
||||||
|
|
||||||
@@ -247,8 +247,8 @@ database.fileNotFound=未找到文件
|
|||||||
database.fileNullOrEmpty=文件不能为空
|
database.fileNullOrEmpty=文件不能为空
|
||||||
database.failedImportFile=导入文件失败
|
database.failedImportFile=导入文件失败
|
||||||
|
|
||||||
session.expired=您的会话已过期。请刷新页面并重试。
|
session.expired=Your session has expired. Please refresh the page and try again.
|
||||||
session.refreshPage=刷新页面
|
session.refreshPage=Refresh Page
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -266,7 +266,7 @@ home.multiTool.desc=合并、旋转、重新排列和删除 PDF 页面
|
|||||||
multiTool.tags=多工具,多操作,用户界面,点击拖动,前端,客户端
|
multiTool.tags=多工具,多操作,用户界面,点击拖动,前端,客户端
|
||||||
|
|
||||||
home.merge.title=合并
|
home.merge.title=合并
|
||||||
home.merge.desc=轻松将多个 PDF 合并成一个。
|
home.merge.desc=轻松合并多个PDF为一个。
|
||||||
merge.tags=合并,页面操作,后端,服务器端
|
merge.tags=合并,页面操作,后端,服务器端
|
||||||
|
|
||||||
home.split.title=拆分
|
home.split.title=拆分
|
||||||
@@ -508,21 +508,17 @@ home.removeImagePdf.desc=删除图像减少 PDF 大小
|
|||||||
removeImagePdf.tags=删除图像, 页面操作, 后端, 服务端
|
removeImagePdf.tags=删除图像, 页面操作, 后端, 服务端
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=按章节拆分 PDF
|
home.splitPdfByChapters.title=Split PDF by Chapters
|
||||||
home.splitPdfByChapters.desc=根据其章节结构将 PDF 拆分为多个文件。
|
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||||
splitPdfByChapters.tags=分割,章节,书签,组织
|
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||||
|
|
||||||
home.validateSignature.title=验证 PDF 签名
|
|
||||||
home.validateSignature.desc=验证 PDF 文档中的数字签名和证书
|
|
||||||
validateSignature.tags=签名,验证,验证,PDF,证书,数字签名,验证签名,验证证书
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=替换-反转-颜色
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=替换-反转 PDF 颜色
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=替换和反转颜色
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=替换 PDF 中文本和背景的颜色,并将PDF全色反转以减小文件大小
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=替换或反转颜色选项
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
@@ -560,9 +556,9 @@ login.oauth2AccessDenied=拒绝访问
|
|||||||
login.oauth2InvalidTokenResponse=无效的Token响应
|
login.oauth2InvalidTokenResponse=无效的Token响应
|
||||||
login.oauth2InvalidIdToken=无效的Token
|
login.oauth2InvalidIdToken=无效的Token
|
||||||
login.userIsDisabled=用户被禁用,登录已被阻止。请联系管理员。
|
login.userIsDisabled=用户被禁用,登录已被阻止。请联系管理员。
|
||||||
login.alreadyLoggedIn=您已经登录到了
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=设备,请注销设备后重试。
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=你已经有太多的会话了。请注销一些设备后重试。
|
login.toManySessions=You have too many active sessions
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自动删除
|
autoRedact.title=自动删除
|
||||||
@@ -737,7 +733,7 @@ pageLayout.submit=提交
|
|||||||
scalePages.title=调整页面缩放比例
|
scalePages.title=调整页面缩放比例
|
||||||
scalePages.header=调整页面缩放比例
|
scalePages.header=调整页面缩放比例
|
||||||
scalePages.pageSize=文档页面的尺寸。
|
scalePages.pageSize=文档页面的尺寸。
|
||||||
scalePages.keepPageSize=保持页面原尺寸
|
scalePages.keepPageSize=Original Size
|
||||||
scalePages.scaleFactor=页面的缩放级别(裁剪)。
|
scalePages.scaleFactor=页面的缩放级别(裁剪)。
|
||||||
scalePages.submit=提交
|
scalePages.submit=提交
|
||||||
|
|
||||||
@@ -757,7 +753,7 @@ certSign.showSig=显示签名
|
|||||||
certSign.reason=原因
|
certSign.reason=原因
|
||||||
certSign.location=位置
|
certSign.location=位置
|
||||||
certSign.name=名称
|
certSign.name=名称
|
||||||
certSign.showLogo=显示 Logo
|
certSign.showLogo=Show Logo
|
||||||
certSign.submit=给PDF签名
|
certSign.submit=给PDF签名
|
||||||
|
|
||||||
|
|
||||||
@@ -792,9 +788,9 @@ compare.highlightColor.2=高亮颜色 2:
|
|||||||
compare.document.1=文档 1
|
compare.document.1=文档 1
|
||||||
compare.document.2=文档 2
|
compare.document.2=文档 2
|
||||||
compare.submit=比较
|
compare.submit=比较
|
||||||
compare.complex.message=提供的一份或两份文件是大文件,比较的准确性可能会降低。
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
compare.large.file.message=提供的文件中有一份或两份过大,无法处理。
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
compare.no.text.message=所选的 PDF 文件中有一个或两个没有文本内容。请选择包含文本的 PDF 文件进行对比。
|
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=电子书和漫画转换成PDF
|
BookToPDF.title=电子书和漫画转换成PDF
|
||||||
@@ -817,17 +813,17 @@ sign.draw=绘制签名
|
|||||||
sign.text=文本输入
|
sign.text=文本输入
|
||||||
sign.clear=清除
|
sign.clear=清除
|
||||||
sign.add=添加
|
sign.add=添加
|
||||||
sign.saved=已保存签名
|
sign.saved=Saved Signatures
|
||||||
sign.save=保存签名
|
sign.save=Save Signature
|
||||||
sign.personalSigs=个人签名
|
sign.personalSigs=Personal Signatures
|
||||||
sign.sharedSigs=Shared Signatures
|
sign.sharedSigs=Shared Signatures
|
||||||
sign.noSavedSigs=未找到已保存的签名
|
sign.noSavedSigs=No saved signatures found
|
||||||
sign.addToAll=添加到所有页面
|
sign.addToAll=Add to all pages
|
||||||
sign.delete=删除
|
sign.delete=Delete
|
||||||
sign.first=首页
|
sign.first=First page
|
||||||
sign.last=末页
|
sign.last=Last page
|
||||||
sign.next=下一页
|
sign.next=Next page
|
||||||
sign.previous=上一页
|
sign.previous=Previous page
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
repair.title=修复
|
repair.title=修复
|
||||||
@@ -944,39 +940,27 @@ pdfOrganiser.placeholder=(例如:1,3,2 或 4-8,2,10-12 或 2n-1)
|
|||||||
multiTool.title=PDF多功能工具
|
multiTool.title=PDF多功能工具
|
||||||
multiTool.header=PDF多功能工具
|
multiTool.header=PDF多功能工具
|
||||||
multiTool.uploadPrompts=文件名
|
multiTool.uploadPrompts=文件名
|
||||||
multiTool.selectAll=选择所有
|
multiTool.selectAll=Select All
|
||||||
multiTool.deselectAll=取消选择所有
|
multiTool.deselectAll=Deselect All
|
||||||
multiTool.selectPages=Page Select
|
multiTool.selectPages=Page Select
|
||||||
multiTool.selectedPages=已选择的页面
|
multiTool.selectedPages=Selected Pages
|
||||||
multiTool.page=Page
|
multiTool.page=Page
|
||||||
multiTool.deleteSelected=删除已选
|
multiTool.deleteSelected=Delete Selected
|
||||||
multiTool.downloadAll=导出全部
|
multiTool.downloadAll=Export
|
||||||
multiTool.downloadSelected=导出已选
|
multiTool.downloadSelected=Export Selected
|
||||||
|
|
||||||
multiTool.insertPageBreak=插入分页符
|
multiTool.insertPageBreak=Insert Page Break
|
||||||
multiTool.addFile=添加文件
|
multiTool.addFile=Add File
|
||||||
multiTool.rotateLeft=向左旋转
|
multiTool.rotateLeft=Rotate Left
|
||||||
multiTool.rotateRight=向右旋转
|
multiTool.rotateRight=Rotate Right
|
||||||
multiTool.split=分割
|
multiTool.split=Split
|
||||||
multiTool.moveLeft=向做移动
|
multiTool.moveLeft=Move Left
|
||||||
multiTool.moveRight=向右移动
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=删除
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=选择页面
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=此文件受密码保护。请输入密码:
|
|
||||||
decrypt.cancelled=PDF 操作已取消: {0}
|
|
||||||
decrypt.noPassword=未提供加密 PDF 的密码: {0}
|
|
||||||
decrypt.invalidPassword=请使用正确的密码重试。
|
|
||||||
decrypt.invalidPasswordHeader=密码错误或不支持的 PDF 加密: {0}
|
|
||||||
decrypt.unexpectedError=处理文件时发生错误。请再试一次。
|
|
||||||
decrypt.serverError=服务器解密时发生错误: {0}
|
|
||||||
decrypt.success=文件解密成功。
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=此功能也适用于我们的“<a href="{0}">多功能工具页面</a>”。查看它以获得增强的逐页 UI 以及其他功能!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=浏览PDF
|
viewPdf.title=浏览PDF
|
||||||
@@ -1066,7 +1050,6 @@ addPassword.submit=加密
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=添加水印
|
watermark.title=添加水印
|
||||||
watermark.header=添加水印
|
watermark.header=添加水印
|
||||||
watermark.customColor=自定义文本颜色
|
|
||||||
watermark.selectText.1=选择要添加水印的PDF:
|
watermark.selectText.1=选择要添加水印的PDF:
|
||||||
watermark.selectText.2=水印文本:
|
watermark.selectText.2=水印文本:
|
||||||
watermark.selectText.3=字体大小:
|
watermark.selectText.3=字体大小:
|
||||||
@@ -1235,11 +1218,11 @@ licenses.version=版本
|
|||||||
licenses.license=许可证
|
licenses.license=许可证
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=问卷调查
|
survey.nav=调查
|
||||||
survey.title=Stirling-PDF 问卷调查
|
survey.title=Stirling-PDF调查
|
||||||
survey.description=Stirling-PDF没有跟踪器,所以我们希望听取用户的意见来改进Stirling-PDF!
|
survey.description=Stirling-PDF没有跟踪器,所以我们希望听取用户的意见来改进Stirling-PDF!
|
||||||
survey.changes=自上次调查以来,Stirling-PDF 已经发生了变化!要了解更多信息,请在此处查看我们的博客文章:
|
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
||||||
survey.changes2=通过这些变化,我们得到了商业支持和资金援助。
|
survey.changes2=With these changes we are getting paid business support and funding
|
||||||
survey.please=请考虑参加我们的调查!
|
survey.please=请考虑参加我们的调查!
|
||||||
survey.disabled=(调查弹出窗口将在后续更新中被禁用,但可在页脚处查看)
|
survey.disabled=(调查弹出窗口将在后续更新中被禁用,但可在页脚处查看)
|
||||||
survey.button=参与调查
|
survey.button=参与调查
|
||||||
@@ -1267,61 +1250,13 @@ removeImage.removeImage=删除图像
|
|||||||
removeImage.submit=删除图像
|
removeImage.submit=删除图像
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=按章节拆分 PDF
|
splitByChapters.title=Split PDF by Chapters
|
||||||
splitByChapters.header=按章节拆分 PDF
|
splitByChapters.header=Split PDF by Chapters
|
||||||
splitByChapters.bookmarkLevel=书签级别
|
splitByChapters.bookmarkLevel=Bookmark Level
|
||||||
splitByChapters.includeMetadata=包含元数据
|
splitByChapters.includeMetadata=Include Metadata
|
||||||
splitByChapters.allowDuplicates=允许重复
|
splitByChapters.allowDuplicates=Allow Duplicates
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=拆分 PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=单击
|
|
||||||
fileChooser.or=或
|
|
||||||
fileChooser.dragAndDrop=拖放文件
|
|
||||||
fileChooser.hoveredDragAndDrop=拖放文件到此处
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=版本
|
|
||||||
releases.title=版本说明
|
|
||||||
releases.header=版本说明
|
|
||||||
releases.current.version=当前版本
|
|
||||||
releases.note=版本说明仅提供英文版本
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -512,10 +512,6 @@ home.splitPdfByChapters.title=依章節分割 PDF
|
|||||||
home.splitPdfByChapters.desc=根據 PDF 的章節結構將其分割成多個檔案。
|
home.splitPdfByChapters.desc=根據 PDF 的章節結構將其分割成多個檔案。
|
||||||
splitPdfByChapters.tags=分割,章節,書籤,整理
|
splitPdfByChapters.tags=分割,章節,書籤,整理
|
||||||
|
|
||||||
home.validateSignature.title=Validate PDF Signature
|
|
||||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
|
||||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=取代-反轉顏色
|
replace-color.title=取代-反轉顏色
|
||||||
replace-color.header=取代-反轉 PDF 顏色
|
replace-color.header=取代-反轉 PDF 顏色
|
||||||
@@ -962,18 +958,6 @@ multiTool.moveLeft=Move Left
|
|||||||
multiTool.moveRight=Move Right
|
multiTool.moveRight=Move Right
|
||||||
multiTool.delete=Delete
|
multiTool.delete=Delete
|
||||||
multiTool.dragDropMessage=Page(s) Selected
|
multiTool.dragDropMessage=Page(s) Selected
|
||||||
multiTool.undo=Undo
|
|
||||||
multiTool.redo=Redo
|
|
||||||
|
|
||||||
#decrypt
|
|
||||||
decrypt.passwordPrompt=This file is password-protected. Please enter the password:
|
|
||||||
decrypt.cancelled=Operation cancelled for PDF: {0}
|
|
||||||
decrypt.noPassword=No password provided for encrypted PDF: {0}
|
|
||||||
decrypt.invalidPassword=Please try again with the correct password.
|
|
||||||
decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
|
|
||||||
decrypt.unexpectedError=There was an error processing the file. Please try again.
|
|
||||||
decrypt.serverError=Server error while decrypting: {0}
|
|
||||||
decrypt.success=File decrypted successfully.
|
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
|
||||||
@@ -1066,13 +1050,12 @@ addPassword.submit=加密
|
|||||||
#watermark
|
#watermark
|
||||||
watermark.title=新增浮水印
|
watermark.title=新增浮水印
|
||||||
watermark.header=新增浮水印
|
watermark.header=新增浮水印
|
||||||
watermark.customColor=自訂文字顏色
|
|
||||||
watermark.selectText.1=選擇要新增浮水印的 PDF:
|
watermark.selectText.1=選擇要新增浮水印的 PDF:
|
||||||
watermark.selectText.2=浮水印文字:
|
watermark.selectText.2=浮水印文字:
|
||||||
watermark.selectText.3=字型大小:
|
watermark.selectText.3=字型大小:
|
||||||
watermark.selectText.4=旋轉(0-360):
|
watermark.selectText.4=旋轉(0-360):
|
||||||
watermark.selectText.5=Width Spacer(每個浮水印之間的水平間距):
|
watermark.selectText.5=widthSpacer(每個浮水印之間的水平間距):
|
||||||
watermark.selectText.6=Height Spacer(每個浮水印之間的垂直間距):
|
watermark.selectText.6=heightSpacer(每個浮水印之間的垂直間距):
|
||||||
watermark.selectText.7=不透明度(0% - 100%):
|
watermark.selectText.7=不透明度(0% - 100%):
|
||||||
watermark.selectText.8=浮水印類型:
|
watermark.selectText.8=浮水印類型:
|
||||||
watermark.selectText.9=浮水印影像:
|
watermark.selectText.9=浮水印影像:
|
||||||
@@ -1277,51 +1260,3 @@ splitByChapters.desc.2=書籤層級:選擇用於分割的書籤層級(0 表
|
|||||||
splitByChapters.desc.3=包含中繼資料:如果勾選,原始 PDF 的中繼資料將包含在每個分割後的 PDF 中。
|
splitByChapters.desc.3=包含中繼資料:如果勾選,原始 PDF 的中繼資料將包含在每個分割後的 PDF 中。
|
||||||
splitByChapters.desc.4=允許重複:如果勾選,允許同一頁面上的多個書籤建立獨立的 PDF。
|
splitByChapters.desc.4=允許重複:如果勾選,允許同一頁面上的多個書籤建立獨立的 PDF。
|
||||||
splitByChapters.submit=分割 PDF
|
splitByChapters.submit=分割 PDF
|
||||||
|
|
||||||
#File Chooser
|
|
||||||
fileChooser.click=Click
|
|
||||||
fileChooser.or=or
|
|
||||||
fileChooser.dragAndDrop=Drag & Drop
|
|
||||||
fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
|
|
||||||
|
|
||||||
#release notes
|
|
||||||
releases.footer=Releases
|
|
||||||
releases.title=Release Notes
|
|
||||||
releases.header=Release Notes
|
|
||||||
releases.current.version=Current Release
|
|
||||||
releases.note=Release notes are only available in English
|
|
||||||
|
|
||||||
#Validate Signature
|
|
||||||
validateSignature.title=Validate PDF Signatures
|
|
||||||
validateSignature.header=Validate Digital Signatures
|
|
||||||
validateSignature.selectPDF=Select signed PDF file
|
|
||||||
validateSignature.submit=Validate Signatures
|
|
||||||
validateSignature.results=Validation Results
|
|
||||||
validateSignature.status=Status
|
|
||||||
validateSignature.signer=Signer
|
|
||||||
validateSignature.date=Date
|
|
||||||
validateSignature.reason=Reason
|
|
||||||
validateSignature.location=Location
|
|
||||||
validateSignature.noSignatures=No digital signatures found in this document
|
|
||||||
validateSignature.status.valid=Valid
|
|
||||||
validateSignature.status.invalid=Invalid
|
|
||||||
validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
|
|
||||||
validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
|
|
||||||
validateSignature.cert.expired=Certificate has expired
|
|
||||||
validateSignature.cert.revoked=Certificate has been revoked
|
|
||||||
validateSignature.signature.info=Signature Information
|
|
||||||
validateSignature.signature=Signature
|
|
||||||
validateSignature.signature.mathValid=Signature is mathematically valid BUT:
|
|
||||||
validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
|
|
||||||
validateSignature.cert.info=Certificate Details
|
|
||||||
validateSignature.cert.issuer=Issuer
|
|
||||||
validateSignature.cert.subject=Subject
|
|
||||||
validateSignature.cert.serialNumber=Serial Number
|
|
||||||
validateSignature.cert.validFrom=Valid From
|
|
||||||
validateSignature.cert.validUntil=Valid Until
|
|
||||||
validateSignature.cert.algorithm=Algorithm
|
|
||||||
validateSignature.cert.keySize=Key Size
|
|
||||||
validateSignature.cert.version=Version
|
|
||||||
validateSignature.cert.keyUsage=Key Usage
|
|
||||||
validateSignature.cert.selfSigned=Self-Signed
|
|
||||||
validateSignature.cert.bits=bits
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
|
|
||||||
security:
|
security:
|
||||||
enableLogin: false # set to 'true' to enable login
|
enableLogin: false # set to 'true' to enable login
|
||||||
csrfDisabled: false # set to 'true' to disable CSRF protection (not recommended for production)
|
csrfDisabled: true # set to 'true' to disable CSRF protection (not recommended for production)
|
||||||
loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1
|
loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1
|
||||||
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
|
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
|
||||||
loginMethod: all # Accepts values like 'all' and 'normal'(only Login with Username/Password), 'oauth2'(only Login with OAuth2) or 'saml2'(only Login with SAML2)
|
loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
|
||||||
initialLogin:
|
initialLogin:
|
||||||
username: '' # initial username for the first login
|
username: '' # initial username for the first login
|
||||||
password: '' # initial password for the first login
|
password: '' # initial password for the first login
|
||||||
@@ -42,14 +42,14 @@ security:
|
|||||||
issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) endpoint
|
issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) endpoint
|
||||||
clientId: '' # client ID from your provider
|
clientId: '' # client ID from your provider
|
||||||
clientSecret: '' # client secret from your provider
|
clientSecret: '' # client secret from your provider
|
||||||
autoCreateUser: true # set to 'true' to allow auto-creation of non-existing users
|
autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
|
||||||
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
||||||
useAsUsername: email # default is 'email'; custom fields can be used as the username
|
useAsUsername: email # default is 'email'; custom fields can be used as the username
|
||||||
scopes: openid, profile, email # specify the scopes for which the application will request permissions
|
scopes: openid, profile, email # specify the scopes for which the application will request permissions
|
||||||
provider: google # set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
provider: google # set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
||||||
saml2:
|
saml2:
|
||||||
enabled: false # Only enabled for paid enterprise clients (enterpriseEdition.enabled must be true)
|
enabled: false # currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true
|
||||||
autoCreateUser: true # set to 'true' to allow auto-creation of non-existing users
|
autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
|
||||||
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
||||||
registrationId: stirling
|
registrationId: stirling
|
||||||
idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata
|
idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata
|
||||||
@@ -102,7 +102,6 @@ metrics:
|
|||||||
AutomaticallyGenerated:
|
AutomaticallyGenerated:
|
||||||
key: example
|
key: example
|
||||||
UUID: example
|
UUID: example
|
||||||
appVersion: 0.35.0
|
|
||||||
|
|
||||||
processExecutor:
|
processExecutor:
|
||||||
sessionLimit: # Process executor instances limits
|
sessionLimit: # Process executor instances limits
|
||||||
|
|||||||
@@ -172,13 +172,6 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.google.code.gson:gson",
|
|
||||||
"moduleUrl": "https://github.com/google/gson",
|
|
||||||
"moduleVersion": "2.11.0",
|
|
||||||
"moduleLicense": "Apache-2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.google.errorprone:error_prone_annotations",
|
"moduleName": "com.google.errorprone:error_prone_annotations",
|
||||||
"moduleUrl": "https://errorprone.info/error_prone_annotations",
|
"moduleUrl": "https://errorprone.info/error_prone_annotations",
|
||||||
@@ -414,7 +407,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "commons-io:commons-io",
|
"moduleName": "commons-io:commons-io",
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
||||||
"moduleVersion": "2.18.0",
|
"moduleVersion": "2.17.0",
|
||||||
"moduleLicense": "Apache-2.0",
|
"moduleLicense": "Apache-2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@@ -598,34 +591,6 @@
|
|||||||
"moduleLicense": "GPL2 w/ CPE",
|
"moduleLicense": "GPL2 w/ CPE",
|
||||||
"moduleLicenseUrl": "https://oss.oracle.com/licenses/CDDL+GPL-1.1"
|
"moduleLicenseUrl": "https://oss.oracle.com/licenses/CDDL+GPL-1.1"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "me.friwi:gluegen-rt",
|
|
||||||
"moduleUrl": "http://jogamp.org/gluegen/www/",
|
|
||||||
"moduleVersion": "v2.4.0-rc-20210111",
|
|
||||||
"moduleLicense": "BSD-4 License",
|
|
||||||
"moduleLicenseUrl": "http://www.spdx.org/licenses/BSD-4-Clause"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "me.friwi:jcef-api",
|
|
||||||
"moduleUrl": "https://bitbucket.org/chromiumembedded/java-cef/",
|
|
||||||
"moduleVersion": "jcef-99c2f7a+cef-127.3.1+g6cbb30e+chromium-127.0.6533.100",
|
|
||||||
"moduleLicense": "BSD License",
|
|
||||||
"moduleLicenseUrl": "https://bitbucket.org/chromiumembedded/java-cef/src/master/LICENSE.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "me.friwi:jcefmaven",
|
|
||||||
"moduleUrl": "https://github.com/jcefmaven/jcefmaven/",
|
|
||||||
"moduleVersion": "127.3.1",
|
|
||||||
"moduleLicense": "Apache-2.0 License",
|
|
||||||
"moduleLicenseUrl": "https://github.com/jcefmaven/jcefmaven/blob/master/LICENSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "me.friwi:jogl-all",
|
|
||||||
"moduleUrl": "http://jogamp.org/jogl/www/",
|
|
||||||
"moduleVersion": "v2.4.0-rc-20210111",
|
|
||||||
"moduleLicense": "Ubuntu Font Licence 1.0",
|
|
||||||
"moduleLicenseUrl": "http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "net.bytebuddy:byte-buddy",
|
"moduleName": "net.bytebuddy:byte-buddy",
|
||||||
"moduleVersion": "1.15.10",
|
"moduleVersion": "1.15.10",
|
||||||
@@ -666,13 +631,6 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.apache.commons:commons-compress",
|
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-compress/",
|
|
||||||
"moduleVersion": "1.21",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.apache.commons:commons-csv",
|
"moduleName": "org.apache.commons:commons-csv",
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-csv/",
|
"moduleUrl": "https://commons.apache.org/proper/commons-csv/",
|
||||||
@@ -1121,30 +1079,6 @@
|
|||||||
"moduleLicense": "Eclipse Public License, Version 2.0",
|
"moduleLicense": "Eclipse Public License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://github.com/locationtech/jts/blob/master/LICENSE_EPLv2.txt"
|
"moduleLicenseUrl": "https://github.com/locationtech/jts/blob/master/LICENSE_EPLv2.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.openjfx:javafx-base",
|
|
||||||
"moduleVersion": "21",
|
|
||||||
"moduleLicense": "GPLv2+CE",
|
|
||||||
"moduleLicenseUrl": "https://openjdk.java.net/legal/gplv2+ce.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.openjfx:javafx-controls",
|
|
||||||
"moduleVersion": "21",
|
|
||||||
"moduleLicense": "GPLv2+CE",
|
|
||||||
"moduleLicenseUrl": "https://openjdk.java.net/legal/gplv2+ce.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.openjfx:javafx-graphics",
|
|
||||||
"moduleVersion": "21",
|
|
||||||
"moduleLicense": "GPLv2+CE",
|
|
||||||
"moduleLicenseUrl": "https://openjdk.java.net/legal/gplv2+ce.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.openjfx:javafx-swing",
|
|
||||||
"moduleVersion": "21",
|
|
||||||
"moduleLicense": "GPLv2+CE",
|
|
||||||
"moduleLicenseUrl": "https://openjdk.java.net/legal/gplv2+ce.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.opensaml:opensaml-core",
|
"moduleName": "org.opensaml:opensaml-core",
|
||||||
"moduleVersion": "4.3.2",
|
"moduleVersion": "4.3.2",
|
||||||
@@ -1452,13 +1386,6 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.springframework.session:spring-session-core",
|
|
||||||
"moduleUrl": "https://spring.io/projects/spring-session",
|
|
||||||
"moduleVersion": "3.4.0",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-aop",
|
"moduleName": "org.springframework:spring-aop",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
@@ -1545,7 +1472,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.thymeleaf.extras:thymeleaf-extras-springsecurity5",
|
"moduleName": "org.thymeleaf.extras:thymeleaf-extras-springsecurity5",
|
||||||
"moduleVersion": "3.1.3.RELEASE",
|
"moduleVersion": "3.1.2.RELEASE",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@@ -1557,7 +1484,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.thymeleaf:thymeleaf-spring5",
|
"moduleName": "org.thymeleaf:thymeleaf-spring5",
|
||||||
"moduleVersion": "3.1.3.RELEASE",
|
"moduleVersion": "3.1.2.RELEASE",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,221 +1,10 @@
|
|||||||
.custom-file-chooser {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
min-height: 55px;
|
|
||||||
border-radius: 1rem;
|
|
||||||
--selected-files-display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container {
|
|
||||||
position: relative;
|
|
||||||
border-radius: 1rem;
|
|
||||||
border: 1px dashed rgb(105, 116, 134);
|
|
||||||
|
|
||||||
column-gap: 7px;
|
|
||||||
row-gap: 7px;
|
|
||||||
height: 150px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
--overlay-display: none;
|
|
||||||
transition: background-color 0.5s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container:hover {
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--md-sys-color-surface-container-low);
|
|
||||||
|
|
||||||
-webkit-transition: box-shadow 1s ease, background-color 2s linear;
|
|
||||||
-moz-transition: box-shadow 1s ease, background-color 2s linear;
|
|
||||||
-o-transition: box-shadow 1s ease, background-color 2s linear;
|
|
||||||
-ms-transition: box-shadow 1s ease, background-color 2s linear;
|
|
||||||
transition: box-shadow 1s ease, background-color 2s linear;
|
|
||||||
|
|
||||||
box-shadow: 0 0 10px rgb(105, 116, 134);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container * {
|
|
||||||
user-select: none;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.input-container::before {
|
|
||||||
display: var(--overlay-display);
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
content: '';
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
background-color: var(--md-sys-color-surface);
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
white-space: pre;
|
|
||||||
border-radius: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container::after {
|
|
||||||
display: var(--overlay-display);
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
content: attr(data-text);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
font-weight: 550;
|
|
||||||
color: var(--md-sys-color-on-surface);
|
|
||||||
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
min-width: 150px;
|
|
||||||
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
|
|
||||||
transform: translateX(-50%) translateY(-50%);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container input[type="file"] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container div:nth-of-type(2) {
|
|
||||||
color: var(--md-sys-color-on-surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container div:nth-of-type(1), .input-container div:nth-of-type(3) {
|
|
||||||
color: var(--md-sys-color-on-surface);
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-input-btn {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
padding: 6px 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
color: #212529;
|
|
||||||
font-size: 1rem;
|
|
||||||
border-radius: 3rem;
|
|
||||||
|
|
||||||
background-color: #DDE0E3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-file-container {
|
|
||||||
padding-top: 1px;
|
|
||||||
position: relative;
|
|
||||||
row-gap: 1px;
|
|
||||||
height: 60px;
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 30px;
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-icon * {
|
|
||||||
height: inherit;
|
|
||||||
width: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-info {
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-info > div:nth-child(1) {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: var(--md-sys-color-on-surface);
|
|
||||||
|
|
||||||
max-width: 60px;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-info > div:nth-child(2) {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
color: grey;
|
|
||||||
|
|
||||||
max-width: 60px;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove-selected-file {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
height: 15px;
|
|
||||||
width: 15px;
|
|
||||||
|
|
||||||
right: 10px;
|
|
||||||
top: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove-selected-file * {
|
|
||||||
overflow: hidden;
|
|
||||||
height: inherit;
|
|
||||||
width: inherit;
|
|
||||||
z-index: 3;
|
|
||||||
pointer-events: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove-selected-file:after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
left: 1;
|
|
||||||
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
background-color: white;
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove-selected-file:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-file-label {
|
.custom-file-label {
|
||||||
padding-right: 90px;
|
padding-right: 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-files {
|
.selected-files {
|
||||||
display: var(--selected-files-display);
|
margin-top: 10px;
|
||||||
padding-left: 5px;
|
max-height: 150px;
|
||||||
padding-right: 3px;
|
overflow-y: auto;
|
||||||
padding-top: 15px;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
|
|
||||||
flex: 1;
|
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
|
||||||
row-gap: 12px;
|
|
||||||
column-gap: 5px;
|
|
||||||
|
|
||||||
border-radius: 1rem;
|
|
||||||
border: 1px solid rgb(105, 116, 134, 0.5);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,6 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: -20px;
|
margin: -20px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-sizing:content-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-group-container.animated-group {
|
.feature-group-container.animated-group {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user