Compare commits
56 Commits
autoPrintE
...
v0.31.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
384c3ee88f | ||
|
|
5f7a0537f9 | ||
|
|
5aa5628465 | ||
|
|
0d91bca932 | ||
|
|
8e88591499 | ||
|
|
3e051d0105 | ||
|
|
4a9b16ff8f | ||
|
|
a7082ecd85 | ||
|
|
966e6a4923 | ||
|
|
27d2681a97 | ||
|
|
ed75fa4e1b | ||
|
|
9b9752bd7a | ||
|
|
903dc7638c | ||
|
|
c39b111edc | ||
|
|
d910929aa6 | ||
|
|
a9ce0e80ee | ||
|
|
4922ab700e | ||
|
|
01f3c138a6 | ||
|
|
4e21f76979 | ||
|
|
a9ccd85e75 | ||
|
|
6f407f1d2f | ||
|
|
af5e2b6895 | ||
|
|
d2046c64d8 | ||
|
|
1b88d89191 | ||
|
|
03bf98265b | ||
|
|
89da2a5c01 | ||
|
|
a10d06b693 | ||
|
|
a7ed99084f | ||
|
|
88f3594d80 | ||
|
|
e0b77ca274 | ||
|
|
bac81c930d | ||
|
|
2f49626a4c | ||
|
|
83ef003505 | ||
|
|
949b87005c | ||
|
|
532f7cdbbf | ||
|
|
51c4a60313 | ||
|
|
aa00808219 | ||
|
|
5d40175e18 | ||
|
|
a40fdd5a0b | ||
|
|
6ea7ffc36c | ||
|
|
39e0fd8eef | ||
|
|
cae8cd0aa9 | ||
|
|
04d5ae1912 | ||
|
|
e01ba93cf8 | ||
|
|
edd0ec9d23 | ||
|
|
899f3d267b | ||
|
|
88c0a9e26b | ||
|
|
dc6cec9daf | ||
|
|
a64dd2e282 | ||
|
|
c9b7d848b4 | ||
|
|
89a9ba6ebc | ||
|
|
22249ef9bf | ||
|
|
619a863b99 | ||
|
|
e098b2999c | ||
|
|
1149f2a30d | ||
|
|
eff1843061 |
53
.github/scripts/gradle_to_chart.py
vendored
53
.github/scripts/gradle_to_chart.py
vendored
@@ -8,17 +8,20 @@ gradle_path = "build.gradle"
|
|||||||
|
|
||||||
def get_chart_version(path):
|
def get_chart_version(path):
|
||||||
"""
|
"""
|
||||||
Reads the appVersion from Chart.yaml.
|
Reads the version and the appVersion from Chart.yaml.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): The file path to the Chart.yaml.
|
path (str): The file path to the Chart.yaml.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The appVersion if found, otherwise an empty string.
|
dict: The version under "chart" key and the appVersion under "app" key.
|
||||||
"""
|
"""
|
||||||
with open(path, encoding="utf-8") as file:
|
with open(path, encoding="utf-8") as file:
|
||||||
chart_yaml = yaml.safe_load(file)
|
chart_yaml = yaml.safe_load(file)
|
||||||
return chart_yaml.get("appVersion", "")
|
return {
|
||||||
|
"chart": chart_yaml["version"],
|
||||||
|
"app": chart_yaml["appVersion"]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_gradle_version(path):
|
def get_gradle_version(path):
|
||||||
@@ -39,17 +42,46 @@ def get_gradle_version(path):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def update_chart_version(path, new_version):
|
def get_new_chart_version(chart_version, old_app_version, new_app_version):
|
||||||
|
"""
|
||||||
|
Get the new chart version from
|
||||||
|
|
||||||
|
Args:
|
||||||
|
str: The current chart version.
|
||||||
|
str: The current app version.
|
||||||
|
str: The new app version.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The new chart version to update to.
|
||||||
|
"""
|
||||||
|
chart_major, chart_minor, chart_patch = chart_version.split(".")
|
||||||
|
|
||||||
|
old_major, old_minor, old_patch = old_app_version.split(".")
|
||||||
|
new_major, new_minor, new_patch = new_app_version.split(".")
|
||||||
|
|
||||||
|
if old_major != new_major:
|
||||||
|
new_chart_version = f"{int(chart_major)+1}.0.0"
|
||||||
|
elif old_minor != new_minor:
|
||||||
|
new_chart_version = f"{chart_major}.{int(chart_minor)+1}.0"
|
||||||
|
elif old_patch != new_patch:
|
||||||
|
new_chart_version = f"{chart_major}.{chart_minor}.{int(chart_patch)+1}"
|
||||||
|
|
||||||
|
return new_chart_version
|
||||||
|
|
||||||
|
|
||||||
|
def update_chart_version(path, new_chart_version, new_app_version):
|
||||||
"""
|
"""
|
||||||
Updates the appVersion in Chart.yaml with a new version.
|
Updates the version and the appVersion in Chart.yaml with a new version.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): The file path to the Chart.yaml.
|
path (str): The file path to the Chart.yaml.
|
||||||
new_version (str): The new version to update to.
|
new_chart_version (str): The new chart version to update to.
|
||||||
|
new_app_version (str): The new app version to update to.
|
||||||
"""
|
"""
|
||||||
with open(path, encoding="utf-8") as file:
|
with open(path, encoding="utf-8") as file:
|
||||||
chart_yaml = yaml.safe_load(file)
|
chart_yaml = yaml.safe_load(file)
|
||||||
chart_yaml["appVersion"] = new_version
|
chart_yaml["version"] = new_chart_version
|
||||||
|
chart_yaml["appVersion"] = new_app_version
|
||||||
with open(path, "w", encoding="utf-8") as file:
|
with open(path, "w", encoding="utf-8") as file:
|
||||||
yaml.safe_dump(chart_yaml, file)
|
yaml.safe_dump(chart_yaml, file)
|
||||||
|
|
||||||
@@ -58,10 +90,11 @@ def update_chart_version(path, new_version):
|
|||||||
chart_version = get_chart_version(chart_yaml_path)
|
chart_version = get_chart_version(chart_yaml_path)
|
||||||
gradle_version = get_gradle_version(gradle_path)
|
gradle_version = get_gradle_version(gradle_path)
|
||||||
|
|
||||||
if chart_version != gradle_version:
|
if chart_version["app"] != gradle_version:
|
||||||
|
new_chart_version = get_new_chart_version(chart_version["chart"], chart_version["app"], gradle_version, )
|
||||||
print(
|
print(
|
||||||
f"Versions do not match. Updating Chart.yaml from {chart_version} to {gradle_version}."
|
f"Versions do not match. Updating Chart.yaml from {chart_version['chart']} to {new_chart_version}."
|
||||||
)
|
)
|
||||||
update_chart_version(chart_yaml_path, gradle_version)
|
update_chart_version(chart_yaml_path, new_chart_version, gradle_version)
|
||||||
else:
|
else:
|
||||||
print("Versions match. No update required.")
|
print("Versions match. No update required.")
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ bin/
|
|||||||
tmp/
|
tmp/
|
||||||
*.tmp
|
*.tmp
|
||||||
*.bak
|
*.bak
|
||||||
|
*.exe
|
||||||
*.swp
|
*.swp
|
||||||
*~.nib
|
*~.nib
|
||||||
local.properties
|
local.properties
|
||||||
|
|||||||
63
README.md
63
README.md
@@ -166,6 +166,13 @@ Note: Podman is CLI-compatible with Docker, so simply replace "docker" with "pod
|
|||||||
|
|
||||||
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md
|
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md
|
||||||
|
|
||||||
|
## Reuse stored files
|
||||||
|
|
||||||
|
Certain functionality like ``Sign`` Supports pre-saved files stored at ``/customFiles/signatures/``, image files placed within here will be accesable to be used via webUI
|
||||||
|
Currently this supports two folder types
|
||||||
|
- ``/customFiles/signatures/ALL_USERS`` accessible to all users, useful for orginasations were many users use same files or for users not using authentication
|
||||||
|
- ``/customFiles/signatures/{username}`` such as ``/customFiles/signatures/froodle`` accessible to only the ``froodle`` username, private for all others
|
||||||
|
|
||||||
## Supported Languages
|
## Supported Languages
|
||||||
|
|
||||||
Stirling PDF currently supports 38!
|
Stirling PDF currently supports 38!
|
||||||
@@ -173,40 +180,40 @@ Stirling PDF currently supports 38!
|
|||||||
| Language | Progress |
|
| Language | Progress |
|
||||||
| ------------------------------------------- | -------------------------------------- |
|
| ------------------------------------------- | -------------------------------------- |
|
||||||
| Arabic (العربية) (ar_AR) |  |
|
| Arabic (العربية) (ar_AR) |  |
|
||||||
| 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) |  |
|
||||||
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
| Indonesia (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) |  |
|
||||||
| 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.)
|
||||||
|
|||||||
35
build.gradle
35
build.gradle
@@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id "java"
|
||||||
id "org.springframework.boot" version "3.3.4"
|
id "org.springframework.boot" version "3.3.5"
|
||||||
id "io.spring.dependency-management" version "1.1.6"
|
id "io.spring.dependency-management" version "1.1.6"
|
||||||
id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
|
id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
|
||||||
id "io.swagger.swaggerhub" version "1.3.2"
|
id "io.swagger.swaggerhub" version "1.3.2"
|
||||||
@@ -13,7 +13,7 @@ plugins {
|
|||||||
import com.github.jk1.license.render.*
|
import com.github.jk1.license.render.*
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
springBootVersion = "3.3.4"
|
springBootVersion = "3.3.5"
|
||||||
pdfboxVersion = "3.0.3"
|
pdfboxVersion = "3.0.3"
|
||||||
logbackVersion = "1.5.7"
|
logbackVersion = "1.5.7"
|
||||||
imageioVersion = "3.12.0"
|
imageioVersion = "3.12.0"
|
||||||
@@ -22,7 +22,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
group = "stirling.software"
|
||||||
version = "0.30.0"
|
version = "0.31.1"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
// 17 is lowest but we support and recommend 21
|
// 17 is lowest but we support and recommend 21
|
||||||
@@ -32,11 +32,9 @@ java {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven {
|
maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
|
||||||
url "https://build.shibboleth.net/nexus/content/repositories/releases/"
|
|
||||||
}
|
|
||||||
maven {
|
maven {
|
||||||
url "https://build.shibboleth.net/maven/releases/"
|
url 'https://build.shibboleth.net/maven/releases'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +119,7 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
//security updates
|
//security updates
|
||||||
implementation "org.springframework:spring-webmvc:6.1.13"
|
implementation "org.springframework:spring-webmvc:6.1.14"
|
||||||
|
|
||||||
implementation("io.github.pixee:java-security-toolkit:1.2.0")
|
implementation("io.github.pixee:java-security-toolkit:1.2.0")
|
||||||
|
|
||||||
@@ -139,15 +137,25 @@ 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"
|
||||||
runtimeOnly "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.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.security:spring-security-saml2-service-provider:6.3.3'
|
implementation 'org.springframework.security:spring-security-saml2-service-provider:6.3.4'
|
||||||
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
||||||
//2.2.x requires rebuild of DB file.. need migration path
|
//2.2.x requires rebuild of DB file.. need migration path
|
||||||
runtimeOnly "com.h2database:h2:2.1.214"
|
runtimeOnly "com.h2database:h2:2.1.214"
|
||||||
// implementation "com.h2database:h2:2.2.224"
|
// implementation "com.h2database:h2:2.2.224"
|
||||||
|
constraints {
|
||||||
|
implementation "org.opensaml:opensaml-core"
|
||||||
|
implementation "org.opensaml:opensaml-saml-api"
|
||||||
|
implementation "org.opensaml:opensaml-saml-impl"
|
||||||
|
}
|
||||||
|
implementation "org.springframework.security:spring-security-saml2-service-provider"
|
||||||
|
|
||||||
|
implementation 'com.coveo:saml-client:5.0.0'
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
||||||
@@ -173,6 +181,9 @@ dependencies {
|
|||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
||||||
|
|
||||||
|
// Image metadata extractor
|
||||||
|
implementation "com.drewnoakes:metadata-extractor:2.19.0"
|
||||||
|
|
||||||
implementation "commons-io:commons-io:2.17.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
|
||||||
@@ -198,8 +209,8 @@ dependencies {
|
|||||||
implementation "io.micrometer:micrometer-core:1.13.6"
|
implementation "io.micrometer:micrometer-core:1.13.6"
|
||||||
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
|
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
|
||||||
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
||||||
implementation "org.commonmark:commonmark:0.23.0"
|
implementation "org.commonmark:commonmark:0.24.0"
|
||||||
implementation "org.commonmark:commonmark-ext-gfm-tables:0.23.0"
|
implementation "org.commonmark:commonmark-ext-gfm-tables:0.24.0"
|
||||||
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
||||||
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
|
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
|
||||||
implementation "com.fathzer:javaluator:3.0.5"
|
implementation "com.fathzer:javaluator:3.0.5"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 0.30.0
|
appVersion: 0.31.1
|
||||||
description: locally hosted web application that allows you to perform various operations
|
description: locally hosted web application that allows you to perform various operations
|
||||||
on PDF files
|
on PDF files
|
||||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
@@ -13,4 +13,4 @@ maintainers:
|
|||||||
name: stirling-pdf-chart
|
name: stirling-pdf-chart
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/Stirling-Tools/Stirling-PDF
|
- https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
version: 1.0.0
|
version: 1.0.1
|
||||||
|
|||||||
20
scripts/remove_translation_keys.sh
Normal file
20
scripts/remove_translation_keys.sh
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if a key was provided
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "Please provide a key to remove."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
key_to_remove="$1"
|
||||||
|
|
||||||
|
for file in ../src/main/resources/messages_*.properties; do
|
||||||
|
# If the key ends with a dot, remove all keys starting with it
|
||||||
|
if [[ "$key_to_remove" == *. ]]; then
|
||||||
|
sed -i "/^${key_to_remove//./\\.}/d" "$file"
|
||||||
|
else
|
||||||
|
# Otherwise, remove only the exact key match
|
||||||
|
sed -i "/^${key_to_remove//./\\.}=/d" "$file"
|
||||||
|
fi
|
||||||
|
echo "Updated $file"
|
||||||
|
done
|
||||||
@@ -1,22 +1,19 @@
|
|||||||
package stirling.software.SPDF.EE;
|
package stirling.software.SPDF.EE;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
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.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Lazy
|
@Lazy
|
||||||
|
@Slf4j
|
||||||
public class EEAppConfig {
|
public class EEAppConfig {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(EEAppConfig.class);
|
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Autowired private LicenseKeyChecker licenseKeyChecker;
|
@Autowired private LicenseKeyChecker licenseKeyChecker;
|
||||||
|
|
||||||
@Bean(name = "runningEE")
|
@Bean(name = "runningEE")
|
||||||
|
|||||||
@@ -33,8 +33,12 @@ public class SPdfApplication {
|
|||||||
@Autowired private Environment env;
|
@Autowired private Environment env;
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
private static String baseUrlStatic;
|
||||||
private static String serverPortStatic;
|
private static String serverPortStatic;
|
||||||
|
|
||||||
|
@Value("${baseUrl:http://localhost}")
|
||||||
|
private String baseUrl;
|
||||||
|
|
||||||
@Value("${server.port:8080}")
|
@Value("${server.port:8080}")
|
||||||
public void setServerPortStatic(String port) {
|
public void setServerPortStatic(String port) {
|
||||||
if ("auto".equalsIgnoreCase(port)) {
|
if ("auto".equalsIgnoreCase(port)) {
|
||||||
@@ -65,12 +69,13 @@ public class SPdfApplication {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
|
baseUrlStatic = this.baseUrl;
|
||||||
// Check if the BROWSER_OPEN environment variable is set to true
|
// Check if the BROWSER_OPEN environment variable is set to true
|
||||||
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
||||||
boolean browserOpen = browserOpenEnv != null && "true".equalsIgnoreCase(browserOpenEnv);
|
boolean browserOpen = browserOpenEnv != null && "true".equalsIgnoreCase(browserOpenEnv);
|
||||||
if (browserOpen) {
|
if (browserOpen) {
|
||||||
try {
|
try {
|
||||||
String url = "http://localhost:" + getStaticPort();
|
String url = baseUrl + ":" + getStaticPort();
|
||||||
|
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
Runtime rt = Runtime.getRuntime();
|
Runtime rt = Runtime.getRuntime();
|
||||||
@@ -138,10 +143,18 @@ public class SPdfApplication {
|
|||||||
|
|
||||||
private static void printStartupLogs() {
|
private static void printStartupLogs() {
|
||||||
logger.info("Stirling-PDF Started.");
|
logger.info("Stirling-PDF Started.");
|
||||||
String url = "http://localhost:" + getStaticPort();
|
String url = baseUrlStatic + ":" + getStaticPort();
|
||||||
logger.info("Navigate to {}", url);
|
logger.info("Navigate to {}", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getStaticBaseUrl() {
|
||||||
|
return baseUrlStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonStaticBaseUrl() {
|
||||||
|
return baseUrlStatic;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getStaticPort() {
|
public static String getStaticPort() {
|
||||||
return serverPortStatic;
|
return serverPortStatic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ 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.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@@ -162,12 +163,14 @@ public class AppConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "analyticsPrompt")
|
@Bean(name = "analyticsPrompt")
|
||||||
|
@Scope("request")
|
||||||
public boolean analyticsPrompt() {
|
public boolean analyticsPrompt() {
|
||||||
return applicationProperties.getSystem().getEnableAnalytics() == null
|
return applicationProperties.getSystem().getEnableAnalytics() == null
|
||||||
|| "undefined".equals(applicationProperties.getSystem().getEnableAnalytics());
|
|| "undefined".equals(applicationProperties.getSystem().getEnableAnalytics());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "analyticsEnabled")
|
@Bean(name = "analyticsEnabled")
|
||||||
|
@Scope("request")
|
||||||
public boolean analyticsEnabled() {
|
public boolean analyticsEnabled() {
|
||||||
if (applicationProperties.getEnterpriseEdition().isEnabled()) return true;
|
if (applicationProperties.getEnterpriseEdition().isEnabled()) return true;
|
||||||
return applicationProperties.getSystem().getEnableAnalytics() != null
|
return applicationProperties.getSystem().getEnableAnalytics() != null
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -42,7 +43,7 @@ public class EndpointConfiguration {
|
|||||||
|
|
||||||
public void disableEndpoint(String endpoint) {
|
public void disableEndpoint(String endpoint) {
|
||||||
if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
||||||
logger.info("Disabling {}", endpoint);
|
logger.debug("Disabling {}", endpoint);
|
||||||
endpointStatuses.put(endpoint, false);
|
endpointStatuses.put(endpoint, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,6 +77,23 @@ public class EndpointConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void logDisabledEndpointsSummary() {
|
||||||
|
List<String> disabledList =
|
||||||
|
endpointStatuses.entrySet().stream()
|
||||||
|
.filter(entry -> !entry.getValue()) // only get disabled endpoints (value
|
||||||
|
// is false)
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!disabledList.isEmpty()) {
|
||||||
|
logger.info(
|
||||||
|
"Total disabled endpoints: {}. Disabled endpoints: {}",
|
||||||
|
disabledList.size(),
|
||||||
|
String.join(", ", disabledList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
// Adding endpoints to "PageOps" group
|
// Adding endpoints to "PageOps" group
|
||||||
addEndpointToGroup("PageOps", "remove-pages");
|
addEndpointToGroup("PageOps", "remove-pages");
|
||||||
@@ -163,14 +181,12 @@ public class EndpointConfiguration {
|
|||||||
|
|
||||||
// python
|
// python
|
||||||
addEndpointToGroup("Python", "extract-image-scans");
|
addEndpointToGroup("Python", "extract-image-scans");
|
||||||
addEndpointToGroup("Python", REMOVE_BLANKS);
|
|
||||||
addEndpointToGroup("Python", "html-to-pdf");
|
addEndpointToGroup("Python", "html-to-pdf");
|
||||||
addEndpointToGroup("Python", "url-to-pdf");
|
addEndpointToGroup("Python", "url-to-pdf");
|
||||||
addEndpointToGroup("Python", "pdf-to-img");
|
addEndpointToGroup("Python", "pdf-to-img");
|
||||||
|
|
||||||
// openCV
|
// openCV
|
||||||
addEndpointToGroup("OpenCV", "extract-image-scans");
|
addEndpointToGroup("OpenCV", "extract-image-scans");
|
||||||
addEndpointToGroup("OpenCV", REMOVE_BLANKS);
|
|
||||||
|
|
||||||
// LibreOffice
|
// LibreOffice
|
||||||
addEndpointToGroup("LibreOffice", "repair");
|
addEndpointToGroup("LibreOffice", "repair");
|
||||||
@@ -230,6 +246,17 @@ public class EndpointConfiguration {
|
|||||||
addEndpointToGroup("Javascript", "sign");
|
addEndpointToGroup("Javascript", "sign");
|
||||||
addEndpointToGroup("Javascript", "compare");
|
addEndpointToGroup("Javascript", "compare");
|
||||||
addEndpointToGroup("Javascript", "adjust-contrast");
|
addEndpointToGroup("Javascript", "adjust-contrast");
|
||||||
|
|
||||||
|
// Ghostscript dependent endpoints
|
||||||
|
addEndpointToGroup("Ghostscript", "compress-pdf");
|
||||||
|
addEndpointToGroup("Ghostscript", "pdf-to-pdfa");
|
||||||
|
|
||||||
|
// Weasyprint dependent endpoints
|
||||||
|
addEndpointToGroup("Weasyprint", "html-to-pdf");
|
||||||
|
addEndpointToGroup("Weasyprint", "url-to-pdf");
|
||||||
|
|
||||||
|
// Pdftohtml dependent endpoints
|
||||||
|
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processEnvironmentConfigs() {
|
private void processEnvironmentConfigs() {
|
||||||
@@ -251,5 +278,9 @@ public class EndpointConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getEndpointsForGroup(String group) {
|
||||||
|
return endpointGroups.getOrDefault(group, new HashSet<>());
|
||||||
|
}
|
||||||
|
|
||||||
private static final String REMOVE_BLANKS = "remove-blanks";
|
private static final String REMOVE_BLANKS = "remove-blanks";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class ExternalAppDepConfig {
|
||||||
|
@Autowired private EndpointConfiguration endpointConfiguration;
|
||||||
|
|
||||||
|
private boolean isCommandAvailable(String command) {
|
||||||
|
try {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||||
|
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||||
|
processBuilder.command("where", command);
|
||||||
|
} else {
|
||||||
|
processBuilder.command("which", command);
|
||||||
|
}
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
return exitCode == 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Error checking for command {}: {}", command, e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<String, List<String>> commandToGroupMapping =
|
||||||
|
new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("gs", List.of("Ghostscript"));
|
||||||
|
put("soffice", List.of("LibreOffice"));
|
||||||
|
put("ocrmypdf", List.of("OCRmyPDF"));
|
||||||
|
put("weasyprint", List.of("Weasyprint"));
|
||||||
|
put("pdftohtml", List.of("Pdftohtml"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private List<String> getAffectedFeatures(String group) {
|
||||||
|
return endpointConfiguration.getEndpointsForGroup(group).stream()
|
||||||
|
.map(endpoint -> formatEndpointAsFeature(endpoint))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatEndpointAsFeature(String endpoint) {
|
||||||
|
// First replace common terms
|
||||||
|
String feature = endpoint.replace("-", " ").replace("pdf", "PDF").replace("img", "image");
|
||||||
|
|
||||||
|
// Split into words and capitalize each word
|
||||||
|
return Arrays.stream(feature.split("\\s+"))
|
||||||
|
.map(word -> capitalizeWord(word))
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String capitalizeWord(String word) {
|
||||||
|
if (word.isEmpty()) {
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
if ("pdf".equalsIgnoreCase(word)) {
|
||||||
|
return "PDF";
|
||||||
|
}
|
||||||
|
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDependencyAndDisableGroup(String command) {
|
||||||
|
boolean isAvailable = isCommandAvailable(command);
|
||||||
|
if (!isAvailable) {
|
||||||
|
List<String> affectedGroups = commandToGroupMapping.get(command);
|
||||||
|
|
||||||
|
if (affectedGroups != null) {
|
||||||
|
for (String group : affectedGroups) {
|
||||||
|
List<String> affectedFeatures = getAffectedFeatures(group);
|
||||||
|
endpointConfiguration.disableGroup(group);
|
||||||
|
log.warn(
|
||||||
|
"Missing dependency: {} - Disabling group: {} (Affected features: {})",
|
||||||
|
command,
|
||||||
|
group,
|
||||||
|
affectedFeatures != null && !affectedFeatures.isEmpty()
|
||||||
|
? String.join(", ", affectedFeatures)
|
||||||
|
: "unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void checkDependencies() {
|
||||||
|
|
||||||
|
// Check core dependencies
|
||||||
|
checkDependencyAndDisableGroup("gs");
|
||||||
|
checkDependencyAndDisableGroup("soffice");
|
||||||
|
checkDependencyAndDisableGroup("ocrmypdf");
|
||||||
|
checkDependencyAndDisableGroup("weasyprint");
|
||||||
|
checkDependencyAndDisableGroup("pdftohtml");
|
||||||
|
|
||||||
|
// Special handling for Python/OpenCV dependencies
|
||||||
|
boolean pythonAvailable = isCommandAvailable("python3") || isCommandAvailable("python");
|
||||||
|
if (!pythonAvailable) {
|
||||||
|
List<String> pythonFeatures = getAffectedFeatures("Python");
|
||||||
|
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||||
|
|
||||||
|
endpointConfiguration.disableGroup("Python");
|
||||||
|
endpointConfiguration.disableGroup("OpenCV");
|
||||||
|
log.warn(
|
||||||
|
"Missing dependency: Python - Disabling Python features: {} and OpenCV features: {}",
|
||||||
|
String.join(", ", pythonFeatures),
|
||||||
|
String.join(", ", openCVFeatures));
|
||||||
|
} else {
|
||||||
|
// If Python is available, check for OpenCV
|
||||||
|
try {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||||
|
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||||
|
processBuilder.command("python", "-c", "import cv2");
|
||||||
|
} else {
|
||||||
|
processBuilder.command("python3", "-c", "import cv2");
|
||||||
|
}
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||||
|
endpointConfiguration.disableGroup("OpenCV");
|
||||||
|
log.warn(
|
||||||
|
"OpenCV not available in Python - Disabling OpenCV features: {}",
|
||||||
|
String.join(", ", openCVFeatures));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||||
|
endpointConfiguration.disableGroup("OpenCV");
|
||||||
|
log.warn(
|
||||||
|
"Error checking OpenCV: {} - Disabling OpenCV features: {}",
|
||||||
|
e.getMessage(),
|
||||||
|
String.join(", ", openCVFeatures));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpointConfiguration.logDisabledEndpointsSummary();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import org.springframework.core.Ordered;
|
|||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import io.micrometer.common.util.StringUtils;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
@@ -39,4 +41,23 @@ public class InitialSetup {
|
|||||||
applicationProperties.getAutomaticallyGenerated().setKey(secretKey);
|
applicationProperties.getAutomaticallyGenerated().setKey(secretKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void initLegalUrls() throws IOException {
|
||||||
|
// Initialize Terms and Conditions
|
||||||
|
String termsUrl = applicationProperties.getLegal().getTermsAndConditions();
|
||||||
|
if (StringUtils.isEmpty(termsUrl)) {
|
||||||
|
String defaultTermsUrl = "https://www.stirlingpdf.com/terms-and-conditions";
|
||||||
|
GeneralUtils.saveKeyToConfig("legal.termsAndConditions", defaultTermsUrl);
|
||||||
|
applicationProperties.getLegal().setTermsAndConditions(defaultTermsUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Privacy Policy
|
||||||
|
String privacyUrl = applicationProperties.getLegal().getPrivacyPolicy();
|
||||||
|
if (StringUtils.isEmpty(privacyUrl)) {
|
||||||
|
String defaultPrivacyUrl = "https://www.stirlingpdf.com/privacy-policy";
|
||||||
|
GeneralUtils.saveKeyToConfig("legal.privacyPolicy", defaultPrivacyUrl);
|
||||||
|
applicationProperties.getLegal().setPrivacyPolicy(defaultPrivacyUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,237 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||||
|
|
||||||
|
import com.coveo.saml.SamlClient;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.SPdfApplication;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
||||||
|
import stirling.software.SPDF.model.Provider;
|
||||||
|
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
|
||||||
|
import stirling.software.SPDF.utils.UrlUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||||
|
|
||||||
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLogoutSuccess(
|
public void onLogoutSuccess(
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
|
|
||||||
if (request.getParameter("userIsDisabled") != null) {
|
if (!response.isCommitted()) {
|
||||||
getRedirectStrategy()
|
// Handle user logout due to disabled account
|
||||||
.sendRedirect(request, response, "/login?erroroauth=userIsDisabled");
|
if (request.getParameter("userIsDisabled") != null) {
|
||||||
return;
|
response.sendRedirect(
|
||||||
|
request.getContextPath() + "/login?erroroauth=userIsDisabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handle OAuth2 authentication error
|
||||||
|
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
||||||
|
response.sendRedirect(
|
||||||
|
request.getContextPath() + "/login?erroroauth=userAlreadyExistsWeb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (authentication != null) {
|
||||||
|
// Handle SAML2 logout redirection
|
||||||
|
if (authentication instanceof Saml2Authentication) {
|
||||||
|
getRedirect_saml2(request, response, authentication);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handle OAuth2 logout redirection
|
||||||
|
else if (authentication instanceof OAuth2AuthenticationToken) {
|
||||||
|
getRedirect_oauth2(request, response, authentication);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handle Username/Password logout
|
||||||
|
else if (authentication instanceof UsernamePasswordAuthenticationToken) {
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handle unknown authentication types
|
||||||
|
else {
|
||||||
|
log.error(
|
||||||
|
"authentication class unknown: "
|
||||||
|
+ authentication.getClass().getSimpleName());
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect to login page after logout
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect for SAML2 authentication logout
|
||||||
|
private void getRedirect_saml2(
|
||||||
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
|
||||||
|
String registrationId = samlConf.getRegistrationId();
|
||||||
|
|
||||||
|
Saml2Authentication samlAuthentication = (Saml2Authentication) authentication;
|
||||||
|
CustomSaml2AuthenticatedPrincipal principal =
|
||||||
|
(CustomSaml2AuthenticatedPrincipal) samlAuthentication.getPrincipal();
|
||||||
|
|
||||||
|
String nameIdValue = principal.getName();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read certificate from the resource
|
||||||
|
Resource certificateResource = samlConf.getSpCert();
|
||||||
|
X509Certificate certificate = CertificateUtils.readCertificate(certificateResource);
|
||||||
|
|
||||||
|
List<X509Certificate> certificates = new ArrayList<>();
|
||||||
|
certificates.add(certificate);
|
||||||
|
|
||||||
|
// Construct URLs required for SAML configuration
|
||||||
|
String serverUrl =
|
||||||
|
SPdfApplication.getStaticBaseUrl() + ":" + SPdfApplication.getStaticPort();
|
||||||
|
|
||||||
|
String relyingPartyIdentifier =
|
||||||
|
serverUrl + "/saml2/service-provider-metadata/" + registrationId;
|
||||||
|
|
||||||
|
String assertionConsumerServiceUrl = serverUrl + "/login/saml2/sso/" + registrationId;
|
||||||
|
|
||||||
|
String idpUrl = samlConf.getIdpSingleLogoutUrl();
|
||||||
|
|
||||||
|
String idpIssuer = samlConf.getIdpIssuer();
|
||||||
|
|
||||||
|
// Create SamlClient instance for SAML logout
|
||||||
|
SamlClient samlClient =
|
||||||
|
new SamlClient(
|
||||||
|
relyingPartyIdentifier,
|
||||||
|
assertionConsumerServiceUrl,
|
||||||
|
idpUrl,
|
||||||
|
idpIssuer,
|
||||||
|
certificates,
|
||||||
|
SamlClient.SamlIdpBinding.POST);
|
||||||
|
|
||||||
|
// Read private key for service provider
|
||||||
|
Resource privateKeyResource = samlConf.getPrivateKey();
|
||||||
|
RSAPrivateKey privateKey = CertificateUtils.readPrivateKey(privateKeyResource);
|
||||||
|
|
||||||
|
// Set service provider keys for the SamlClient
|
||||||
|
samlClient.setSPKeys(certificate, privateKey);
|
||||||
|
|
||||||
|
// Redirect to identity provider for logout
|
||||||
|
samlClient.redirectToIdentityProvider(response, null, nameIdValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(nameIdValue, e);
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect for OAuth2 authentication logout
|
||||||
|
private void getRedirect_oauth2(
|
||||||
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
|
throws IOException {
|
||||||
|
String param = "logout=true";
|
||||||
|
String registrationId = null;
|
||||||
|
String issuer = null;
|
||||||
|
String clientId = null;
|
||||||
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
|
||||||
|
if (authentication instanceof OAuth2AuthenticationToken) {
|
||||||
|
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
|
||||||
|
registrationId = oauthToken.getAuthorizedClientRegistrationId();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get OAuth2 provider details from configuration
|
||||||
|
Provider provider = oauth.getClient().get(registrationId);
|
||||||
|
issuer = provider.getIssuer();
|
||||||
|
clientId = provider.getClientId();
|
||||||
|
} catch (UnsupportedProviderException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
registrationId = oauth.getProvider() != null ? oauth.getProvider() : "";
|
||||||
|
issuer = oauth.getIssuer();
|
||||||
|
clientId = oauth.getClientId();
|
||||||
|
}
|
||||||
|
String errorMessage = "";
|
||||||
|
// Handle different error scenarios during logout
|
||||||
|
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
||||||
|
param = "erroroauth=oauth2AuthenticationErrorWeb";
|
||||||
|
} else if ((errorMessage = request.getParameter("error")) != null) {
|
||||||
|
param = "error=" + sanitizeInput(errorMessage);
|
||||||
|
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
|
||||||
|
param = "erroroauth=" + sanitizeInput(errorMessage);
|
||||||
|
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
|
||||||
|
param = "error=oauth2AutoCreateDisabled";
|
||||||
|
} else if (request.getParameter("oauth2_admin_blocked_user") != null) {
|
||||||
|
param = "erroroauth=oauth2_admin_blocked_user";
|
||||||
|
} else if (request.getParameter("userIsDisabled") != null) {
|
||||||
|
param = "erroroauth=userIsDisabled";
|
||||||
|
} else if (request.getParameter("badcredentials") != null) {
|
||||||
|
param = "error=badcredentials";
|
||||||
}
|
}
|
||||||
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
String redirect_url = UrlUtils.getOrigin(request) + "/login?" + param;
|
||||||
|
|
||||||
|
// Redirect based on OAuth2 provider
|
||||||
|
switch (registrationId.toLowerCase()) {
|
||||||
|
case "keycloak":
|
||||||
|
// Add Keycloak specific logout URL if needed
|
||||||
|
String logoutUrl =
|
||||||
|
issuer
|
||||||
|
+ "/protocol/openid-connect/logout"
|
||||||
|
+ "?client_id="
|
||||||
|
+ clientId
|
||||||
|
+ "&post_logout_redirect_uri="
|
||||||
|
+ response.encodeRedirectURL(redirect_url);
|
||||||
|
log.info("Redirecting to Keycloak logout URL: " + logoutUrl);
|
||||||
|
response.sendRedirect(logoutUrl);
|
||||||
|
break;
|
||||||
|
case "github":
|
||||||
|
// Add GitHub specific logout URL if needed
|
||||||
|
String githubLogoutUrl = "https://github.com/logout";
|
||||||
|
log.info("Redirecting to GitHub logout URL: " + githubLogoutUrl);
|
||||||
|
response.sendRedirect(githubLogoutUrl);
|
||||||
|
break;
|
||||||
|
case "google":
|
||||||
|
// Add Google specific logout URL if needed
|
||||||
|
// String googleLogoutUrl =
|
||||||
|
// "https://accounts.google.com/Logout?continue=https://appengine.google.com/_ah/logout?continue="
|
||||||
|
// + response.encodeRedirectURL(redirect_url);
|
||||||
|
log.info("Google does not have a specific logout URL");
|
||||||
|
// log.info("Redirecting to Google logout URL: " + googleLogoutUrl);
|
||||||
|
// response.sendRedirect(googleLogoutUrl);
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
String defaultRedirectUrl = request.getContextPath() + "/login?" + param;
|
||||||
|
log.info("Redirecting to default logout URL: " + defaultRedirectUrl);
|
||||||
|
response.sendRedirect(defaultRedirectUrl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize input to avoid potential security vulnerabilities
|
||||||
|
private String sanitizeInput(String input) {
|
||||||
|
return input.replaceAll("[^a-zA-Z0-9 ]", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,63 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
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.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
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;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
|
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||||
|
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
|
||||||
|
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
||||||
|
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||||
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
|
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
|
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
|
||||||
|
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.RelyingPartyRegistrationRepository;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||||
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
|
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
|
||||||
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;
|
||||||
|
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||||
|
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 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;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
|
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
||||||
import stirling.software.SPDF.config.security.saml.ConvertResponseToAuthentication;
|
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
|
||||||
import stirling.software.SPDF.config.security.saml.CustomSAMLAuthenticationFailureHandler;
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationFailureHandler;
|
||||||
import stirling.software.SPDF.config.security.saml.CustomSAMLAuthenticationSuccessHandler;
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationSuccessHandler;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2ResponseAuthenticationConverter;
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
||||||
|
import stirling.software.SPDF.model.User;
|
||||||
|
import stirling.software.SPDF.model.provider.GithubProvider;
|
||||||
|
import stirling.software.SPDF.model.provider.GoogleProvider;
|
||||||
|
import stirling.software.SPDF.model.provider.KeycloakProvider;
|
||||||
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -45,12 +68,6 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
@Autowired private CustomUserDetailsService userDetailsService;
|
@Autowired private CustomUserDetailsService userDetailsService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private GrantedAuthoritiesMapper userAuthoritiesMapper;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
@@ -71,17 +88,49 @@ public class SecurityConfiguration {
|
|||||||
@Autowired private FirstLoginFilter firstLoginFilter;
|
@Autowired private FirstLoginFilter firstLoginFilter;
|
||||||
@Autowired private SessionPersistentRegistry sessionRegistry;
|
@Autowired private SessionPersistentRegistry sessionRegistry;
|
||||||
|
|
||||||
@Autowired private ConvertResponseToAuthentication convertResponseToAuthentication;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
http.authenticationManager(authenticationManager(http));
|
|
||||||
|
|
||||||
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());
|
http.csrf(csrf -> csrf.disable());
|
||||||
|
} else {
|
||||||
|
CookieCsrfTokenRepository cookieRepo =
|
||||||
|
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||||
|
CsrfTokenRequestAttributeHandler requestHandler =
|
||||||
|
new CsrfTokenRequestAttributeHandler();
|
||||||
|
requestHandler.setCsrfRequestAttributeName(null);
|
||||||
|
http.csrf(
|
||||||
|
csrf ->
|
||||||
|
csrf.ignoringRequestMatchers(
|
||||||
|
request -> {
|
||||||
|
String apiKey = request.getHeader("X-API-Key");
|
||||||
|
|
||||||
|
// If there's no API key, don't ignore CSRF
|
||||||
|
// (return false)
|
||||||
|
if (apiKey == null || apiKey.trim().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate API key using existing UserService
|
||||||
|
try {
|
||||||
|
Optional<User> user =
|
||||||
|
userService.getUserByApiKey(apiKey);
|
||||||
|
// If API key is valid, ignore CSRF (return
|
||||||
|
// true)
|
||||||
|
// If API key is invalid, don't ignore CSRF
|
||||||
|
// (return false)
|
||||||
|
return user.isPresent();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// If there's any error validating the API
|
||||||
|
// key, don't ignore CSRF
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.csrfTokenRepository(cookieRepo)
|
||||||
|
.csrfTokenRequestHandler(requestHandler));
|
||||||
}
|
}
|
||||||
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||||
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
@@ -94,134 +143,134 @@ public class SecurityConfiguration {
|
|||||||
.sessionRegistry(sessionRegistry)
|
.sessionRegistry(sessionRegistry)
|
||||||
.expiredUrl("/login?logout=true"));
|
.expiredUrl("/login?logout=true"));
|
||||||
|
|
||||||
http.formLogin(
|
http.authenticationProvider(daoAuthenticationProvider());
|
||||||
formLogin ->
|
http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()));
|
||||||
formLogin
|
http.logout(
|
||||||
.loginPage("/login")
|
logout ->
|
||||||
.successHandler(
|
logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
||||||
new CustomAuthenticationSuccessHandler(
|
.logoutSuccessHandler(
|
||||||
loginAttemptService, userService))
|
new CustomLogoutSuccessHandler(applicationProperties))
|
||||||
.defaultSuccessUrl("/")
|
.clearAuthentication(true)
|
||||||
.failureHandler(
|
.invalidateHttpSession(true) // Invalidate session
|
||||||
new CustomAuthenticationFailureHandler(
|
.deleteCookies("JSESSIONID", "remember-me"));
|
||||||
loginAttemptService, userService))
|
http.rememberMe(
|
||||||
.permitAll())
|
rememberMeConfigurer ->
|
||||||
.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()))
|
rememberMeConfigurer // Use the configurator directly
|
||||||
.logout(
|
.key("uniqueAndSecret")
|
||||||
logout ->
|
.tokenRepository(persistentTokenRepository())
|
||||||
logout.logoutRequestMatcher(
|
.tokenValiditySeconds(1209600) // 2 weeks
|
||||||
new AntPathRequestMatcher("/logout"))
|
);
|
||||||
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
|
http.authorizeHttpRequests(
|
||||||
.invalidateHttpSession(true) // Invalidate session
|
authz ->
|
||||||
.deleteCookies("JSESSIONID", "remember-me"))
|
authz.requestMatchers(
|
||||||
.rememberMe(
|
req -> {
|
||||||
rememberMeConfigurer ->
|
String uri = req.getRequestURI();
|
||||||
rememberMeConfigurer // Use the configurator directly
|
String contextPath = req.getContextPath();
|
||||||
.key("uniqueAndSecret")
|
|
||||||
.tokenRepository(persistentTokenRepository())
|
|
||||||
.tokenValiditySeconds(1209600) // 2 weeks
|
|
||||||
)
|
|
||||||
.authorizeHttpRequests(
|
|
||||||
authz ->
|
|
||||||
authz.requestMatchers(
|
|
||||||
req -> {
|
|
||||||
String uri = req.getRequestURI();
|
|
||||||
String contextPath = req.getContextPath();
|
|
||||||
|
|
||||||
// Remove the context path from the URI
|
// Remove the context path from the URI
|
||||||
String trimmedUri =
|
String trimmedUri =
|
||||||
uri.startsWith(contextPath)
|
uri.startsWith(contextPath)
|
||||||
? uri.substring(
|
? uri.substring(
|
||||||
contextPath
|
contextPath.length())
|
||||||
.length())
|
: uri;
|
||||||
: uri;
|
|
||||||
|
|
||||||
return trimmedUri.startsWith("/login")
|
return trimmedUri.startsWith("/login")
|
||||||
|| trimmedUri.startsWith("/oauth")
|
|| trimmedUri.startsWith("/oauth")
|
||||||
|| trimmedUri.startsWith("/saml2")
|
|| trimmedUri.startsWith("/saml2")
|
||||||
|| trimmedUri.endsWith(".svg")
|
|| trimmedUri.endsWith(".svg")
|
||||||
|| trimmedUri.startsWith(
|
|| trimmedUri.startsWith("/register")
|
||||||
"/register")
|
|| trimmedUri.startsWith("/error")
|
||||||
|| trimmedUri.startsWith("/error")
|
|| trimmedUri.startsWith("/images/")
|
||||||
|| trimmedUri.startsWith("/images/")
|
|| trimmedUri.startsWith("/public/")
|
||||||
|| trimmedUri.startsWith("/public/")
|
|| trimmedUri.startsWith("/css/")
|
||||||
|| trimmedUri.startsWith("/css/")
|
|| trimmedUri.startsWith("/fonts/")
|
||||||
|| trimmedUri.startsWith("/fonts/")
|
|| trimmedUri.startsWith("/js/")
|
||||||
|| trimmedUri.startsWith("/js/")
|
|| trimmedUri.startsWith(
|
||||||
|| trimmedUri.startsWith(
|
"/api/v1/info/status");
|
||||||
"/api/v1/info/status");
|
})
|
||||||
})
|
.permitAll()
|
||||||
.permitAll()
|
.anyRequest()
|
||||||
.anyRequest()
|
.authenticated());
|
||||||
.authenticated());
|
|
||||||
|
// Handle User/Password Logins
|
||||||
|
if (applicationProperties.getSecurity().isUserPass()) {
|
||||||
|
http.formLogin(
|
||||||
|
formLogin ->
|
||||||
|
formLogin
|
||||||
|
.loginPage("/login")
|
||||||
|
.successHandler(
|
||||||
|
new CustomAuthenticationSuccessHandler(
|
||||||
|
loginAttemptService, userService))
|
||||||
|
.failureHandler(
|
||||||
|
new CustomAuthenticationFailureHandler(
|
||||||
|
loginAttemptService, userService))
|
||||||
|
.defaultSuccessUrl("/")
|
||||||
|
.permitAll());
|
||||||
|
}
|
||||||
|
|
||||||
// Handle OAUTH2 Logins
|
// Handle OAUTH2 Logins
|
||||||
if (applicationProperties.getSecurity().getOauth2() != null
|
if (applicationProperties.getSecurity().isOauth2Activ()) {
|
||||||
&& applicationProperties.getSecurity().getOauth2().getEnabled()
|
|
||||||
&& !applicationProperties
|
|
||||||
.getSecurity()
|
|
||||||
.getLoginMethod()
|
|
||||||
.equalsIgnoreCase("normal")) {
|
|
||||||
|
|
||||||
http.oauth2Login(
|
http.oauth2Login(
|
||||||
oauth2 ->
|
oauth2 ->
|
||||||
oauth2.loginPage("/oauth2")
|
oauth2.loginPage("/oauth2")
|
||||||
/*
|
/*
|
||||||
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
|
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
|
||||||
If user exists, login proceeds as usual. If user does not exist, then it is autocreated but only if 'OAUTH2AutoCreateUser'
|
If user exists, login proceeds as usual. If user does not exist, then it is autocreated but only if 'OAUTH2AutoCreateUser'
|
||||||
is set as true, else login fails with an error message advising the same.
|
is set as true, else login fails with an error message advising the same.
|
||||||
*/
|
*/
|
||||||
|
.successHandler(
|
||||||
|
new CustomOAuth2AuthenticationSuccessHandler(
|
||||||
|
loginAttemptService,
|
||||||
|
applicationProperties,
|
||||||
|
userService))
|
||||||
|
.failureHandler(
|
||||||
|
new CustomOAuth2AuthenticationFailureHandler())
|
||||||
|
// Add existing Authorities from the database
|
||||||
|
.userInfoEndpoint(
|
||||||
|
userInfoEndpoint ->
|
||||||
|
userInfoEndpoint
|
||||||
|
.oidcUserService(
|
||||||
|
new CustomOAuth2UserService(
|
||||||
|
applicationProperties,
|
||||||
|
userService,
|
||||||
|
loginAttemptService))
|
||||||
|
.userAuthoritiesMapper(
|
||||||
|
userAuthoritiesMapper()))
|
||||||
|
.permitAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle SAML
|
||||||
|
if (applicationProperties.getSecurity().isSaml2Activ()
|
||||||
|
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
|
||||||
|
http.authenticationProvider(samlAuthenticationProvider());
|
||||||
|
http.saml2Login(
|
||||||
|
saml2 ->
|
||||||
|
saml2.loginPage("/saml2")
|
||||||
.successHandler(
|
.successHandler(
|
||||||
new CustomOAuth2AuthenticationSuccessHandler(
|
new CustomSaml2AuthenticationSuccessHandler(
|
||||||
loginAttemptService,
|
loginAttemptService,
|
||||||
applicationProperties,
|
applicationProperties,
|
||||||
userService))
|
userService))
|
||||||
.failureHandler(
|
.failureHandler(
|
||||||
new CustomOAuth2AuthenticationFailureHandler())
|
new CustomSaml2AuthenticationFailureHandler())
|
||||||
// Add existing Authorities from the database
|
.permitAll())
|
||||||
.userInfoEndpoint(
|
|
||||||
userInfoEndpoint ->
|
|
||||||
userInfoEndpoint
|
|
||||||
.oidcUserService(
|
|
||||||
new CustomOAuth2UserService(
|
|
||||||
applicationProperties,
|
|
||||||
userService,
|
|
||||||
loginAttemptService))
|
|
||||||
.userAuthoritiesMapper(
|
|
||||||
userAuthoritiesMapper)))
|
|
||||||
.logout(
|
|
||||||
logout ->
|
|
||||||
logout.logoutSuccessHandler(
|
|
||||||
new CustomOAuth2LogoutSuccessHandler(
|
|
||||||
applicationProperties)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle SAML
|
|
||||||
if (applicationProperties.getSecurity().getSaml() != null
|
|
||||||
&& applicationProperties.getSecurity().getSaml().getEnabled()
|
|
||||||
&& !applicationProperties
|
|
||||||
.getSecurity()
|
|
||||||
.getLoginMethod()
|
|
||||||
.equalsIgnoreCase("normal")) {
|
|
||||||
http.saml2Login(
|
|
||||||
saml2 -> {
|
|
||||||
saml2.loginPage("/saml2")
|
|
||||||
.relyingPartyRegistrationRepository(
|
|
||||||
relyingPartyRegistrationRepository)
|
|
||||||
.successHandler(
|
|
||||||
new CustomSAMLAuthenticationSuccessHandler(
|
|
||||||
loginAttemptService,
|
|
||||||
userService,
|
|
||||||
applicationProperties))
|
|
||||||
.failureHandler(
|
|
||||||
new CustomSAMLAuthenticationFailureHandler());
|
|
||||||
})
|
|
||||||
.addFilterBefore(
|
.addFilterBefore(
|
||||||
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
|
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
||||||
http.csrf(csrf -> csrf.disable());
|
http.csrf(csrf -> csrf.disable());
|
||||||
|
} else {
|
||||||
|
CookieCsrfTokenRepository cookieRepo =
|
||||||
|
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||||
|
CsrfTokenRequestAttributeHandler requestHandler =
|
||||||
|
new CsrfTokenRequestAttributeHandler();
|
||||||
|
requestHandler.setCsrfRequestAttributeName(null);
|
||||||
|
http.csrf(
|
||||||
|
csrf ->
|
||||||
|
csrf.csrfTokenRepository(cookieRepo)
|
||||||
|
.csrfTokenRequestHandler(requestHandler));
|
||||||
}
|
}
|
||||||
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
||||||
}
|
}
|
||||||
@@ -231,39 +280,234 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
@ConditionalOnProperty(
|
||||||
name = "security.saml.enabled",
|
name = "security.saml2.enabled",
|
||||||
havingValue = "true",
|
havingValue = "true",
|
||||||
matchIfMissing = false)
|
matchIfMissing = false)
|
||||||
public AuthenticationProvider samlAuthenticationProvider() {
|
public AuthenticationProvider samlAuthenticationProvider() {
|
||||||
OpenSaml4AuthenticationProvider authenticationProvider =
|
OpenSaml4AuthenticationProvider authenticationProvider =
|
||||||
new OpenSaml4AuthenticationProvider();
|
new OpenSaml4AuthenticationProvider();
|
||||||
authenticationProvider.setResponseAuthenticationConverter(convertResponseToAuthentication);
|
authenticationProvider.setResponseAuthenticationConverter(
|
||||||
|
new CustomSaml2ResponseAuthenticationConverter(userService));
|
||||||
return authenticationProvider;
|
return authenticationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Bean
|
// Client Registration Repository for OAUTH2 OIDC Login
|
||||||
// public AuthenticationProvider daoAuthenticationProvider() {
|
@Bean
|
||||||
// DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
@ConditionalOnProperty(
|
||||||
// provider.setUserDetailsService(userDetailsService); // UserDetailsService
|
value = "security.oauth2.enabled",
|
||||||
// provider.setPasswordEncoder(passwordEncoder()); // PasswordEncoder
|
havingValue = "true",
|
||||||
// return provider;
|
matchIfMissing = false)
|
||||||
// }
|
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||||
|
List<ClientRegistration> registrations = new ArrayList<>();
|
||||||
|
|
||||||
|
githubClientRegistration().ifPresent(registrations::add);
|
||||||
|
oidcClientRegistration().ifPresent(registrations::add);
|
||||||
|
googleClientRegistration().ifPresent(registrations::add);
|
||||||
|
keycloakClientRegistration().ifPresent(registrations::add);
|
||||||
|
|
||||||
|
if (registrations.isEmpty()) {
|
||||||
|
log.error("At least one OAuth2 provider must be configured");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new InMemoryClientRegistrationRepository(registrations);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ClientRegistration> googleClientRegistration() {
|
||||||
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
if (oauth == null || !oauth.getEnabled()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
Client client = oauth.getClient();
|
||||||
|
if (client == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
GoogleProvider google = client.getGoogle();
|
||||||
|
return google != null && google.isSettingsValid()
|
||||||
|
? Optional.of(
|
||||||
|
ClientRegistration.withRegistrationId(google.getName())
|
||||||
|
.clientId(google.getClientId())
|
||||||
|
.clientSecret(google.getClientSecret())
|
||||||
|
.scope(google.getScopes())
|
||||||
|
.authorizationUri(google.getAuthorizationuri())
|
||||||
|
.tokenUri(google.getTokenuri())
|
||||||
|
.userInfoUri(google.getUserinfouri())
|
||||||
|
.userNameAttributeName(google.getUseAsUsername())
|
||||||
|
.clientName(google.getClientName())
|
||||||
|
.redirectUri("{baseUrl}/login/oauth2/code/" + google.getName())
|
||||||
|
.authorizationGrantType(
|
||||||
|
org.springframework.security.oauth2.core
|
||||||
|
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||||
|
.build())
|
||||||
|
: Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ClientRegistration> keycloakClientRegistration() {
|
||||||
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
if (oauth == null || !oauth.getEnabled()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
Client client = oauth.getClient();
|
||||||
|
if (client == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
KeycloakProvider keycloak = client.getKeycloak();
|
||||||
|
|
||||||
|
return keycloak != null && keycloak.isSettingsValid()
|
||||||
|
? Optional.of(
|
||||||
|
ClientRegistrations.fromIssuerLocation(keycloak.getIssuer())
|
||||||
|
.registrationId(keycloak.getName())
|
||||||
|
.clientId(keycloak.getClientId())
|
||||||
|
.clientSecret(keycloak.getClientSecret())
|
||||||
|
.scope(keycloak.getScopes())
|
||||||
|
.userNameAttributeName(keycloak.getUseAsUsername())
|
||||||
|
.clientName(keycloak.getClientName())
|
||||||
|
.build())
|
||||||
|
: Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ClientRegistration> githubClientRegistration() {
|
||||||
|
|
||||||
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
if (oauth == null || !oauth.getEnabled()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
Client client = oauth.getClient();
|
||||||
|
if (client == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
GithubProvider github = client.getGithub();
|
||||||
|
return github != null && github.isSettingsValid()
|
||||||
|
? Optional.of(
|
||||||
|
ClientRegistration.withRegistrationId(github.getName())
|
||||||
|
.clientId(github.getClientId())
|
||||||
|
.clientSecret(github.getClientSecret())
|
||||||
|
.scope(github.getScopes())
|
||||||
|
.authorizationUri(github.getAuthorizationuri())
|
||||||
|
.tokenUri(github.getTokenuri())
|
||||||
|
.userInfoUri(github.getUserinfouri())
|
||||||
|
.userNameAttributeName(github.getUseAsUsername())
|
||||||
|
.clientName(github.getClientName())
|
||||||
|
.redirectUri("{baseUrl}/login/oauth2/code/" + github.getName())
|
||||||
|
.authorizationGrantType(
|
||||||
|
org.springframework.security.oauth2.core
|
||||||
|
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||||
|
.build())
|
||||||
|
: Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ClientRegistration> oidcClientRegistration() {
|
||||||
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
if (oauth == null
|
||||||
|
|| oauth.getIssuer() == null
|
||||||
|
|| oauth.getIssuer().isEmpty()
|
||||||
|
|| oauth.getClientId() == null
|
||||||
|
|| oauth.getClientId().isEmpty()
|
||||||
|
|| oauth.getClientSecret() == null
|
||||||
|
|| oauth.getClientSecret().isEmpty()
|
||||||
|
|| oauth.getScopes() == null
|
||||||
|
|| oauth.getScopes().isEmpty()
|
||||||
|
|| oauth.getUseAsUsername() == null
|
||||||
|
|| oauth.getUseAsUsername().isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Optional.of(
|
||||||
|
ClientRegistrations.fromIssuerLocation(oauth.getIssuer())
|
||||||
|
.registrationId("oidc")
|
||||||
|
.clientId(oauth.getClientId())
|
||||||
|
.clientSecret(oauth.getClientSecret())
|
||||||
|
.scope(oauth.getScopes())
|
||||||
|
.userNameAttributeName(oauth.getUseAsUsername())
|
||||||
|
.clientName("OIDC")
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
|
@ConditionalOnProperty(
|
||||||
AuthenticationManagerBuilder authenticationManagerBuilder =
|
name = "security.saml2.enabled",
|
||||||
http.getSharedObject(AuthenticationManagerBuilder.class);
|
havingValue = "true",
|
||||||
|
matchIfMissing = false)
|
||||||
|
public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exception {
|
||||||
|
|
||||||
// authenticationManagerBuilder =
|
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
|
||||||
// authenticationManagerBuilder.authenticationProvider(
|
|
||||||
// daoAuthenticationProvider()); // Benutzername/Passwort
|
|
||||||
|
|
||||||
if (applicationProperties.getSecurity().getSaml() != null
|
Resource privateKeyResource = samlConf.getPrivateKey();
|
||||||
&& applicationProperties.getSecurity().getSaml().getEnabled()) {
|
|
||||||
authenticationManagerBuilder.authenticationProvider(
|
Resource certificateResource = samlConf.getSpCert();
|
||||||
samlAuthenticationProvider()); // SAML
|
|
||||||
}
|
Saml2X509Credential signingCredential =
|
||||||
return authenticationManagerBuilder.build();
|
new Saml2X509Credential(
|
||||||
|
CertificateUtils.readPrivateKey(privateKeyResource),
|
||||||
|
CertificateUtils.readCertificate(certificateResource),
|
||||||
|
Saml2X509CredentialType.SIGNING);
|
||||||
|
|
||||||
|
X509Certificate idpCert = CertificateUtils.readCertificate(samlConf.getidpCert());
|
||||||
|
|
||||||
|
Saml2X509Credential verificationCredential = Saml2X509Credential.verification(idpCert);
|
||||||
|
|
||||||
|
RelyingPartyRegistration rp =
|
||||||
|
RelyingPartyRegistration.withRegistrationId(samlConf.getRegistrationId())
|
||||||
|
.signingX509Credentials((c) -> c.add(signingCredential))
|
||||||
|
.assertingPartyDetails(
|
||||||
|
(details) ->
|
||||||
|
details.entityId(samlConf.getIdpIssuer())
|
||||||
|
.singleSignOnServiceLocation(
|
||||||
|
samlConf.getIdpSingleLoginUrl())
|
||||||
|
.verificationX509Credentials(
|
||||||
|
(c) -> c.add(verificationCredential))
|
||||||
|
.wantAuthnRequestsSigned(true))
|
||||||
|
.build();
|
||||||
|
return new InMemoryRelyingPartyRegistrationRepository(rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DaoAuthenticationProvider daoAuthenticationProvider() {
|
||||||
|
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||||
|
provider.setUserDetailsService(userDetailsService);
|
||||||
|
provider.setPasswordEncoder(passwordEncoder());
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This following function is to grant Authorities to the OAUTH2 user from the values stored in the database.
|
||||||
|
This is required for the internal; 'hasRole()' function to give out the correct role.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(
|
||||||
|
value = "security.oauth2.enabled",
|
||||||
|
havingValue = "true",
|
||||||
|
matchIfMissing = false)
|
||||||
|
GrantedAuthoritiesMapper userAuthoritiesMapper() {
|
||||||
|
return (authorities) -> {
|
||||||
|
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
|
||||||
|
|
||||||
|
authorities.forEach(
|
||||||
|
authority -> {
|
||||||
|
// Add existing OAUTH2 Authorities
|
||||||
|
mappedAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
|
||||||
|
|
||||||
|
// Add Authorities from database for existing user, if user is present.
|
||||||
|
if (authority instanceof OAuth2UserAuthority oauth2Auth) {
|
||||||
|
String useAsUsername =
|
||||||
|
applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getOauth2()
|
||||||
|
.getUseAsUsername();
|
||||||
|
Optional<User> userOpt =
|
||||||
|
userService.findByUsernameIgnoreCase(
|
||||||
|
(String) oauth2Auth.getAttributes().get(useAsUsername));
|
||||||
|
if (userOpt.isPresent()) {
|
||||||
|
User user = userOpt.get();
|
||||||
|
if (user != null) {
|
||||||
|
mappedAuthorities.add(
|
||||||
|
new SimpleGrantedAuthority(
|
||||||
|
userService.findRole(user).getAuthority()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mappedAuthorities;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import jakarta.servlet.FilterChain;
|
|||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
@@ -111,7 +112,9 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||||
response.getWriter()
|
response.getWriter()
|
||||||
.write(
|
.write(
|
||||||
"Authentication required. Please provide a X-API-KEY in request header.\nThis is found in Settings -> Account Settings -> API Key\nAlternatively you can disable authentication if this is unexpected");
|
"Authentication required. Please provide a X-API-KEY in request header.\n"
|
||||||
|
+ "This is found in Settings -> Account Settings -> API Key\n"
|
||||||
|
+ "Alternatively you can disable authentication if this is unexpected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,6 +127,8 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
username = ((UserDetails) principal).getUsername();
|
username = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
username = ((OAuth2User) principal).getName();
|
username = ((OAuth2User) principal).getName();
|
||||||
|
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
username = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
username = (String) principal;
|
username = (String) principal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
@@ -44,10 +45,6 @@ public class UserService implements UserServiceInterface {
|
|||||||
|
|
||||||
@Autowired DatabaseBackupInterface databaseBackupHelper;
|
@Autowired DatabaseBackupInterface databaseBackupHelper;
|
||||||
|
|
||||||
public long getTotalUserCount() {
|
|
||||||
return userRepository.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle OAUTH2 login and user auto creation.
|
// Handle OAUTH2 login and user auto creation.
|
||||||
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
|
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
|
||||||
throws IllegalArgumentException, IOException {
|
throws IllegalArgumentException, IOException {
|
||||||
@@ -338,6 +335,10 @@ public class UserService implements UserServiceInterface {
|
|||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
OAuth2User oAuth2User = (OAuth2User) principal;
|
OAuth2User oAuth2User = (OAuth2User) principal;
|
||||||
usernameP = oAuth2User.getName();
|
usernameP = oAuth2User.getName();
|
||||||
|
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
CustomSaml2AuthenticatedPrincipal saml2User =
|
||||||
|
(CustomSaml2AuthenticatedPrincipal) principal;
|
||||||
|
usernameP = saml2User.getName();
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
usernameP = (String) principal;
|
usernameP = (String) principal;
|
||||||
}
|
}
|
||||||
@@ -357,4 +358,9 @@ public class UserService implements UserServiceInterface {
|
|||||||
return principal.toString();
|
return principal.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTotalUsersCount() {
|
||||||
|
return userRepository.count();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ public class CustomOAuth2AuthenticationFailureHandler
|
|||||||
}
|
}
|
||||||
log.error("OAuth2 Authentication error: " + errorCode);
|
log.error("OAuth2 Authentication error: " + errorCode);
|
||||||
log.error("OAuth2AuthenticationException", exception);
|
log.error("OAuth2AuthenticationException", exception);
|
||||||
getRedirectStrategy()
|
getRedirectStrategy().sendRedirect(request, response, "/login?erroroauth=" + errorCode);
|
||||||
.sendRedirect(request, response, "/logout?erroroauth=" + errorCode);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.error("Unhandled authentication exception", exception);
|
log.error("Unhandled authentication exception", exception);
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ public class CustomOAuth2AuthenticationSuccessHandler
|
|||||||
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.isUserDisabled(username)) {
|
||||||
|
getRedirectStrategy()
|
||||||
|
.sendRedirect(request, response, "/logout?userIsDisabled=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (userService.usernameExistsIgnoreCase(username)
|
if (userService.usernameExistsIgnoreCase(username)
|
||||||
&& userService.hasPassword(username)
|
&& userService.hasPassword(username)
|
||||||
&& !userService.isAuthenticationTypeByUsername(
|
&& !userService.isAuthenticationTypeByUsername(
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.oauth2;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
|
||||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
|
||||||
import stirling.software.SPDF.model.Provider;
|
|
||||||
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
|
|
||||||
import stirling.software.SPDF.utils.UrlUtils;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
|
||||||
|
|
||||||
public CustomOAuth2LogoutSuccessHandler(ApplicationProperties applicationProperties) {
|
|
||||||
this.applicationProperties = applicationProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLogoutSuccess(
|
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
String param = "logout=true";
|
|
||||||
String registrationId = null;
|
|
||||||
String issuer = null;
|
|
||||||
String clientId = null;
|
|
||||||
|
|
||||||
if (authentication == null) {
|
|
||||||
if (request.getParameter("userIsDisabled") != null) {
|
|
||||||
response.sendRedirect(
|
|
||||||
request.getContextPath() + "/login?erroroauth=userIsDisabled");
|
|
||||||
} else {
|
|
||||||
super.onLogoutSuccess(request, response, authentication);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
|
|
||||||
if (authentication instanceof OAuth2AuthenticationToken) {
|
|
||||||
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
|
|
||||||
registrationId = oauthToken.getAuthorizedClientRegistrationId();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Provider provider = oauth.getClient().get(registrationId);
|
|
||||||
issuer = provider.getIssuer();
|
|
||||||
clientId = provider.getClientId();
|
|
||||||
} catch (UnsupportedProviderException e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
registrationId = oauth.getProvider() != null ? oauth.getProvider() : "";
|
|
||||||
issuer = oauth.getIssuer();
|
|
||||||
clientId = oauth.getClientId();
|
|
||||||
}
|
|
||||||
String errorMessage = "";
|
|
||||||
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
|
||||||
param = "erroroauth=oauth2AuthenticationErrorWeb";
|
|
||||||
} else if ((errorMessage = request.getParameter("error")) != null) {
|
|
||||||
param = "error=" + sanitizeInput(errorMessage);
|
|
||||||
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
|
|
||||||
param = "erroroauth=" + sanitizeInput(errorMessage);
|
|
||||||
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
|
|
||||||
param = "error=oauth2AutoCreateDisabled";
|
|
||||||
} else if (request.getParameter("oauth2_admin_blocked_user") != null) {
|
|
||||||
param = "erroroauth=oauth2_admin_blocked_user";
|
|
||||||
} else if (request.getParameter("userIsDisabled") != null) {
|
|
||||||
param = "erroroauth=userIsDisabled";
|
|
||||||
} else if (request.getParameter("badcredentials") != null) {
|
|
||||||
param = "error=badcredentials";
|
|
||||||
}
|
|
||||||
|
|
||||||
String redirect_url = UrlUtils.getOrigin(request) + "/login?" + param;
|
|
||||||
|
|
||||||
switch (registrationId.toLowerCase()) {
|
|
||||||
case "keycloak":
|
|
||||||
// Add Keycloak specific logout URL if needed
|
|
||||||
String logoutUrl =
|
|
||||||
issuer
|
|
||||||
+ "/protocol/openid-connect/logout"
|
|
||||||
+ "?client_id="
|
|
||||||
+ clientId
|
|
||||||
+ "&post_logout_redirect_uri="
|
|
||||||
+ response.encodeRedirectURL(redirect_url);
|
|
||||||
log.info("Redirecting to Keycloak logout URL: " + logoutUrl);
|
|
||||||
response.sendRedirect(logoutUrl);
|
|
||||||
break;
|
|
||||||
case "github":
|
|
||||||
// Add GitHub specific logout URL if needed
|
|
||||||
String githubLogoutUrl = "https://github.com/logout";
|
|
||||||
log.info("Redirecting to GitHub logout URL: " + githubLogoutUrl);
|
|
||||||
response.sendRedirect(githubLogoutUrl);
|
|
||||||
break;
|
|
||||||
case "google":
|
|
||||||
// Add Google specific logout URL if needed
|
|
||||||
// String googleLogoutUrl =
|
|
||||||
// "https://accounts.google.com/Logout?continue=https://appengine.google.com/_ah/logout?continue="
|
|
||||||
// + response.encodeRedirectURL(redirect_url);
|
|
||||||
log.info("Google does not have a specific logout URL");
|
|
||||||
// log.info("Redirecting to Google logout URL: " + googleLogoutUrl);
|
|
||||||
// response.sendRedirect(googleLogoutUrl);
|
|
||||||
// break;
|
|
||||||
default:
|
|
||||||
String defaultRedirectUrl = request.getContextPath() + "/login?" + param;
|
|
||||||
log.info("Redirecting to default logout URL: " + defaultRedirectUrl);
|
|
||||||
response.sendRedirect(defaultRedirectUrl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String sanitizeInput(String input) {
|
|
||||||
return input.replaceAll("[^a-zA-Z0-9 ]", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class ConvertResponseToAuthentication
|
|
||||||
implements Converter<ResponseToken, Saml2Authentication> {
|
|
||||||
|
|
||||||
private final Saml2AuthorityAttributeLookup saml2AuthorityAttributeLookup;
|
|
||||||
|
|
||||||
public ConvertResponseToAuthentication(
|
|
||||||
Saml2AuthorityAttributeLookup saml2AuthorityAttributeLookup) {
|
|
||||||
this.saml2AuthorityAttributeLookup = saml2AuthorityAttributeLookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Saml2Authentication convert(ResponseToken responseToken) {
|
|
||||||
final Assertion assertion =
|
|
||||||
CollectionUtils.firstElement(responseToken.getResponse().getAssertions());
|
|
||||||
final Map<String, List<Object>> attributes =
|
|
||||||
SamlAssertionUtils.getAssertionAttributes(assertion);
|
|
||||||
final String registrationId =
|
|
||||||
responseToken.getToken().getRelyingPartyRegistration().getRegistrationId();
|
|
||||||
final ScimSaml2AuthenticatedPrincipal principal =
|
|
||||||
new ScimSaml2AuthenticatedPrincipal(
|
|
||||||
assertion,
|
|
||||||
attributes,
|
|
||||||
saml2AuthorityAttributeLookup.getIdentityMappings(registrationId));
|
|
||||||
final Collection<? extends GrantedAuthority> assertionAuthorities =
|
|
||||||
getAssertionAuthorities(
|
|
||||||
attributes,
|
|
||||||
saml2AuthorityAttributeLookup.getAuthorityAttribute(registrationId));
|
|
||||||
return new Saml2Authentication(
|
|
||||||
principal, responseToken.getToken().getSaml2Response(), assertionAuthorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Collection<? extends GrantedAuthority> getAssertionAuthorities(
|
|
||||||
final Map<String, List<Object>> attributes, final String authoritiesAttributeName) {
|
|
||||||
if (attributes == null || attributes.isEmpty()) {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<Object> groups = new ArrayList<>(attributes.get(authoritiesAttributeName));
|
|
||||||
return groups.stream()
|
|
||||||
.filter(String.class::isInstance)
|
|
||||||
.map(String.class::cast)
|
|
||||||
.map(String::toLowerCase)
|
|
||||||
.map(SimpleGrantedAuthority::new)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
|
||||||
import org.springframework.security.authentication.DisabledException;
|
|
||||||
import org.springframework.security.authentication.LockedException;
|
|
||||||
import org.springframework.security.core.AuthenticationException;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
|
||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class CustomSAMLAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationFailure(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
AuthenticationException exception)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
if (exception instanceof BadCredentialsException) {
|
|
||||||
log.error("BadCredentialsException", exception);
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?error=badcredentials");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (exception instanceof DisabledException) {
|
|
||||||
log.error("User is deactivated: ", exception);
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/logout?userIsDisabled=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (exception instanceof LockedException) {
|
|
||||||
log.error("Account locked: ", exception);
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/logout?error=locked");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (exception instanceof Saml2AuthenticationException) {
|
|
||||||
log.error("SAML2 Authentication error: ", exception);
|
|
||||||
getRedirectStrategy()
|
|
||||||
.sendRedirect(request, response, "/logout?error=saml2AuthenticationError");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.error("Unhandled authentication exception", exception);
|
|
||||||
super.onAuthenticationFailure(request, response, exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.LockedException;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
|
||||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
|
||||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import jakarta.servlet.http.HttpSession;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.config.security.LoginAttemptService;
|
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
|
||||||
import stirling.software.SPDF.utils.RequestUriUtils;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class CustomSAMLAuthenticationSuccessHandler
|
|
||||||
extends SavedRequestAwareAuthenticationSuccessHandler {
|
|
||||||
|
|
||||||
private LoginAttemptService loginAttemptService;
|
|
||||||
private UserService userService;
|
|
||||||
private ApplicationProperties applicationProperties;
|
|
||||||
|
|
||||||
public CustomSAMLAuthenticationSuccessHandler(
|
|
||||||
LoginAttemptService loginAttemptService,
|
|
||||||
UserService userService,
|
|
||||||
ApplicationProperties applicationProperties) {
|
|
||||||
this.loginAttemptService = loginAttemptService;
|
|
||||||
this.userService = userService;
|
|
||||||
this.applicationProperties = applicationProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationSuccess(
|
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
|
||||||
throws ServletException, IOException {
|
|
||||||
|
|
||||||
Object principal = authentication.getPrincipal();
|
|
||||||
String username = "";
|
|
||||||
|
|
||||||
if (principal instanceof OAuth2User) {
|
|
||||||
OAuth2User oauthUser = (OAuth2User) principal;
|
|
||||||
username = oauthUser.getName();
|
|
||||||
} else if (principal instanceof UserDetails) {
|
|
||||||
UserDetails oauthUser = (UserDetails) principal;
|
|
||||||
username = oauthUser.getUsername();
|
|
||||||
} else if (principal instanceof ScimSaml2AuthenticatedPrincipal) {
|
|
||||||
ScimSaml2AuthenticatedPrincipal samlPrincipal =
|
|
||||||
(ScimSaml2AuthenticatedPrincipal) principal;
|
|
||||||
username = samlPrincipal.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the saved request
|
|
||||||
HttpSession session = request.getSession(false);
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
SavedRequest savedRequest =
|
|
||||||
(session != null)
|
|
||||||
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (savedRequest != null
|
|
||||||
&& !RequestUriUtils.isStaticResource(contextPath, savedRequest.getRedirectUrl())) {
|
|
||||||
// Redirect to the original destination
|
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
|
||||||
} else {
|
|
||||||
OAUTH2 oAuth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
|
|
||||||
if (loginAttemptService.isBlocked(username)) {
|
|
||||||
if (session != null) {
|
|
||||||
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
|
||||||
}
|
|
||||||
throw new LockedException(
|
|
||||||
"Your account has been locked due to too many failed login attempts.");
|
|
||||||
}
|
|
||||||
if (userService.usernameExistsIgnoreCase(username)
|
|
||||||
&& userService.hasPassword(username)
|
|
||||||
&& !userService.isAuthenticationTypeByUsername(
|
|
||||||
username, AuthenticationType.OAUTH2)
|
|
||||||
&& oAuth.getAutoCreateUser()) {
|
|
||||||
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (oAuth.getBlockRegistration()
|
|
||||||
&& !userService.usernameExistsIgnoreCase(username)) {
|
|
||||||
response.sendRedirect(contextPath + "/logout?oauth2_admin_blocked_user=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (principal instanceof OAuth2User) {
|
|
||||||
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
|
|
||||||
}
|
|
||||||
response.sendRedirect(contextPath + "/");
|
|
||||||
return;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class SAMLLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLogoutSuccess(
|
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
String redirectUrl = determineTargetUrl(request, response, authentication);
|
|
||||||
|
|
||||||
if (response.isCommitted()) {
|
|
||||||
log.debug("Response has already been committed. Unable to redirect to " + redirectUrl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, redirectUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String determineTargetUrl(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
Authentication authentication) {
|
|
||||||
// Default to the root URL
|
|
||||||
return "/";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
public interface Saml2AuthorityAttributeLookup {
|
|
||||||
String getAuthorityAttribute(String registrationId);
|
|
||||||
|
|
||||||
SimpleScimMappings getIdentityMappings(String registrationId);
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class Saml2AuthorityAttributeLookupImpl implements Saml2AuthorityAttributeLookup {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAuthorityAttribute(String registrationId) {
|
|
||||||
return "authorityAttributeName";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SimpleScimMappings getIdentityMappings(String registrationId) {
|
|
||||||
return new SimpleScimMappings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.opensaml.core.xml.XMLObject;
|
|
||||||
import org.opensaml.core.xml.schema.*;
|
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
|
||||||
|
|
||||||
public class SamlAssertionUtils {
|
|
||||||
|
|
||||||
public static Map<String, List<Object>> getAssertionAttributes(Assertion assertion) {
|
|
||||||
Map<String, List<Object>> attributeMap = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
assertion
|
|
||||||
.getAttributeStatements()
|
|
||||||
.forEach(
|
|
||||||
attributeStatement -> {
|
|
||||||
attributeStatement
|
|
||||||
.getAttributes()
|
|
||||||
.forEach(
|
|
||||||
attribute -> {
|
|
||||||
List<Object> attributeValues = new ArrayList<>();
|
|
||||||
|
|
||||||
attribute
|
|
||||||
.getAttributeValues()
|
|
||||||
.forEach(
|
|
||||||
xmlObject -> {
|
|
||||||
Object attributeValue =
|
|
||||||
getXmlObjectValue(
|
|
||||||
xmlObject);
|
|
||||||
if (attributeValue != null) {
|
|
||||||
attributeValues.add(
|
|
||||||
attributeValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
attributeMap.put(
|
|
||||||
attribute.getName(), attributeValues);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return attributeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object getXmlObjectValue(XMLObject xmlObject) {
|
|
||||||
if (xmlObject instanceof XSAny) {
|
|
||||||
return ((XSAny) xmlObject).getTextContent();
|
|
||||||
} else if (xmlObject instanceof XSString) {
|
|
||||||
return ((XSString) xmlObject).getValue();
|
|
||||||
} else if (xmlObject instanceof XSInteger) {
|
|
||||||
return ((XSInteger) xmlObject).getValue();
|
|
||||||
} else if (xmlObject instanceof XSURI) {
|
|
||||||
return ((XSURI) xmlObject).getURI();
|
|
||||||
} else if (xmlObject instanceof XSBoolean) {
|
|
||||||
return ((XSBoolean) xmlObject).getValue().getValue();
|
|
||||||
} else if (xmlObject instanceof XSDateTime) {
|
|
||||||
Instant dateTime = ((XSDateTime) xmlObject).getValue();
|
|
||||||
return (dateTime != null) ? Instant.ofEpochMilli(dateTime.toEpochMilli()) : null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
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.RelyingPartyRegistrationRepository;
|
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@Slf4j
|
|
||||||
public class SamlConfig {
|
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnProperty(
|
|
||||||
value = "security.saml.enabled",
|
|
||||||
havingValue = "true",
|
|
||||||
matchIfMissing = false)
|
|
||||||
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository()
|
|
||||||
throws CertificateException {
|
|
||||||
RelyingPartyRegistration registration =
|
|
||||||
RelyingPartyRegistrations.fromMetadataLocation(
|
|
||||||
applicationProperties
|
|
||||||
.getSecurity()
|
|
||||||
.getSaml()
|
|
||||||
.getIdpMetadataLocation())
|
|
||||||
.entityId(applicationProperties.getSecurity().getSaml().getEntityId())
|
|
||||||
.registrationId(
|
|
||||||
applicationProperties.getSecurity().getSaml().getRegistrationId())
|
|
||||||
.build();
|
|
||||||
return new InMemoryRelyingPartyRegistrationRepository(registration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
|
||||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.unboundid.scim2.common.types.Email;
|
|
||||||
import com.unboundid.scim2.common.types.Name;
|
|
||||||
import com.unboundid.scim2.common.types.UserResource;
|
|
||||||
|
|
||||||
public class ScimSaml2AuthenticatedPrincipal implements AuthenticatedPrincipal, Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private final transient UserResource userResource;
|
|
||||||
|
|
||||||
public ScimSaml2AuthenticatedPrincipal(
|
|
||||||
final Assertion assertion,
|
|
||||||
final Map<String, List<Object>> attributes,
|
|
||||||
final SimpleScimMappings attributeMappings) {
|
|
||||||
Assert.notNull(assertion, "assertion cannot be null");
|
|
||||||
Assert.notNull(assertion.getSubject(), "assertion subject cannot be null");
|
|
||||||
Assert.notNull(
|
|
||||||
assertion.getSubject().getNameID(), "assertion subject NameID cannot be null");
|
|
||||||
Assert.notNull(attributes, "attributes cannot be null");
|
|
||||||
Assert.notNull(attributeMappings, "attributeMappings cannot be null");
|
|
||||||
|
|
||||||
final Name name =
|
|
||||||
new Name()
|
|
||||||
.setFamilyName(
|
|
||||||
getAttribute(
|
|
||||||
attributes,
|
|
||||||
attributeMappings,
|
|
||||||
SimpleScimMappings::getFamilyName))
|
|
||||||
.setGivenName(
|
|
||||||
getAttribute(
|
|
||||||
attributes,
|
|
||||||
attributeMappings,
|
|
||||||
SimpleScimMappings::getGivenName));
|
|
||||||
|
|
||||||
final List<Email> emails = new ArrayList<>(1);
|
|
||||||
emails.add(
|
|
||||||
new Email()
|
|
||||||
.setValue(
|
|
||||||
getAttribute(
|
|
||||||
attributes,
|
|
||||||
attributeMappings,
|
|
||||||
SimpleScimMappings::getEmail))
|
|
||||||
.setPrimary(true));
|
|
||||||
|
|
||||||
userResource =
|
|
||||||
new UserResource()
|
|
||||||
.setUserName(assertion.getSubject().getNameID().getValue())
|
|
||||||
.setName(name)
|
|
||||||
.setEmails(emails);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getAttribute(
|
|
||||||
final Map<String, List<Object>> attributes,
|
|
||||||
final SimpleScimMappings simpleScimMappings,
|
|
||||||
final Function<SimpleScimMappings, String> attributeMapper) {
|
|
||||||
|
|
||||||
final String key = attributeMapper.apply(simpleScimMappings);
|
|
||||||
|
|
||||||
final List<Object> values = attributes.getOrDefault(key, Collections.emptyList());
|
|
||||||
|
|
||||||
return values.stream()
|
|
||||||
.filter(String.class::isInstance)
|
|
||||||
.map(String.class::cast)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.userResource.getUserName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserResource getUserResource() {
|
|
||||||
return this.userResource;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class SimpleScimMappings {
|
|
||||||
String givenName;
|
|
||||||
String familyName;
|
|
||||||
String email;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml2;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
|
||||||
|
import org.bouncycastle.util.io.pem.PemObject;
|
||||||
|
import org.bouncycastle.util.io.pem.PemReader;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
public class CertificateUtils {
|
||||||
|
|
||||||
|
public static X509Certificate readCertificate(Resource certificateResource) throws Exception {
|
||||||
|
try (PemReader pemReader =
|
||||||
|
new PemReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
certificateResource.getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
|
PemObject pemObject = pemReader.readPemObject();
|
||||||
|
byte[] decodedCert = pemObject.getContent();
|
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
|
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception {
|
||||||
|
try (PemReader pemReader =
|
||||||
|
new PemReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
privateKeyResource.getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
|
PemObject pemObject = pemReader.readPemObject();
|
||||||
|
byte[] decodedKey = pemObject.getContent();
|
||||||
|
return (RSAPrivateKey)
|
||||||
|
KeyFactory.getInstance("RSA")
|
||||||
|
.generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml2;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||||
|
|
||||||
|
public class CustomSaml2AuthenticatedPrincipal
|
||||||
|
implements Saml2AuthenticatedPrincipal, Serializable {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Map<String, List<Object>> attributes;
|
||||||
|
private final String nameId;
|
||||||
|
private final List<String> sessionIndexes;
|
||||||
|
|
||||||
|
public CustomSaml2AuthenticatedPrincipal(
|
||||||
|
String name,
|
||||||
|
Map<String, List<Object>> attributes,
|
||||||
|
String nameId,
|
||||||
|
List<String> sessionIndexes) {
|
||||||
|
this.name = name;
|
||||||
|
this.attributes = attributes;
|
||||||
|
this.nameId = nameId;
|
||||||
|
this.sessionIndexes = sessionIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, List<Object>> getAttributes() {
|
||||||
|
return this.attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNameId() {
|
||||||
|
return this.nameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getSessionIndexes() {
|
||||||
|
return this.sessionIndexes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.ProviderNotFoundException;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.saml2.core.Saml2Error;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||||
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationFailure(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
AuthenticationException exception)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
if (exception instanceof Saml2AuthenticationException) {
|
||||||
|
Saml2Error error = ((Saml2AuthenticationException) exception).getSaml2Error();
|
||||||
|
getRedirectStrategy()
|
||||||
|
.sendRedirect(request, response, "/login?erroroauth=" + error.getErrorCode());
|
||||||
|
} else if (exception instanceof ProviderNotFoundException) {
|
||||||
|
getRedirectStrategy()
|
||||||
|
.sendRedirect(
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
"/login?erroroauth=not_authentication_provider_found");
|
||||||
|
}
|
||||||
|
log.error("AuthenticationException: " + exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||||
|
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import stirling.software.SPDF.config.security.LoginAttemptService;
|
||||||
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
||||||
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
|
import stirling.software.SPDF.utils.RequestUriUtils;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CustomSaml2AuthenticationSuccessHandler
|
||||||
|
extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||||
|
|
||||||
|
private LoginAttemptService loginAttemptService;
|
||||||
|
|
||||||
|
private ApplicationProperties applicationProperties;
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSuccess(
|
||||||
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
|
||||||
|
Object principal = authentication.getPrincipal();
|
||||||
|
|
||||||
|
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
String username = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
||||||
|
// Get the saved request
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
String contextPath = request.getContextPath();
|
||||||
|
SavedRequest savedRequest =
|
||||||
|
(session != null)
|
||||||
|
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (savedRequest != null
|
||||||
|
&& !RequestUriUtils.isStaticResource(
|
||||||
|
contextPath, savedRequest.getRedirectUrl())) {
|
||||||
|
// Redirect to the original destination
|
||||||
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
|
} else {
|
||||||
|
SAML2 saml2 = applicationProperties.getSecurity().getSaml2();
|
||||||
|
|
||||||
|
if (loginAttemptService.isBlocked(username)) {
|
||||||
|
if (session != null) {
|
||||||
|
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
||||||
|
}
|
||||||
|
throw new LockedException(
|
||||||
|
"Your account has been locked due to too many failed login attempts.");
|
||||||
|
}
|
||||||
|
if (userService.usernameExistsIgnoreCase(username)
|
||||||
|
&& userService.hasPassword(username)
|
||||||
|
&& !userService.isAuthenticationTypeByUsername(
|
||||||
|
username, AuthenticationType.OAUTH2)
|
||||||
|
&& saml2.getAutoCreateUser()) {
|
||||||
|
response.sendRedirect(
|
||||||
|
contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (saml2.getBlockRegistration()
|
||||||
|
&& !userService.usernameExistsIgnoreCase(username)) {
|
||||||
|
response.sendRedirect(
|
||||||
|
contextPath + "/login?erroroauth=oauth2_admin_blocked_user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
userService.processOAuth2PostLogin(username, saml2.getAutoCreateUser());
|
||||||
|
response.sendRedirect(contextPath + "/");
|
||||||
|
return;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml2;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
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.Attribute;
|
||||||
|
import org.opensaml.saml.saml2.core.AttributeStatement;
|
||||||
|
import org.opensaml.saml.saml2.core.AuthnStatement;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
|
import stirling.software.SPDF.model.User;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class CustomSaml2ResponseAuthenticationConverter
|
||||||
|
implements Converter<ResponseToken, Saml2Authentication> {
|
||||||
|
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
public CustomSaml2ResponseAuthenticationConverter(UserService userService) {
|
||||||
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Saml2Authentication convert(ResponseToken responseToken) {
|
||||||
|
// Extract the assertion from the response
|
||||||
|
Assertion assertion = responseToken.getResponse().getAssertions().get(0);
|
||||||
|
|
||||||
|
// Extract the NameID
|
||||||
|
String nameId = assertion.getSubject().getNameID().getValue();
|
||||||
|
|
||||||
|
Optional<User> userOpt = userService.findByUsernameIgnoreCase(nameId);
|
||||||
|
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
|
||||||
|
if (userOpt.isPresent()) {
|
||||||
|
User user = userOpt.get();
|
||||||
|
if (user != null) {
|
||||||
|
simpleGrantedAuthority =
|
||||||
|
new SimpleGrantedAuthority(userService.findRole(user).getAuthority());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the SessionIndexes
|
||||||
|
List<String> sessionIndexes = new ArrayList<>();
|
||||||
|
for (AuthnStatement authnStatement : assertion.getAuthnStatements()) {
|
||||||
|
sessionIndexes.add(authnStatement.getSessionIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the Attributes
|
||||||
|
Map<String, List<Object>> attributes = extractAttributes(assertion);
|
||||||
|
|
||||||
|
// Create the custom principal
|
||||||
|
CustomSaml2AuthenticatedPrincipal principal =
|
||||||
|
new CustomSaml2AuthenticatedPrincipal(nameId, attributes, nameId, sessionIndexes);
|
||||||
|
|
||||||
|
// Create the Saml2Authentication
|
||||||
|
return new Saml2Authentication(
|
||||||
|
principal,
|
||||||
|
responseToken.getToken().getSaml2Response(),
|
||||||
|
Collections.singletonList(simpleGrantedAuthority));
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
log.info("BOOL: " + ((XSBoolean) xmlObject).getValue());
|
||||||
|
values.add(((XSString) xmlObject).getValue());
|
||||||
|
}
|
||||||
|
attributes.put(attributeName, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
import stirling.software.SPDF.model.SessionEntity;
|
import stirling.software.SPDF.model.SessionEntity;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -50,6 +51,8 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
principalName = ((UserDetails) principal).getUsername();
|
principalName = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
principalName = ((OAuth2User) principal).getName();
|
principalName = ((OAuth2User) principal).getName();
|
||||||
|
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
principalName = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
principalName = (String) principal;
|
principalName = (String) principal;
|
||||||
}
|
}
|
||||||
@@ -79,6 +82,8 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
principalName = ((UserDetails) principal).getUsername();
|
principalName = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
principalName = ((OAuth2User) principal).getName();
|
principalName = ((OAuth2User) principal).getName();
|
||||||
|
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
principalName = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
principalName = (String) principal;
|
principalName = (String) principal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class SettingsController {
|
|||||||
}
|
}
|
||||||
GeneralUtils.saveKeyToConfig("system.enableAnalytics", String.valueOf(enabled), false);
|
GeneralUtils.saveKeyToConfig("system.enableAnalytics", String.valueOf(enabled), false);
|
||||||
applicationProperties.getSystem().setEnableAnalytics(String.valueOf(enabled));
|
applicationProperties.getSystem().setEnableAnalytics(String.valueOf(enabled));
|
||||||
|
|
||||||
return ResponseEntity.ok("Updated");
|
return ResponseEntity.ok("Updated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
import stirling.software.SPDF.model.Role;
|
import stirling.software.SPDF.model.Role;
|
||||||
@@ -336,6 +337,8 @@ public class UserController {
|
|||||||
userNameP = ((UserDetails) principal).getUsername();
|
userNameP = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
userNameP = ((OAuth2User) principal).getName();
|
userNameP = ((OAuth2User) principal).getName();
|
||||||
|
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
userNameP = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
userNameP = (String) principal;
|
userNameP = (String) principal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ public interface UserServiceInterface {
|
|||||||
String getApiKeyForUser(String username);
|
String getApiKeyForUser(String username);
|
||||||
|
|
||||||
String getCurrentUsername();
|
String getCurrentUsername();
|
||||||
|
|
||||||
|
long getTotalUsersCount();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
@@ -14,12 +17,38 @@ import java.security.UnrecoverableKeyException;
|
|||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.pdfbox.examples.signature.CreateSignatureBase;
|
import org.apache.pdfbox.examples.signature.CreateSignatureBase;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDResources;
|
||||||
|
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||||
|
import org.apache.pdfbox.pdmodel.common.PDStream;
|
||||||
|
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||||
|
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||||
|
import org.apache.pdfbox.pdmodel.font.Standard14Fonts.FontName;
|
||||||
|
import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
|
||||||
|
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||||
|
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||||
|
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||||
|
import org.apache.pdfbox.util.Matrix;
|
||||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||||
|
import org.bouncycastle.asn1.x500.RDN;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||||
|
import org.bouncycastle.asn1.x500.style.IETFUtils;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.openssl.PEMDecryptorProvider;
|
import org.bouncycastle.openssl.PEMDecryptorProvider;
|
||||||
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
||||||
@@ -35,6 +64,7 @@ import org.bouncycastle.pkcs.PKCSException;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
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;
|
||||||
@@ -62,6 +92,8 @@ public class CertSignController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CreateSignature extends CreateSignatureBase {
|
class CreateSignature extends CreateSignatureBase {
|
||||||
|
File imageFile;
|
||||||
|
|
||||||
public CreateSignature(KeyStore keystore, char[] pin)
|
public CreateSignature(KeyStore keystore, char[] pin)
|
||||||
throws KeyStoreException,
|
throws KeyStoreException,
|
||||||
UnrecoverableKeyException,
|
UnrecoverableKeyException,
|
||||||
@@ -69,6 +101,95 @@ public class CertSignController {
|
|||||||
IOException,
|
IOException,
|
||||||
CertificateException {
|
CertificateException {
|
||||||
super(keystore, pin);
|
super(keystore, pin);
|
||||||
|
ClassPathResource resource = new ClassPathResource("static/images/signature.png");
|
||||||
|
imageFile = resource.getFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream createVisibleSignature(
|
||||||
|
PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showImage)
|
||||||
|
throws IOException {
|
||||||
|
// modified from org.apache.pdfbox.examples.signature.CreateVisibleSignature2
|
||||||
|
try (PDDocument doc = new PDDocument()) {
|
||||||
|
PDPage page = new PDPage(srcDoc.getPage(pageNumber).getMediaBox());
|
||||||
|
doc.addPage(page);
|
||||||
|
PDAcroForm acroForm = new PDAcroForm(doc);
|
||||||
|
doc.getDocumentCatalog().setAcroForm(acroForm);
|
||||||
|
PDSignatureField signatureField = new PDSignatureField(acroForm);
|
||||||
|
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
|
||||||
|
List<PDField> acroFormFields = acroForm.getFields();
|
||||||
|
acroForm.setSignaturesExist(true);
|
||||||
|
acroForm.setAppendOnly(true);
|
||||||
|
acroForm.getCOSObject().setDirect(true);
|
||||||
|
acroFormFields.add(signatureField);
|
||||||
|
|
||||||
|
PDRectangle rect = new PDRectangle(0, 0, 200, 50);
|
||||||
|
|
||||||
|
widget.setRectangle(rect);
|
||||||
|
|
||||||
|
// from PDVisualSigBuilder.createHolderForm()
|
||||||
|
PDStream stream = new PDStream(doc);
|
||||||
|
PDFormXObject form = new PDFormXObject(stream);
|
||||||
|
PDResources res = new PDResources();
|
||||||
|
form.setResources(res);
|
||||||
|
form.setFormType(1);
|
||||||
|
PDRectangle bbox = new PDRectangle(rect.getWidth(), rect.getHeight());
|
||||||
|
float height = bbox.getHeight();
|
||||||
|
form.setBBox(bbox);
|
||||||
|
PDFont font = new PDType1Font(FontName.TIMES_BOLD);
|
||||||
|
|
||||||
|
// from PDVisualSigBuilder.createAppearanceDictionary()
|
||||||
|
PDAppearanceDictionary appearance = new PDAppearanceDictionary();
|
||||||
|
appearance.getCOSObject().setDirect(true);
|
||||||
|
PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
|
||||||
|
appearance.setNormalAppearance(appearanceStream);
|
||||||
|
widget.setAppearance(appearance);
|
||||||
|
|
||||||
|
try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) {
|
||||||
|
if (showImage) {
|
||||||
|
cs.saveGraphicsState();
|
||||||
|
PDExtendedGraphicsState extState = new PDExtendedGraphicsState();
|
||||||
|
extState.setBlendMode(BlendMode.MULTIPLY);
|
||||||
|
extState.setNonStrokingAlphaConstant(0.5f);
|
||||||
|
cs.setGraphicsStateParameters(extState);
|
||||||
|
cs.transform(Matrix.getScaleInstance(0.08f, 0.08f));
|
||||||
|
PDImageXObject img =
|
||||||
|
PDImageXObject.createFromFileByExtension(imageFile, doc);
|
||||||
|
cs.drawImage(img, 100, 0);
|
||||||
|
cs.restoreGraphicsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// show text
|
||||||
|
float fontSize = 10;
|
||||||
|
float leading = fontSize * 1.5f;
|
||||||
|
cs.beginText();
|
||||||
|
cs.setFont(font, fontSize);
|
||||||
|
cs.setNonStrokingColor(Color.black);
|
||||||
|
cs.newLineAtOffset(fontSize, height - leading);
|
||||||
|
cs.setLeading(leading);
|
||||||
|
|
||||||
|
X509Certificate cert = (X509Certificate) getCertificateChain()[0];
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/2914521/
|
||||||
|
X500Name x500Name = new X500Name(cert.getSubjectX500Principal().getName());
|
||||||
|
RDN cn = x500Name.getRDNs(BCStyle.CN)[0];
|
||||||
|
String name = IETFUtils.valueToString(cn.getFirst().getValue());
|
||||||
|
|
||||||
|
String date = signature.getSignDate().getTime().toString();
|
||||||
|
String reason = signature.getReason();
|
||||||
|
|
||||||
|
cs.showText("Signed by " + name);
|
||||||
|
cs.newLine();
|
||||||
|
cs.showText(date);
|
||||||
|
cs.newLine();
|
||||||
|
cs.showText(reason);
|
||||||
|
|
||||||
|
cs.endText();
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
doc.save(baos);
|
||||||
|
return new ByteArrayInputStream(baos.toByteArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +218,7 @@ public class CertSignController {
|
|||||||
String reason = request.getReason();
|
String reason = request.getReason();
|
||||||
String location = request.getLocation();
|
String location = request.getLocation();
|
||||||
String name = request.getName();
|
String name = request.getName();
|
||||||
Integer pageNumber = request.getPageNumber();
|
Integer pageNumber = request.getPageNumber() - 1;
|
||||||
|
|
||||||
if (certType == null) {
|
if (certType == null) {
|
||||||
throw new IllegalArgumentException("Cert type must be provided");
|
throw new IllegalArgumentException("Cert type must be provided");
|
||||||
@@ -126,11 +247,18 @@ public class CertSignController {
|
|||||||
throw new IllegalArgumentException("Invalid cert type: " + certType);
|
throw new IllegalArgumentException("Invalid cert type: " + certType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: page number
|
|
||||||
|
|
||||||
CreateSignature createSignature = new CreateSignature(ks, password.toCharArray());
|
CreateSignature createSignature = new CreateSignature(ks, password.toCharArray());
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
sign(pdfDocumentFactory, pdf.getBytes(), baos, createSignature, name, location, reason);
|
sign(
|
||||||
|
pdfDocumentFactory,
|
||||||
|
pdf.getBytes(),
|
||||||
|
baos,
|
||||||
|
createSignature,
|
||||||
|
showSignature,
|
||||||
|
pageNumber,
|
||||||
|
name,
|
||||||
|
location,
|
||||||
|
reason);
|
||||||
return WebResponseUtils.boasToWebResponse(
|
return WebResponseUtils.boasToWebResponse(
|
||||||
baos,
|
baos,
|
||||||
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
|
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
|
||||||
@@ -142,6 +270,8 @@ public class CertSignController {
|
|||||||
byte[] input,
|
byte[] input,
|
||||||
OutputStream output,
|
OutputStream output,
|
||||||
CreateSignature instance,
|
CreateSignature instance,
|
||||||
|
Boolean showSignature,
|
||||||
|
Integer pageNumber,
|
||||||
String name,
|
String name,
|
||||||
String location,
|
String location,
|
||||||
String reason) {
|
String reason) {
|
||||||
@@ -154,7 +284,17 @@ public class CertSignController {
|
|||||||
signature.setReason(reason);
|
signature.setReason(reason);
|
||||||
signature.setSignDate(Calendar.getInstance());
|
signature.setSignDate(Calendar.getInstance());
|
||||||
|
|
||||||
doc.addSignature(signature, instance);
|
if (showSignature) {
|
||||||
|
SignatureOptions signatureOptions = new SignatureOptions();
|
||||||
|
signatureOptions.setVisualSignature(
|
||||||
|
instance.createVisibleSignature(doc, signature, pageNumber, true));
|
||||||
|
signatureOptions.setPage(pageNumber);
|
||||||
|
|
||||||
|
doc.addSignature(signature, instance, signatureOptions);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
doc.addSignature(signature, instance);
|
||||||
|
}
|
||||||
doc.saveIncremental(output);
|
doc.saveIncremental(output);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("exception", e);
|
logger.error("exception", e);
|
||||||
|
|||||||
@@ -21,10 +21,13 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.*;
|
import stirling.software.SPDF.model.*;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
||||||
import stirling.software.SPDF.model.provider.GithubProvider;
|
import stirling.software.SPDF.model.provider.GithubProvider;
|
||||||
import stirling.software.SPDF.model.provider.GoogleProvider;
|
import stirling.software.SPDF.model.provider.GoogleProvider;
|
||||||
import stirling.software.SPDF.model.provider.KeycloakProvider;
|
import stirling.software.SPDF.model.provider.KeycloakProvider;
|
||||||
@@ -51,38 +54,54 @@ public class AccountWebController {
|
|||||||
|
|
||||||
Map<String, String> providerList = new HashMap<>();
|
Map<String, String> providerList = new HashMap<>();
|
||||||
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
Security securityProps = applicationProperties.getSecurity();
|
||||||
|
|
||||||
|
OAUTH2 oauth = securityProps.getOauth2();
|
||||||
if (oauth != null) {
|
if (oauth != null) {
|
||||||
if (oauth.isSettingsValid()) {
|
if (oauth.getEnabled()) {
|
||||||
providerList.put("oidc", oauth.getProvider());
|
if (oauth.isSettingsValid()) {
|
||||||
}
|
providerList.put("/oauth2/authorization/oidc", oauth.getProvider());
|
||||||
Client client = oauth.getClient();
|
|
||||||
if (client != null) {
|
|
||||||
GoogleProvider google = client.getGoogle();
|
|
||||||
if (google.isSettingsValid()) {
|
|
||||||
providerList.put(google.getName(), google.getClientName());
|
|
||||||
}
|
}
|
||||||
|
Client client = oauth.getClient();
|
||||||
|
if (client != null) {
|
||||||
|
GoogleProvider google = client.getGoogle();
|
||||||
|
if (google.isSettingsValid()) {
|
||||||
|
providerList.put(
|
||||||
|
"/oauth2/authorization/" + google.getName(),
|
||||||
|
google.getClientName());
|
||||||
|
}
|
||||||
|
|
||||||
GithubProvider github = client.getGithub();
|
GithubProvider github = client.getGithub();
|
||||||
if (github.isSettingsValid()) {
|
if (github.isSettingsValid()) {
|
||||||
providerList.put(github.getName(), github.getClientName());
|
providerList.put(
|
||||||
}
|
"/oauth2/authorization/" + github.getName(),
|
||||||
|
github.getClientName());
|
||||||
|
}
|
||||||
|
|
||||||
KeycloakProvider keycloak = client.getKeycloak();
|
KeycloakProvider keycloak = client.getKeycloak();
|
||||||
if (keycloak.isSettingsValid()) {
|
if (keycloak.isSettingsValid()) {
|
||||||
providerList.put(keycloak.getName(), keycloak.getClientName());
|
providerList.put(
|
||||||
|
"/oauth2/authorization/" + keycloak.getName(),
|
||||||
|
keycloak.getClientName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAML2 saml2 = securityProps.getSaml2();
|
||||||
|
if (securityProps.isSaml2Activ()
|
||||||
|
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
|
||||||
|
providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2");
|
||||||
|
}
|
||||||
// Remove any null keys/values from the providerList
|
// Remove any null keys/values from the providerList
|
||||||
providerList
|
providerList
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
|
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
|
||||||
model.addAttribute("providerlist", providerList);
|
model.addAttribute("providerlist", providerList);
|
||||||
|
|
||||||
model.addAttribute("loginMethod", applicationProperties.getSecurity().getLoginMethod());
|
model.addAttribute("loginMethod", securityProps.getLoginMethod());
|
||||||
model.addAttribute(
|
boolean altLogin = providerList.size() > 0 ? securityProps.isAltLogin() : false;
|
||||||
"oAuth2Enabled", applicationProperties.getSecurity().getOauth2().getEnabled());
|
model.addAttribute("altLogin", altLogin);
|
||||||
|
|
||||||
model.addAttribute("currentPage", "login");
|
model.addAttribute("currentPage", "login");
|
||||||
|
|
||||||
@@ -145,6 +164,17 @@ public class AccountWebController {
|
|||||||
case "userIsDisabled":
|
case "userIsDisabled":
|
||||||
erroroauth = "login.userIsDisabled";
|
erroroauth = "login.userIsDisabled";
|
||||||
break;
|
break;
|
||||||
|
case "invalid_destination":
|
||||||
|
erroroauth = "login.invalid_destination";
|
||||||
|
break;
|
||||||
|
// Valid InResponseTo was not available from the validation context, unable to
|
||||||
|
// evaluate
|
||||||
|
case "invalid_in_response_to":
|
||||||
|
erroroauth = "login.invalid_in_response_to";
|
||||||
|
break;
|
||||||
|
case "not_authentication_provider_found":
|
||||||
|
erroroauth = "login.not_authentication_provider_found";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -349,6 +379,17 @@ public class AccountWebController {
|
|||||||
// Add oAuth2 Login attributes to the model
|
// Add oAuth2 Login attributes to the model
|
||||||
model.addAttribute("oAuth2Login", true);
|
model.addAttribute("oAuth2Login", true);
|
||||||
}
|
}
|
||||||
|
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
||||||
|
// Cast the principal object to OAuth2User
|
||||||
|
CustomSaml2AuthenticatedPrincipal userDetails =
|
||||||
|
(CustomSaml2AuthenticatedPrincipal) principal;
|
||||||
|
|
||||||
|
// Retrieve username and other attributes
|
||||||
|
username = userDetails.getName();
|
||||||
|
// Add oAuth2 Login attributes to the model
|
||||||
|
model.addAttribute("oAuth2Login", true);
|
||||||
|
}
|
||||||
|
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
// Fetch user details from the database
|
// Fetch user details from the database
|
||||||
Optional<User> user =
|
Optional<User> user =
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import io.swagger.v3.oas.annotations.Hidden;
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
||||||
|
import stirling.software.SPDF.model.SignatureFile;
|
||||||
|
import stirling.software.SPDF.service.SignatureService;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@Tag(name = "General", description = "General APIs")
|
@Tag(name = "General", description = "General APIs")
|
||||||
public class GeneralWebController {
|
public class GeneralWebController {
|
||||||
@@ -171,11 +175,28 @@ public class GeneralWebController {
|
|||||||
return "split-pdfs";
|
return "split-pdfs";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String SIGNATURE_BASE_PATH = "customFiles/static/signatures/";
|
||||||
|
private static final String ALL_USERS_FOLDER = "ALL_USERS";
|
||||||
|
|
||||||
|
@Autowired private SignatureService signatureService;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private UserServiceInterface userService;
|
||||||
|
|
||||||
@GetMapping("/sign")
|
@GetMapping("/sign")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String signForm(Model model) {
|
public String signForm(Model model) {
|
||||||
|
String username = "";
|
||||||
|
if (userService != null) {
|
||||||
|
username = userService.getCurrentUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get signatures from both personal and ALL_USERS folders
|
||||||
|
List<SignatureFile> signatures = signatureService.getAvailableSignatures(username);
|
||||||
|
|
||||||
model.addAttribute("currentPage", "sign");
|
model.addAttribute("currentPage", "sign");
|
||||||
model.addAttribute("fonts", getFontNames());
|
model.addAttribute("fonts", getFontNames());
|
||||||
|
model.addAttribute("signatures", signatures);
|
||||||
return "sign";
|
return "sign";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package stirling.software.SPDF.controller.web;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
||||||
|
import stirling.software.SPDF.service.SignatureService;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/api/v1/general/")
|
||||||
|
public class SignatureController {
|
||||||
|
|
||||||
|
@Autowired private SignatureService signatureService;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private UserServiceInterface userService;
|
||||||
|
|
||||||
|
@GetMapping("/sign/{fileName}")
|
||||||
|
public ResponseEntity<byte[]> getSignature(@PathVariable(name = "fileName") String fileName)
|
||||||
|
throws IOException {
|
||||||
|
String username = "NON_SECURITY_USER";
|
||||||
|
if (userService != null) {
|
||||||
|
username = userService.getCurrentUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify access permission
|
||||||
|
if (!signatureService.hasAccessToFile(username, fileName)) {
|
||||||
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] imageBytes = signatureService.getSignatureBytes(username, fileName);
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.contentType(MediaType.IMAGE_JPEG) // Adjust based on file type
|
||||||
|
.body(imageBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
package stirling.software.SPDF.model;
|
package stirling.software.SPDF.model;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
@@ -18,6 +22,8 @@ import org.springframework.core.io.FileSystemResource;
|
|||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
||||||
import stirling.software.SPDF.model.provider.GithubProvider;
|
import stirling.software.SPDF.model.provider.GithubProvider;
|
||||||
@@ -41,7 +47,6 @@ public class ApplicationProperties {
|
|||||||
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
||||||
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
||||||
private AutoPipeline autoPipeline = new AutoPipeline();
|
private AutoPipeline autoPipeline = new AutoPipeline();
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ApplicationProperties.class);
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class AutoPipeline {
|
public static class AutoPipeline {
|
||||||
@@ -63,41 +68,108 @@ public class ApplicationProperties {
|
|||||||
private Boolean csrfDisabled;
|
private Boolean csrfDisabled;
|
||||||
private InitialLogin initialLogin = new InitialLogin();
|
private InitialLogin initialLogin = new InitialLogin();
|
||||||
private OAUTH2 oauth2 = new OAUTH2();
|
private OAUTH2 oauth2 = new OAUTH2();
|
||||||
private SAML saml = new SAML();
|
private SAML2 saml2 = new SAML2();
|
||||||
private int loginAttemptCount;
|
private int loginAttemptCount;
|
||||||
private long loginResetTimeMinutes;
|
private long loginResetTimeMinutes;
|
||||||
private String loginMethod = "all";
|
private String loginMethod = "all";
|
||||||
|
|
||||||
|
public Boolean isAltLogin() {
|
||||||
|
return saml2.getEnabled() || oauth2.getEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LoginMethods {
|
||||||
|
ALL("all"),
|
||||||
|
NORMAL("normal"),
|
||||||
|
OAUTH2("oauth2"),
|
||||||
|
SAML2("saml2");
|
||||||
|
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
LoginMethods(String method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserPass() {
|
||||||
|
return (loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString())
|
||||||
|
|| loginMethod.equalsIgnoreCase(LoginMethods.ALL.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOauth2Activ() {
|
||||||
|
return (oauth2 != null
|
||||||
|
&& oauth2.getEnabled()
|
||||||
|
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSaml2Activ() {
|
||||||
|
return (saml2 != null
|
||||||
|
&& saml2.getEnabled()
|
||||||
|
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class InitialLogin {
|
public static class InitialLogin {
|
||||||
private String username;
|
private String username;
|
||||||
@ToString.Exclude private String password;
|
@ToString.Exclude private String password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Getter
|
||||||
public static class SAML {
|
@Setter
|
||||||
|
public static class SAML2 {
|
||||||
private Boolean enabled = false;
|
private Boolean enabled = false;
|
||||||
private String entityId;
|
private Boolean autoCreateUser = false;
|
||||||
private String registrationId;
|
private Boolean blockRegistration = false;
|
||||||
private String spBaseUrl;
|
private String registrationId = "stirling";
|
||||||
private String idpMetadataLocation;
|
private String idpMetadataUri;
|
||||||
private KeyStore keystore;
|
private String idpSingleLogoutUrl;
|
||||||
|
private String idpSingleLoginUrl;
|
||||||
|
private String idpIssuer;
|
||||||
|
private String idpCert;
|
||||||
|
private String privateKey;
|
||||||
|
private String spCert;
|
||||||
|
|
||||||
@Data
|
public InputStream getIdpMetadataUri() throws IOException {
|
||||||
public static class KeyStore {
|
if (idpMetadataUri.startsWith("classpath:")) {
|
||||||
private String keystoreLocation;
|
return new ClassPathResource(idpMetadataUri.substring("classpath".length()))
|
||||||
private String keystorePassword;
|
.getInputStream();
|
||||||
private String keyAlias;
|
}
|
||||||
private String keyPassword;
|
try {
|
||||||
private String realmCertificateAlias;
|
URI uri = new URI(idpMetadataUri);
|
||||||
|
URL url = uri.toURL();
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
return connection.getInputStream();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IOException("Invalid URI format: " + idpMetadataUri, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Resource getKeystoreResource() {
|
public Resource getSpCert() {
|
||||||
if (keystoreLocation.startsWith("classpath:")) {
|
if (spCert.startsWith("classpath:")) {
|
||||||
return new ClassPathResource(
|
return new ClassPathResource(spCert.substring("classpath:".length()));
|
||||||
keystoreLocation.substring("classpath:".length()));
|
} else {
|
||||||
} else {
|
return new FileSystemResource(spCert);
|
||||||
return new FileSystemResource(keystoreLocation);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Resource getidpCert() {
|
||||||
|
if (idpCert.startsWith("classpath:")) {
|
||||||
|
return new ClassPathResource(idpCert.substring("classpath:".length()));
|
||||||
|
} else {
|
||||||
|
return new FileSystemResource(idpCert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Resource getPrivateKey() {
|
||||||
|
if (privateKey.startsWith("classpath:")) {
|
||||||
|
return new ClassPathResource(privateKey.substring("classpath:".length()));
|
||||||
|
} else {
|
||||||
|
return new FileSystemResource(privateKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ public class Provider implements ProviderInterface {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
// throw new IllegalArgumentException(getName() + ": " + name + " is required!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isValid(Collection<String> value, String name) {
|
protected boolean isValid(Collection<String> value, String name) {
|
||||||
@@ -27,66 +26,55 @@ public class Provider implements ProviderInterface {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
// throw new IllegalArgumentException(getName() + ": " + name + " is required!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getScopes() {
|
public Collection<String> getScopes() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getScope'");
|
throw new UnsupportedOperationException("Unimplemented method 'getScope'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setScopes(String scopes) {
|
public void setScopes(String scopes) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setScope'");
|
throw new UnsupportedOperationException("Unimplemented method 'setScope'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUseAsUsername() {
|
public String getUseAsUsername() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getUseAsUsername'");
|
throw new UnsupportedOperationException("Unimplemented method 'getUseAsUsername'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUseAsUsername(String useAsUsername) {
|
public void setUseAsUsername(String useAsUsername) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setUseAsUsername'");
|
throw new UnsupportedOperationException("Unimplemented method 'setUseAsUsername'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIssuer() {
|
public String getIssuer() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getIssuer'");
|
throw new UnsupportedOperationException("Unimplemented method 'getIssuer'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIssuer(String issuer) {
|
public void setIssuer(String issuer) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setIssuer'");
|
throw new UnsupportedOperationException("Unimplemented method 'setIssuer'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientSecret() {
|
public String getClientSecret() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getClientSecret'");
|
throw new UnsupportedOperationException("Unimplemented method 'getClientSecret'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setClientSecret(String clientSecret) {
|
public void setClientSecret(String clientSecret) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setClientSecret'");
|
throw new UnsupportedOperationException("Unimplemented method 'setClientSecret'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientId() {
|
public String getClientId() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getClientId'");
|
throw new UnsupportedOperationException("Unimplemented method 'getClientId'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setClientId(String clientId) {
|
public void setClientId(String clientId) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setClientId'");
|
throw new UnsupportedOperationException("Unimplemented method 'setClientId'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package stirling.software.SPDF.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class SignatureFile {
|
||||||
|
private String fileName;
|
||||||
|
private String category; // "Personal" or "Shared"
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import com.posthog.java.PostHog;
|
import com.posthog.java.PostHog;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -26,20 +27,23 @@ public class PostHogService {
|
|||||||
private final PostHog postHog;
|
private final PostHog postHog;
|
||||||
private final String uniqueId;
|
private final String uniqueId;
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
|
private final UserServiceInterface userService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PostHogService(
|
public PostHogService(
|
||||||
PostHog postHog,
|
PostHog postHog,
|
||||||
@Qualifier("UUID") String uuid,
|
@Qualifier("UUID") String uuid,
|
||||||
ApplicationProperties applicationProperties) {
|
ApplicationProperties applicationProperties,
|
||||||
|
@Autowired(required = false) UserServiceInterface userService) {
|
||||||
this.postHog = postHog;
|
this.postHog = postHog;
|
||||||
this.uniqueId = uuid;
|
this.uniqueId = uuid;
|
||||||
this.applicationProperties = applicationProperties;
|
this.applicationProperties = applicationProperties;
|
||||||
|
this.userService = userService;
|
||||||
captureSystemInfo();
|
captureSystemInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void captureSystemInfo() {
|
private void captureSystemInfo() {
|
||||||
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
if (!Boolean.parseBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -50,7 +54,7 @@ public class PostHogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void captureEvent(String eventName, Map<String, Object> properties) {
|
public void captureEvent(String eventName, Map<String, Object> properties) {
|
||||||
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
if (!Boolean.parseBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
postHog.capture(uniqueId, eventName, properties);
|
postHog.capture(uniqueId, eventName, properties);
|
||||||
@@ -134,6 +138,10 @@ public class PostHogService {
|
|||||||
}
|
}
|
||||||
metrics.put("application_properties", captureApplicationProperties());
|
metrics.put("application_properties", captureApplicationProperties());
|
||||||
|
|
||||||
|
if (userService != null) {
|
||||||
|
metrics.put("total_users_created", userService.getTotalUsersCount());
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
metrics.put("error", e.getMessage());
|
metrics.put("error", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thymeleaf.util.StringUtils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.SignatureFile;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class SignatureService {
|
||||||
|
|
||||||
|
private static final String SIGNATURE_BASE_PATH = "customFiles/signatures/";
|
||||||
|
private static final String ALL_USERS_FOLDER = "ALL_USERS";
|
||||||
|
|
||||||
|
public boolean hasAccessToFile(String username, String fileName) throws IOException {
|
||||||
|
validateFileName(fileName);
|
||||||
|
// Check if file exists in user's personal folder or ALL_USERS folder
|
||||||
|
Path userPath = Paths.get(SIGNATURE_BASE_PATH, username, fileName);
|
||||||
|
Path allUsersPath = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName);
|
||||||
|
|
||||||
|
return Files.exists(userPath) || Files.exists(allUsersPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SignatureFile> getAvailableSignatures(String username) {
|
||||||
|
List<SignatureFile> signatures = new ArrayList<>();
|
||||||
|
|
||||||
|
// Get signatures from user's personal folder
|
||||||
|
if (!StringUtils.isEmptyOrWhitespace(username)) {
|
||||||
|
Path userFolder = Paths.get(SIGNATURE_BASE_PATH, username);
|
||||||
|
if (Files.exists(userFolder)) {
|
||||||
|
try {
|
||||||
|
signatures.addAll(getSignaturesFromFolder(userFolder, "Personal"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error reading user signatures folder", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get signatures from ALL_USERS folder
|
||||||
|
Path allUsersFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER);
|
||||||
|
if (Files.exists(allUsersFolder)) {
|
||||||
|
try {
|
||||||
|
signatures.addAll(getSignaturesFromFolder(allUsersFolder, "Shared"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error reading shared signatures folder", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return signatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SignatureFile> getSignaturesFromFolder(Path folder, String category)
|
||||||
|
throws IOException {
|
||||||
|
return Files.list(folder)
|
||||||
|
.filter(path -> isImageFile(path))
|
||||||
|
.map(path -> new SignatureFile(path.getFileName().toString(), category))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSignatureBytes(String username, String fileName) throws IOException {
|
||||||
|
validateFileName(fileName);
|
||||||
|
// First try user's personal folder
|
||||||
|
Path userPath = Paths.get(SIGNATURE_BASE_PATH, username, fileName);
|
||||||
|
if (Files.exists(userPath)) {
|
||||||
|
return Files.readAllBytes(userPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then try ALL_USERS folder
|
||||||
|
Path allUsersPath = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName);
|
||||||
|
if (Files.exists(allUsersPath)) {
|
||||||
|
return Files.readAllBytes(allUsersPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException("Signature file not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isImageFile(Path path) {
|
||||||
|
String fileName = path.getFileName().toString().toLowerCase();
|
||||||
|
return fileName.endsWith(".jpg")
|
||||||
|
|| fileName.endsWith(".jpeg")
|
||||||
|
|| fileName.endsWith(".png")
|
||||||
|
|| fileName.endsWith(".gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateFileName(String fileName) {
|
||||||
|
if (fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
|
||||||
|
throw new IllegalArgumentException("Invalid filename");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,31 @@
|
|||||||
package stirling.software.SPDF.utils;
|
package stirling.software.SPDF.utils;
|
||||||
|
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.image.AffineTransformOp;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DataBuffer;
|
import java.awt.image.DataBuffer;
|
||||||
import java.awt.image.DataBufferByte;
|
import java.awt.image.DataBufferByte;
|
||||||
import java.awt.image.DataBufferInt;
|
import java.awt.image.DataBufferInt;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.drew.imaging.ImageMetadataReader;
|
||||||
|
import com.drew.imaging.ImageProcessingException;
|
||||||
|
import com.drew.metadata.Metadata;
|
||||||
|
import com.drew.metadata.MetadataException;
|
||||||
|
import com.drew.metadata.exif.ExifSubIFDDirectory;
|
||||||
|
|
||||||
public class ImageProcessingUtils {
|
public class ImageProcessingUtils {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
|
||||||
|
|
||||||
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
|
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
|
||||||
BufferedImage convertedImage;
|
BufferedImage convertedImage;
|
||||||
switch (colorType) {
|
switch (colorType) {
|
||||||
@@ -59,4 +77,51 @@ public class ImageProcessingUtils {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double extractImageOrientation(InputStream is) throws IOException {
|
||||||
|
try {
|
||||||
|
Metadata metadata = ImageMetadataReader.readMetadata(is);
|
||||||
|
ExifSubIFDDirectory directory =
|
||||||
|
metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
|
||||||
|
if (directory == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int orientationTag = directory.getInt(ExifSubIFDDirectory.TAG_ORIENTATION);
|
||||||
|
switch (orientationTag) {
|
||||||
|
case 1:
|
||||||
|
return 0;
|
||||||
|
case 6:
|
||||||
|
return 90;
|
||||||
|
case 3:
|
||||||
|
return 180;
|
||||||
|
case 8:
|
||||||
|
return 270;
|
||||||
|
default:
|
||||||
|
logger.warn("Unknown orientation tag: {}", orientationTag);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} catch (ImageProcessingException | MetadataException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BufferedImage applyOrientation(BufferedImage image, double orientation) {
|
||||||
|
if (orientation == 0) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
AffineTransform transform =
|
||||||
|
AffineTransform.getRotateInstance(
|
||||||
|
Math.toRadians(orientation),
|
||||||
|
image.getWidth() / 2.0,
|
||||||
|
image.getHeight() / 2.0);
|
||||||
|
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
|
||||||
|
return op.filter(image, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BufferedImage loadImageWithExifOrientation(MultipartFile file)
|
||||||
|
throws IOException {
|
||||||
|
BufferedImage image = ImageIO.read(file.getInputStream());
|
||||||
|
double orientation = extractImageOrientation(file.getInputStream());
|
||||||
|
return applyOrientation(image, orientation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,8 @@ public class PdfUtils {
|
|||||||
|
|
||||||
pdfDocument.close();
|
pdfDocument.close();
|
||||||
|
|
||||||
// Assumes the expectedPageSize is in the format "widthxheight", e.g. "595x842" for A4
|
// Assumes the expectedPageSize is in the format "widthxheight", e.g. "595x842"
|
||||||
|
// for A4
|
||||||
String[] dimensions = expectedPageSize.split("x");
|
String[] dimensions = expectedPageSize.split("x");
|
||||||
float expectedPageWidth = Float.parseFloat(dimensions[0]);
|
float expectedPageWidth = Float.parseFloat(dimensions[0]);
|
||||||
float expectedPageHeight = Float.parseFloat(dimensions[1]);
|
float expectedPageHeight = Float.parseFloat(dimensions[1]);
|
||||||
@@ -407,7 +408,7 @@ public class PdfUtils {
|
|||||||
addImageToDocument(doc, pdImage, fitOption, autoRotate);
|
addImageToDocument(doc, pdImage, fitOption, autoRotate);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BufferedImage image = ImageIO.read(file.getInputStream());
|
BufferedImage image = ImageProcessingUtils.loadImageWithExifOrientation(file);
|
||||||
BufferedImage convertedImage =
|
BufferedImage convertedImage =
|
||||||
ImageProcessingUtils.convertColorType(image, colorType);
|
ImageProcessingUtils.convertColorType(image, colorType);
|
||||||
// Use JPEGFactory if it's JPEG since JPEG is lossy
|
// Use JPEGFactory if it's JPEG since JPEG is lossy
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a temporary file, with the original filename from the multipart file
|
// Create a temporary file, with the original filename from the multipart file
|
||||||
File file = File.createTempFile("temp", getFileInput().getOriginalFilename());
|
File file = Files.createTempFile("temp", getFileInput().getOriginalFilename()).toFile();
|
||||||
|
|
||||||
// Transfer the content of the multipart file to the file
|
// Transfer the content of the multipart file to the file
|
||||||
getFileInput().transferTo(file);
|
getFileInput().transferTo(file);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ public class InvertFullColorStrategy extends ReplaceAndInvertColorStrategy {
|
|||||||
public InputStreamResource replace() throws IOException {
|
public InputStreamResource replace() throws IOException {
|
||||||
|
|
||||||
// Create a temporary file, with the original filename from the multipart file
|
// Create a temporary file, with the original filename from the multipart file
|
||||||
File file = File.createTempFile("temp", getFileInput().getOriginalFilename());
|
File file = Files.createTempFile("temp", getFileInput().getOriginalFilename()).toFile();
|
||||||
|
|
||||||
// Transfer the content of the multipart file to the file
|
// Transfer the content of the multipart file to the file
|
||||||
getFileInput().transferTo(file);
|
getFileInput().transferTo(file);
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=معلومات
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=تم تعطيل المستخدم، تم حظر تسجيل
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=حجب تلقائي
|
autoRedact.title=حجب تلقائي
|
||||||
@@ -783,6 +784,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=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=رسم التوقيع
|
|||||||
sign.text=إدخال النص
|
sign.text=إدخال النص
|
||||||
sign.clear=مسح
|
sign.clear=مسح
|
||||||
sign.add=إضافة
|
sign.add=إضافة
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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=Font Size
|
addPageNumbers.fontSize=Размер на шрифт
|
||||||
addPageNumbers.fontName=Font Name
|
addPageNumbers.fontName=Име на шрифт
|
||||||
pdfPrompt=Изберете PDF(и)
|
pdfPrompt=Изберете PDF(и)
|
||||||
multiPdfPrompt=Изберете PDF (2+)
|
multiPdfPrompt=Изберете PDF (2+)
|
||||||
multiPdfDropPrompt=Изберете (или плъзнете и пуснете) всички PDF файлове, от които се нуждаете
|
multiPdfDropPrompt=Изберете (или плъзнете и пуснете) всички PDF файлове, от които се нуждаете
|
||||||
@@ -56,12 +56,12 @@ userNotFoundMessage=Потребителят не е намерен
|
|||||||
incorrectPasswordMessage=Текущата парола е неправилна.
|
incorrectPasswordMessage=Текущата парола е неправилна.
|
||||||
usernameExistsMessage=Новият потребител вече съществува.
|
usernameExistsMessage=Новият потребител вече съществува.
|
||||||
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
|
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
|
||||||
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
invalidPasswordMessage=Паролата не трябва да е празна и не трябва да има интервали в началото или в края.
|
||||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
confirmPasswordErrorMessage=Нова парола и Потвърждаване на новата парола трябва да съвпадат.
|
||||||
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
|
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
|
||||||
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
||||||
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
||||||
disabledCurrentUserMessage=The current user cannot be disabled
|
disabledCurrentUserMessage=Текущият потребител не може да бъде деактивиран
|
||||||
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
|
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
|
||||||
userAlreadyExistsOAuthMessage=Потребителят вече съществува като OAuth2 потребител.
|
userAlreadyExistsOAuthMessage=Потребителят вече съществува като OAuth2 потребител.
|
||||||
userAlreadyExistsWebMessage=Потребителят вече съществува като уеб-потребител.
|
userAlreadyExistsWebMessage=Потребителят вече съществува като уеб-потребител.
|
||||||
@@ -75,16 +75,18 @@ visitGithub=Посетете Github Repository
|
|||||||
donate=Направете дарение
|
donate=Направете дарение
|
||||||
color=Цвят
|
color=Цвят
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Info
|
info=Информация
|
||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Страница
|
||||||
pages=Pages
|
pages=Страници
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Политика за поверителност
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Правила и условия
|
||||||
legal.accessibility=Accessibility
|
legal.accessibility=Достъпност
|
||||||
legal.cookie=Cookie Policy
|
legal.cookie=Политика за бисквитки
|
||||||
legal.impressum=Impressum
|
legal.impressum=Отпечатък
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -96,7 +98,7 @@ pipeline.defaultOption=Персонализиран
|
|||||||
pipeline.submitButton=Подайте
|
pipeline.submitButton=Подайте
|
||||||
pipeline.help=Pipeline Помощ
|
pipeline.help=Pipeline Помощ
|
||||||
pipeline.scanHelp=Помощ за сканиране на папки
|
pipeline.scanHelp=Помощ за сканиране на папки
|
||||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
pipeline.deletePrompt=Сигурни ли сте, че искате да изтриете pipeline
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
@@ -114,21 +116,21 @@ pipelineOptions.validateButton=Валидирай
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Направете надстройка до Pro версията
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Тази функция е достъпна само за потребители на Pro версията.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro поддържа YAML конфигурационни файлове и други SSO функции.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Търсите повече функции за управление на потребителите? Погледнете за Stirling PDF Pro
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=Искате ли да подобрите 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.paragraph1=Stirling PDF включва анализи, за да ни помогне да подобрим продукта. Ние не проследяваме лична информация или съдържание на файлове.
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Моля, обмислете възможността за анализ, за да помогнете на Stirling-PDF да расте и да ни позволи да разберем по-добре нашите потребители.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Активиране на анализа
|
||||||
analytics.disable=Disable analytics
|
analytics.disable=Деактивиране на анализа
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
analytics.settings=Можете да промените настройките за анализ във config/settings.yml файла
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -145,7 +147,7 @@ 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=Popular
|
navbar.sections.popular=Популярни
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -202,9 +204,9 @@ adminUserSettings.header=Настройки за администраторск
|
|||||||
adminUserSettings.admin=Администратор
|
adminUserSettings.admin=Администратор
|
||||||
adminUserSettings.user=Потребител
|
adminUserSettings.user=Потребител
|
||||||
adminUserSettings.addUser=Добавяне на нов потребител
|
adminUserSettings.addUser=Добавяне на нов потребител
|
||||||
adminUserSettings.deleteUser=Delete User
|
adminUserSettings.deleteUser=Изтриване на потребител
|
||||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
adminUserSettings.confirmDeleteUser=Трябва ли потребителят да бъде изтрит?
|
||||||
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
adminUserSettings.confirmChangeUserStatus=Трябва ли потребителят да бъде деактивиран/активиран?
|
||||||
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
|
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
|
||||||
adminUserSettings.roles=Роли
|
adminUserSettings.roles=Роли
|
||||||
adminUserSettings.role=Роля
|
adminUserSettings.role=Роля
|
||||||
@@ -218,32 +220,32 @@ adminUserSettings.forceChange=Принудете потребителя да п
|
|||||||
adminUserSettings.submit=Съхранете потребителя
|
adminUserSettings.submit=Съхранете потребителя
|
||||||
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
||||||
adminUserSettings.authenticated=Удостоверен
|
adminUserSettings.authenticated=Удостоверен
|
||||||
adminUserSettings.editOwnProfil=Edit own profile
|
adminUserSettings.editOwnProfil=Редактиране на собствен профил
|
||||||
adminUserSettings.enabledUser=enabled user
|
adminUserSettings.enabledUser=активиран потребител
|
||||||
adminUserSettings.disabledUser=disabled user
|
adminUserSettings.disabledUser=деактивиран потребител
|
||||||
adminUserSettings.activeUsers=Active Users:
|
adminUserSettings.activeUsers=Активни потребители:
|
||||||
adminUserSettings.disabledUsers=Disabled Users:
|
adminUserSettings.disabledUsers=Деактивирани потребители:
|
||||||
adminUserSettings.totalUsers=Total Users:
|
adminUserSettings.totalUsers=Общо потребители:
|
||||||
adminUserSettings.lastRequest=Last Request
|
adminUserSettings.lastRequest=Последна заявка
|
||||||
|
|
||||||
|
|
||||||
database.title=Database Import/Export
|
database.title=Импорт/Експорт на база данни
|
||||||
database.header=Database Import/Export
|
database.header=Импорт/Експорт на база данни
|
||||||
database.fileName=File Name
|
database.fileName=Име на файл
|
||||||
database.creationDate=Creation Date
|
database.creationDate=Дата на създаване
|
||||||
database.fileSize=File Size
|
database.fileSize=Размер на файла
|
||||||
database.deleteBackupFile=Delete Backup File
|
database.deleteBackupFile=Изтриване на архивен файл
|
||||||
database.importBackupFile=Import Backup File
|
database.importBackupFile=Импортиране на архивен файл
|
||||||
database.downloadBackupFile=Download Backup File
|
database.downloadBackupFile=Изтеглете архивен файл
|
||||||
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
database.info_1=Когато импортирате данни, е от решаващо значение да осигурите правилната структура. Ако не сте сигурни в това, което правите, потърсете съвет и подкрепа от професионалист. Грешка в структурата може да причини неизправност на приложението, включително пълна невъзможност за стартиране на приложението.
|
||||||
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
database.info_2=Името на файла няма значение при качване. След това ще бъде преименуван, за да следва формата backup_user_yyyyMMddHHmm.sql, осигурявайки последователна конвенция за именуване.
|
||||||
database.submit=Import Backup
|
database.submit=Импортиране на резервно копие
|
||||||
database.importIntoDatabaseSuccessed=Import into database successed
|
database.importIntoDatabaseSuccessed=Импортирането в базата данни бе успешно
|
||||||
database.fileNotFound=File not Found
|
database.fileNotFound=Файлът не е намерен
|
||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=Файлът не трябва да е нулев или празен
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Неуспешно импортиране на файл
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
session.expired=Вашата сесия е изтекла. Моля, опреснете страницата и опитайте отново.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -390,9 +392,9 @@ home.certSign.title=Подпишете със сертификат
|
|||||||
home.certSign.desc=Подписва PDF със сертификат/ключ (PEM/P12)
|
home.certSign.desc=Подписва PDF със сертификат/ключ (PEM/P12)
|
||||||
certSign.tags=удостоверяване,PEM,P12,официален,шифроване
|
certSign.tags=удостоверяване,PEM,P12,официален,шифроване
|
||||||
|
|
||||||
home.removeCertSign.title=Remove Certificate Sign
|
home.removeCertSign.title=Премахване на знака за сертификат
|
||||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
home.removeCertSign.desc=Премахване на подпис на сертификат от PDF
|
||||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=удостоверяване,PEM,P12,официален,декриптиране
|
||||||
|
|
||||||
home.pageLayout.title=Оформление с няколко страници
|
home.pageLayout.title=Оформление с няколко страници
|
||||||
home.pageLayout.desc=Слейте няколко страници от PDF документ в една страница
|
home.pageLayout.desc=Слейте няколко страници от PDF документ в една страница
|
||||||
@@ -498,33 +500,33 @@ home.BookToPDF.title=Книга към PDF
|
|||||||
home.BookToPDF.desc=Преобразува формати на книги/комикси в PDF с помощта на calibre
|
home.BookToPDF.desc=Преобразува формати на книги/комикси в PDF с помощта на calibre
|
||||||
BookToPDF.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
|
BookToPDF.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Remove image
|
home.removeImagePdf.title=Премахване на изображение
|
||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Премахнете изображението от PDF, за да намалите размера на файла
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Премахване на изображение, операции на страници, админ страна, страна на сървъра
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=Разделете PDF по глави
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Разделете PDF на множество файлове въз основа на неговата структура на глави.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=разделяне, глави, отметки, организиране
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Замени-инвертиране-на-цвят
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Замяна-инвертиране на цвят PDF
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Замяна и обръщане на цвят
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Заменете цвета на текста и фона в PDF и обърнете пълния цвят на PDF, за да намалите размера на файла
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Замяна на цвят, операции на страници, заден край, страна на сървъра
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Опции за замяна или инвертиране на цвят
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=По подразбиране (цветове с висок контраст по подразбиране)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=По избор (персонализирани цветове)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Пълно инвертиране (Инвертиране на всички цветове)
|
||||||
replace-color.selectText.5=High contrast color options
|
replace-color.selectText.5=Цветови опции с висок контраст
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=Бял текст на черен фон
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=Черен текст на бял фон
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=Жълт текст на черен фон
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=Зелен текст на черен фон
|
||||||
replace-color.selectText.10=Choose text Color
|
replace-color.selectText.10=Изберете цвят на текста
|
||||||
replace-color.selectText.11=Choose background Color
|
replace-color.selectText.11=Изберете цвят на фона
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Замени
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -543,18 +545,17 @@ login.locked=Вашият акаунт е заключен.
|
|||||||
login.signinTitle=Моля впишете се
|
login.signinTitle=Моля впишете се
|
||||||
login.ssoSignIn=Влизане чрез еднократно влизане
|
login.ssoSignIn=Влизане чрез еднократно влизане
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
|
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
|
||||||
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
login.oauth2AdminBlockedUser=Регистрацията или влизането на нерегистрирани потребители в момента е блокирано. Моля, свържете се с администратора.
|
||||||
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
|
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
|
||||||
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
|
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
|
||||||
login.oauth2invalidRequest=Невалидна заявка
|
login.oauth2invalidRequest=Невалидна заявка
|
||||||
login.oauth2AccessDenied=Отказан достъп
|
login.oauth2AccessDenied=Отказан достъп
|
||||||
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
||||||
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=Потребителят е деактивиран, влизането в момента е блокирано с това потребителско име. Моля, свържете се с администратора.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Вече сте влезли в
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=устройства. Моля, излезте от устройствата и опитайте отново.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Имате твърде много активни сесии
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматично редактиране
|
autoRedact.title=Автоматично редактиране
|
||||||
@@ -729,7 +730,7 @@ pageLayout.submit=Подайте
|
|||||||
scalePages.title=Коригиране на мащаба на страницата
|
scalePages.title=Коригиране на мащаба на страницата
|
||||||
scalePages.header=Коригиране на мащаба на страницата
|
scalePages.header=Коригиране на мащаба на страницата
|
||||||
scalePages.pageSize=Размер на страница от документа.
|
scalePages.pageSize=Размер на страница от документа.
|
||||||
scalePages.keepPageSize=Original Size
|
scalePages.keepPageSize=Оригинален размер
|
||||||
scalePages.scaleFactor=Ниво на мащабиране (изрязване) на страница.
|
scalePages.scaleFactor=Ниво на мащабиране (изрязване) на страница.
|
||||||
scalePages.submit=Подайте
|
scalePages.submit=Подайте
|
||||||
|
|
||||||
@@ -753,10 +754,10 @@ certSign.submit=Подпишете PDF
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Remove Certificate Signature
|
removeCertSign.title=Премахване на подписа на сертификата
|
||||||
removeCertSign.header=Remove the digital certificate from the PDF
|
removeCertSign.header=Премахнете цифровия сертификат от PDF
|
||||||
removeCertSign.selectPDF=Select a PDF file:
|
removeCertSign.selectPDF=Изберете PDF файл:
|
||||||
removeCertSign.submit=Remove Signature
|
removeCertSign.submit=Премахване на подпис
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
@@ -778,11 +779,14 @@ removeAnnotations.submit=Премахване
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Сравнявай
|
compare.title=Сравнявай
|
||||||
compare.header=Сравнявай PDF-и
|
compare.header=Сравнявай PDF-и
|
||||||
compare.highlightColor.1=Highlight Color 1:
|
compare.highlightColor.1=Цвят на маркирането 1:
|
||||||
compare.highlightColor.2=Highlight Color 2:
|
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=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Начертайте подпис
|
|||||||
sign.text=Въвеждане на текст
|
sign.text=Въвеждане на текст
|
||||||
sign.clear=Изчисти
|
sign.clear=Изчисти
|
||||||
sign.add=Добави
|
sign.add=Добави
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -831,7 +840,7 @@ ScannerImageSplit.selectText.7=Минимална контурна площ:
|
|||||||
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
|
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
|
||||||
ScannerImageSplit.selectText.9=Размер на рамката:
|
ScannerImageSplit.selectText.9=Размер на рамката:
|
||||||
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
|
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
|
||||||
ScannerImageSplit.info=Python is not installed. It is required to run.
|
ScannerImageSplit.info=Python не е инсталиран. Изисква се да се изпълнява.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -858,7 +867,7 @@ ocr.submit=Обработка на PDF чрез OCR
|
|||||||
extractImages.title=Извличане на изображения
|
extractImages.title=Извличане на изображения
|
||||||
extractImages.header=Извличане на изображения
|
extractImages.header=Извличане на изображения
|
||||||
extractImages.selectText=Изберете формат на изображението, в който да преобразувате извлечените изображения
|
extractImages.selectText=Изберете формат на изображението, в който да преобразувате извлечените изображения
|
||||||
extractImages.allowDuplicates=Save duplicate images
|
extractImages.allowDuplicates=Запазване на дублирани изображения
|
||||||
extractImages.submit=Извличане
|
extractImages.submit=Извличане
|
||||||
|
|
||||||
|
|
||||||
@@ -896,7 +905,7 @@ merge.title=Обединяване
|
|||||||
merge.header=Обединяване на множество PDF файлове (2+)
|
merge.header=Обединяване на множество PDF файлове (2+)
|
||||||
merge.sortByName=Сортиране по име
|
merge.sortByName=Сортиране по име
|
||||||
merge.sortByDate=Сортиране по дата
|
merge.sortByDate=Сортиране по дата
|
||||||
merge.removeCertSign=Remove digital signature in the merged file?
|
merge.removeCertSign=Премахване на цифровия подпис в обединения файл?
|
||||||
merge.submit=Обединяване
|
merge.submit=Обединяване
|
||||||
|
|
||||||
|
|
||||||
@@ -914,7 +923,7 @@ pdfOrganiser.mode.6=Четно-нечетно разделяне
|
|||||||
pdfOrganiser.mode.7=Премахни първо
|
pdfOrganiser.mode.7=Премахни първо
|
||||||
pdfOrganiser.mode.8=Премахване на последния
|
pdfOrganiser.mode.8=Премахване на последния
|
||||||
pdfOrganiser.mode.9=Премахване на първия и последния
|
pdfOrganiser.mode.9=Премахване на първия и последния
|
||||||
pdfOrganiser.mode.10=Odd-Even Merge
|
pdfOrganiser.mode.10=Обединяване на четно и нечетно
|
||||||
pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
|
pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
|
||||||
|
|
||||||
|
|
||||||
@@ -983,7 +992,7 @@ pdfToImage.color=Цвят
|
|||||||
pdfToImage.grey=Скала на сивото
|
pdfToImage.grey=Скала на сивото
|
||||||
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
|
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
|
||||||
pdfToImage.submit=Преобразуване
|
pdfToImage.submit=Преобразуване
|
||||||
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
pdfToImage.info=Python не е инсталиран. Изисква се за конвертиране на WebP.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1020,7 +1029,7 @@ watermark.selectText.6=дължинаSpacer (Разстояние между в
|
|||||||
watermark.selectText.7=Непрозрачност (0% - 100%):
|
watermark.selectText.7=Непрозрачност (0% - 100%):
|
||||||
watermark.selectText.8=Тип воден знак:
|
watermark.selectText.8=Тип воден знак:
|
||||||
watermark.selectText.9=Изображение за воден знак:
|
watermark.selectText.9=Изображение за воден знак:
|
||||||
watermark.selectText.10=Convert PDF to PDF-Image
|
watermark.selectText.10=Конвертирайте PDF в PDF-изображение
|
||||||
watermark.submit=Добавяне на воден знак
|
watermark.submit=Добавяне на воден знак
|
||||||
watermark.type.1=Текст
|
watermark.type.1=Текст
|
||||||
watermark.type.2=Изображение
|
watermark.type.2=Изображение
|
||||||
@@ -1077,7 +1086,7 @@ pdfToPDFA.credit=Тази услуга използва ghostscript за PDF/A
|
|||||||
pdfToPDFA.submit=Преобразуване
|
pdfToPDFA.submit=Преобразуване
|
||||||
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
|
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
|
||||||
pdfToPDFA.outputFormat=Изходен формат
|
pdfToPDFA.outputFormat=Изходен формат
|
||||||
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
pdfToPDFA.pdfWithDigitalSignature=PDF файлът съдържа цифров подпис. Това ще бъде премахнато в следващата стъпка.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
@@ -1118,10 +1127,10 @@ PDFToXML.credit=Тази услуга използва LibreOffice за прео
|
|||||||
PDFToXML.submit=Преобразуване
|
PDFToXML.submit=Преобразуване
|
||||||
|
|
||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF ??? CSV
|
PDFToCSV.title=PDF към CSV
|
||||||
PDFToCSV.header=PDF ??? CSV
|
PDFToCSV.header=PDF към CSV
|
||||||
PDFToCSV.prompt=Изберете страница за извличане на таблица
|
PDFToCSV.prompt=Изберете страница за извличане на таблица
|
||||||
PDFToCSV.submit=????
|
PDFToCSV.submit=Преобразуване
|
||||||
|
|
||||||
#split-by-size-or-count
|
#split-by-size-or-count
|
||||||
split-by-size-or-count.title=Разделяне на PDF по размер или брой
|
split-by-size-or-count.title=Разделяне на PDF по размер или брой
|
||||||
@@ -1179,15 +1188,15 @@ licenses.version=Версия
|
|||||||
licenses.license=Лиценз
|
licenses.license=Лиценз
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survey
|
survey.nav=Анкета
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Анкета
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF няма проследяване, така че искаме да чуем мнението на нашите потребители за подобряване на Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
survey.changes=Stirling-PDF се промени от последното проучване! За да научите повече, моля, проверете публикацията в нашия блог тук:
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
survey.changes2=С тези промени получаваме платена бизнес подкрепа и финансиране
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Моля, помислете дали да не участвате в нашата анкета!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Изскачащият прозорец с анкетата ще бъде деактивиран при следващите актуализации, но ще бъде наличен в долната част на страницата)
|
||||||
survey.button=Take Survey
|
survey.button=Участвайте в анкетата
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=Не показвай повече
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
@@ -1205,21 +1214,19 @@ error.discordSubmit=Discord - Изпратете запитване за под
|
|||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Remove image
|
removeImage.title=Премахване на изображението
|
||||||
removeImage.header=Remove image
|
removeImage.header=Премахване на изображението
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Премахване на изображението
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Премахване на изображението
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
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.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.submit=Split PDF
|
|
||||||
|
|
||||||
|
|
||||||
|
splitByChapters.title=Разделете PDF по глави
|
||||||
|
splitByChapters.header=Разделете PDF по глави
|
||||||
|
splitByChapters.bookmarkLevel=Ниво на отметка
|
||||||
|
splitByChapters.includeMetadata=Включете метаданни
|
||||||
|
splitByChapters.allowDuplicates=Разрешаване на дубликати
|
||||||
|
splitByChapters.desc.1=Този инструмент разделя PDF файл на множество PDF файлове въз основа на неговата структура на глави.
|
||||||
|
splitByChapters.desc.2=Ниво на отметка: Изберете нивото на отметките, които да използвате за разделяне (0 за най-високо ниво, 1 за второ ниво и т.н.).
|
||||||
|
splitByChapters.desc.3=Включване на метаданни: Ако е отметнато, метаданните на оригиналния PDF ще бъдат включени във всеки разделен PDF.
|
||||||
|
splitByChapters.desc.4=Разрешаване на дубликати: Ако е отметнато, позволява множество отметки на една и съща страница за създаване на отделни PDF файлове.
|
||||||
|
splitByChapters.submit=Разделяне на PDF
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -783,6 +784,9 @@ 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=Comparar
|
compare.submit=Comparar
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Dibuixa la signatura
|
|||||||
sign.text=Entrada de text
|
sign.text=Entrada de text
|
||||||
sign.clear=Esborrar
|
sign.clear=Esborrar
|
||||||
sign.add=Afegeix
|
sign.add=Afegeix
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porovnat
|
compare.submit=Porovnat
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Knihy a komiksy do PDF
|
BookToPDF.title=Knihy a komiksy do PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Nakreslit podpis
|
|||||||
sign.text=Vstup textu
|
sign.text=Vstup textu
|
||||||
sign.clear=Vymazat
|
sign.clear=Vymazat
|
||||||
sign.add=Přidat
|
sign.add=Přidat
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=Bruger er deaktiveret, login er i øjeblikket blokeret med
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Rediger
|
autoRedact.title=Auto Rediger
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Fremhævningsfarve 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Sammenlign
|
compare.submit=Sammenlign
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Bøger og Tegneserier til PDF
|
BookToPDF.title=Bøger og Tegneserier til PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Tegn Underskrift
|
|||||||
sign.text=Tekstinput
|
sign.text=Tekstinput
|
||||||
sign.clear=Ryd
|
sign.clear=Ryd
|
||||||
sign.add=Tilføj
|
sign.add=Tilføj
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Informationen
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Datenschutz
|
legal.privacy=Datenschutz
|
||||||
legal.terms=AGB
|
legal.terms=AGB
|
||||||
@@ -114,21 +116,21 @@ pipelineOptions.validateButton=Validieren
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Auf Pro-Version umsteigen
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Diese Funktion ist nur für Pro-Nutzer verfügbar.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling-PDF Pro unterstützt YAML Konfigurationsdateien, SSO und weitere Funktionen.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Suchen Sie weitere Funktionen in der Benutzerverwaltung? Steigen Sie auf die Pro-Version um
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=Möchten Sie Stirling-PDF verbessern?
|
||||||
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.paragraph1=Stirling-PDF verfügt über Opt-in-Analytics, die uns helfen, das Produkt zu verbessern. Wir zeichnen keine persönlichen Informationen oder Dateiinhalte auf.
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Bitte erwägen Sie die Analytics zu aktivieren, um Stirling-PDF beim Wachsen zu helfen und um unsere User besser zu verstehen.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Analytics aktivieren
|
||||||
analytics.disable=Disable analytics
|
analytics.disable=Analytics deaktivieren
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
analytics.settings=Sie können die Einstellungen für die Analytics in der config/settings.yml Datei bearbeiten
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -392,7 +394,7 @@ certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
|
|||||||
|
|
||||||
home.removeCertSign.title=Zertifikatsignatur entfernen
|
home.removeCertSign.title=Zertifikatsignatur entfernen
|
||||||
home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
|
home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
|
||||||
removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln,decrypt
|
removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln
|
||||||
|
|
||||||
home.pageLayout.title=Mehrseitiges Layout
|
home.pageLayout.title=Mehrseitiges Layout
|
||||||
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
||||||
@@ -503,28 +505,28 @@ home.removeImagePdf.desc=Bild aus PDF entfernen, um die Dateigröße zu verringe
|
|||||||
removeImagePdf.tags=bild entfernen,seitenoperationen,back end,server side
|
removeImagePdf.tags=bild entfernen,seitenoperationen,back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=PDF-Datei nach Kapiteln aufteilen
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Aufteilung einer PDF-Datei in mehrere Dateien auf Basis der Kapitelstruktur.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=aufteilen,kapitel,lesezeichen,organisieren
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Farbe Ersetzen-Invertieren
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Farb-PDF Ersetzen-Invertieren
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Farbe ersetzen und invertieren
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Ersetzen Sie die Farbe des Texts und Hintergrund der PDF-Datei und invertieren Sie die komplette Farbe der PDF-Datei, um die Dateigröße zu reduzieren
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Farbe ersetzen,Seiteneinstellungen,Backend,Serverseite
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Ersetzen oder Invertieren von Farboptionen
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=Standard(Standardfarben mit hohem Kontrast)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=Benutzerdefiniert(Benutzerdefinierte Farben)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Vollinvertierung(Invertierung aller Farben)
|
||||||
replace-color.selectText.5=High contrast color options
|
replace-color.selectText.5=Farboptionen mit hohem Kontrast
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=Weißer Text auf schwarzem Hintergrund
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=Schwarzer Text auf weißem Hintergrund
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=Gelber Text auf schwarzem Hintergrund
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=Grüner Text auf schwarzem Hintergrund
|
||||||
replace-color.selectText.10=Choose text Color
|
replace-color.selectText.10=Textfarbe auswählen
|
||||||
replace-color.selectText.11=Choose background Color
|
replace-color.selectText.11=Hintergrundfarbe auswählen
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Ersetzen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -551,10 +553,9 @@ login.oauth2AccessDenied=Zugriff abgelehnt
|
|||||||
login.oauth2InvalidTokenResponse=Ungültige Token-Antwort
|
login.oauth2InvalidTokenResponse=Ungültige Token-Antwort
|
||||||
login.oauth2InvalidIdToken=Ungültiges ID-Token
|
login.oauth2InvalidIdToken=Ungültiges ID-Token
|
||||||
login.userIsDisabled=Benutzer ist deaktiviert, die Anmeldung ist mit diesem Benutzernamen derzeit gesperrt. Bitte wenden Sie sich an den Administrator.
|
login.userIsDisabled=Benutzer ist deaktiviert, die Anmeldung ist mit diesem Benutzernamen derzeit gesperrt. Bitte wenden Sie sich an den Administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Sie sind bereits an
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=Geräten angemeldet. Bitte melden Sie sich dort ab und versuchen es dann erneut.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Sie haben zu viele aktive Sitzungen
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisch zensieren/schwärzen
|
autoRedact.title=Automatisch zensieren/schwärzen
|
||||||
@@ -704,7 +705,7 @@ autoSplitPDF.header=PDF automatisch teilen
|
|||||||
autoSplitPDF.description=Drucken Sie, fügen Sie ein, scannen Sie, laden Sie hoch und lassen Sie uns Ihre Dokumente automatisch trennen. Kein manuelles Sortieren erforderlich.
|
autoSplitPDF.description=Drucken Sie, fügen Sie ein, scannen Sie, laden Sie hoch und lassen Sie uns Ihre Dokumente automatisch trennen. Kein manuelles Sortieren erforderlich.
|
||||||
autoSplitPDF.selectText.1=Drucken Sie einige Trennblätter aus (schwarz/weiß ist ausreichend).
|
autoSplitPDF.selectText.1=Drucken Sie einige Trennblätter aus (schwarz/weiß ist ausreichend).
|
||||||
autoSplitPDF.selectText.2=Scannen Sie alle Dokumente auf einmal, indem Sie das Trennblatt zwischen die Dokumente einlegen.
|
autoSplitPDF.selectText.2=Scannen Sie alle Dokumente auf einmal, indem Sie das Trennblatt zwischen die Dokumente einlegen.
|
||||||
autoSplitPDF.selectText.3=Laden Sie die einzelne große gescannte PDF-Datei hoch und überlassen Sie Stirling PDF den Rest.
|
autoSplitPDF.selectText.3=Laden Sie die einzelne große gescannte PDF-Datei hoch und überlassen Sie Stirling-PDF den Rest.
|
||||||
autoSplitPDF.selectText.4=Trennseiten werden automatisch erkannt und entfernt, so dass ein sauberes Enddokument garantiert ist.
|
autoSplitPDF.selectText.4=Trennseiten werden automatisch erkannt und entfernt, so dass ein sauberes Enddokument garantiert ist.
|
||||||
autoSplitPDF.formPrompt=PDF mit Stirling-PDF Seitentrennern hochladen:
|
autoSplitPDF.formPrompt=PDF mit Stirling-PDF Seitentrennern hochladen:
|
||||||
autoSplitPDF.duplexMode=Duplex-Modus (Scannen von Vorder- und Rückseite)
|
autoSplitPDF.duplexMode=Duplex-Modus (Scannen von Vorder- und Rückseite)
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight-Farbe 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Vergleichen
|
compare.submit=Vergleichen
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Bücher und Comics zu PDF
|
BookToPDF.title=Bücher und Comics zu PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Signatur zeichnen
|
|||||||
sign.text=Texteingabe
|
sign.text=Texteingabe
|
||||||
sign.clear=Leeren
|
sign.clear=Leeren
|
||||||
sign.add=Signieren
|
sign.add=Signieren
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1211,15 +1220,13 @@ removeImage.removeImage=Bild entfernen
|
|||||||
removeImage.submit=Bild entfernen
|
removeImage.submit=Bild entfernen
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
splitByChapters.title=PDF nach Kapiteln aufteilen
|
||||||
splitByChapters.header=Split PDF by Chapters
|
splitByChapters.header=PDF nach Kapiteln aufteilen
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
splitByChapters.bookmarkLevel=Lesezeichenebene
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
splitByChapters.includeMetadata=Metadaten einschließen
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
splitByChapters.allowDuplicates=Duplikate erlauben
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
splitByChapters.desc.1=Dieses Werkzeug teilt eine PDF-Datei auf der Grundlage ihrer Kapitelstruktur in mehrere PDF-Dateien auf.
|
||||||
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=Lesezeichenebene: Wählen Sie die Ebene der Lesezeichen, die für die Aufteilung verwendet werden soll (0 für die erste Ebene, 1 für die zweite Ebene usw.).
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
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=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Duplikate erlauben: Wenn diese Option aktiviert ist, können mehrere Lesezeichen auf derselben Seite separate PDF Dateien erstellen.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=PDF teilen
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
|
autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Έγγραφο 1
|
compare.document.1=Έγγραφο 1
|
||||||
compare.document.2=Έγγραφο 2
|
compare.document.2=Έγγραφο 2
|
||||||
compare.submit=Σύγκριση
|
compare.submit=Σύγκριση
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books και Comics σε PDF
|
BookToPDF.title=Books και Comics σε PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Σχεδίαση υπογραφής
|
|||||||
sign.text=Εισαγωγή κειμένου
|
sign.text=Εισαγωγή κειμένου
|
||||||
sign.clear=Καθάρισμα
|
sign.clear=Καθάρισμα
|
||||||
sign.add=Προσθήκη
|
sign.add=Προσθήκη
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -783,6 +784,9 @@ 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
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Draw Signature
|
|||||||
sign.text=Text Input
|
sign.text=Text Input
|
||||||
sign.clear=Clear
|
sign.clear=Clear
|
||||||
sign.add=Add
|
sign.add=Add
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -783,6 +784,9 @@ 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
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Draw Signature
|
|||||||
sign.text=Text Input
|
sign.text=Text Input
|
||||||
sign.clear=Clear
|
sign.clear=Clear
|
||||||
sign.add=Add
|
sign.add=Add
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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=Font Size
|
addPageNumbers.fontSize=Tamaño de Letra
|
||||||
addPageNumbers.fontName=Font Name
|
addPageNumbers.fontName=Nombre de Letra
|
||||||
pdfPrompt=Seleccionar PDF(s)
|
pdfPrompt=Seleccionar PDF(s)
|
||||||
multiPdfPrompt=Seleccionar PDFs (2+)
|
multiPdfPrompt=Seleccionar PDFs (2+)
|
||||||
multiPdfDropPrompt=Seleccione (o arrastre y suelte) todos los PDFs que quiera
|
multiPdfDropPrompt=Seleccione (o arrastre y suelte) todos los PDFs que quiera
|
||||||
@@ -50,7 +50,7 @@ WorkInProgess=Tarea en progreso, puede no funcionar o ralentizarse; ¡por favor,
|
|||||||
poweredBy=Desarrollado por
|
poweredBy=Desarrollado por
|
||||||
yes=Sí
|
yes=Sí
|
||||||
no=No
|
no=No
|
||||||
changedCredsMessage=Se cambiaron las credenciales!
|
changedCredsMessage=¡Se cambiaron las credenciales!
|
||||||
notAuthenticatedMessage=Usuario no autentificado.
|
notAuthenticatedMessage=Usuario no autentificado.
|
||||||
userNotFoundMessage=Usuario no encontrado.
|
userNotFoundMessage=Usuario no encontrado.
|
||||||
incorrectPasswordMessage=La contraseña actual no es correcta.
|
incorrectPasswordMessage=La contraseña actual no es correcta.
|
||||||
@@ -77,14 +77,16 @@ color=Color
|
|||||||
sponsor=Patrocinador
|
sponsor=Patrocinador
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Página
|
||||||
pages=Pages
|
pages=Páginas
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Política de Privacidad
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Términos y Condiciones
|
||||||
legal.accessibility=Accessibility
|
legal.accessibility=Accesibilidad
|
||||||
legal.cookie=Cookie Policy
|
legal.cookie=Política de Cookies
|
||||||
legal.impressum=Impressum
|
legal.impressum=Impresión
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -114,21 +116,21 @@ pipelineOptions.validateButton=Validar
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Actualiza a Pro
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Esta característica está únicamente disponible para usuarios Pro.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro soporta configuración de ficheros YAML y otras características SSO.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=¿Busca más funciones de administración de usuarios? Consulte Stirling PDF Pro
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=¿Quieres mejorar 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.paragraph1=Stirling PDF ha optado por analíticas para ayudarnos a mejorar el producto. No rastreamos ninguna información personal ni contenido de archivos.
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Considere habilitar analíticas para ayudar a Stirling-PDF a crecer y permitirnos comprender mejor a nuestros usuarios.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Habilitar analíticas
|
||||||
analytics.disable=Disable analytics
|
analytics.disable=Deshabilitar analíticas
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
analytics.settings=Puede cambiar la configuración de analíticas en el archivo config/settings.yml
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -243,7 +245,7 @@ database.fileNotFound=Archivo no encontrado
|
|||||||
database.fileNullOrEmpty=El archivo no debe ser nulo o vacío.
|
database.fileNullOrEmpty=El archivo no debe ser nulo o vacío.
|
||||||
database.failedImportFile=Archivo de importación fallido
|
database.failedImportFile=Archivo de importación fallido
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
session.expired=Tu sesión ha caducado. Actualice la página e inténtelo de nuevo.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -392,7 +394,7 @@ certSign.tags=autentificar,PEM,P12,oficial,encriptar
|
|||||||
|
|
||||||
home.removeCertSign.title=Quitar signo de certificado
|
home.removeCertSign.title=Quitar signo de certificado
|
||||||
home.removeCertSign.desc=Eliminar firma de certificado de PDF
|
home.removeCertSign.desc=Eliminar firma de certificado de PDF
|
||||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=autenticar,PEM,P12,oficial,desencriptar
|
||||||
|
|
||||||
home.pageLayout.title=Diseño de varias páginas
|
home.pageLayout.title=Diseño de varias páginas
|
||||||
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
||||||
@@ -503,28 +505,28 @@ home.removeImagePdf.desc=Eliminar imagen del PDF> para reducir el tamaño de arc
|
|||||||
removeImagePdf.tags=Eliminar imagen,Operaciones de página,Back end,lado del servidor
|
removeImagePdf.tags=Eliminar imagen,Operaciones de página,Back end,lado del servidor
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=Dividir PDF por capítulos
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Divida un PDF en varios archivos según su estructura de capítulos.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=dividir,capítulos,marcadores,organizar
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Reemplazar-Invertir-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Reemplazar-Invertir Color en PDF
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Reemplazar e Invertir Color
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Reemplaza el color del texto y el fondo en el PDF e invierte el color completo del PDF para reducir el tamaño del archivo
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Reemplazar Color,Operaciones de Página,Back end,Lado del servidor
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Opciones para Reemplazar o Invertir color
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=Predeterminado (Colores de alto contraste predeterminados)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=Personalizado (Colores personalizados)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Invertir Completo (Invertir todos los colores)
|
||||||
replace-color.selectText.5=High contrast color options
|
replace-color.selectText.5=Opciones de color de alto contraste
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=Texto blanco sobre fondo negro
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=Texto negro sobre fondo blanco
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=Texto amarillo sobre fondo negro
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=Texto verde sobre fondo negro
|
||||||
replace-color.selectText.10=Choose text Color
|
replace-color.selectText.10=Elegir Color de Texto
|
||||||
replace-color.selectText.11=Choose background Color
|
replace-color.selectText.11=Elegir Color de Fondo
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Reemplazar
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -551,10 +553,9 @@ login.oauth2AccessDenied=Acceso denegado
|
|||||||
login.oauth2InvalidTokenResponse=Respuesta de token no válida
|
login.oauth2InvalidTokenResponse=Respuesta de token no válida
|
||||||
login.oauth2InvalidIdToken=Token de identificación no válido
|
login.oauth2InvalidIdToken=Token de identificación no válido
|
||||||
login.userIsDisabled=El usuario está desactivado, actualmente el acceso está bloqueado para ese nombre de usuario. Por favor, póngase en contacto con el administrador.
|
login.userIsDisabled=El usuario está desactivado, actualmente el acceso está bloqueado para ese nombre de usuario. Por favor, póngase en contacto con el administrador.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Ya has iniciado sesión en
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=dispositivos. Cierra sesión en los dispositivos y vuelve a intentarlo.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Tienes demasiadas sesiones activas
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redactar
|
autoRedact.title=Auto Redactar
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Color resaltado 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Libros y Cómics a PDF
|
BookToPDF.title=Libros y Cómics a PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Dibujar firma
|
|||||||
sign.text=Entrada de texto
|
sign.text=Entrada de texto
|
||||||
sign.clear=Borrar
|
sign.clear=Borrar
|
||||||
sign.add=Agregar
|
sign.add=Agregar
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -888,7 +897,7 @@ addImage.title=Añadir imagen
|
|||||||
addImage.header=Añadir imagen de PDF
|
addImage.header=Añadir imagen de PDF
|
||||||
addImage.everyPage=¿Todas las páginas?
|
addImage.everyPage=¿Todas las páginas?
|
||||||
addImage.upload=Añadir imagen
|
addImage.upload=Añadir imagen
|
||||||
addImage.submit=Añadir imagen
|
addImage.submit=Enviar imagen
|
||||||
|
|
||||||
|
|
||||||
#merge
|
#merge
|
||||||
@@ -1211,15 +1220,13 @@ removeImage.removeImage=Eliminar imagen
|
|||||||
removeImage.submit=Eliminar imagen
|
removeImage.submit=Eliminar imagen
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
splitByChapters.title=Dividir PDF por Capítulos
|
||||||
splitByChapters.header=Split PDF by Chapters
|
splitByChapters.header=Dividir PDF por Capítulos
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
splitByChapters.bookmarkLevel=Nivel de Marcador
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
splitByChapters.includeMetadata=Incluir Metadatos
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
splitByChapters.allowDuplicates=Permitir Duplicados
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
splitByChapters.desc.1=Esta herramienta divide un archivo PDF en múltiples archivos PDF según su estructura de capítulos.
|
||||||
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=Nivel de Marcador: Elige el nivel de marcadores para dividir (0 para el nivel superior, 1 para el segundo nivel, etc.).
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Incluir Metadatos: Si está seleccionado, los metadatos del PDF original se incluirán en cada PDF dividido.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Permitir Duplicados: Si está seleccionado, permite que múltiples marcadores en la misma página creen archivos PDF separados.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Dividir PDF
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Idatzi
|
autoRedact.title=Auto Idatzi
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=1. dokumentua
|
compare.document.1=1. dokumentua
|
||||||
compare.document.2=2. dokumentua
|
compare.document.2=2. dokumentua
|
||||||
compare.submit=Konparatu
|
compare.submit=Konparatu
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Marraztu sinadura
|
|||||||
sign.text=Testua sartzea
|
sign.text=Testua sartzea
|
||||||
sign.clear=Garbitu
|
sign.clear=Garbitu
|
||||||
sign.add=Gehitu
|
sign.add=Gehitu
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
###########
|
###########
|
||||||
# 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=Font Size
|
addPageNumbers.fontSize=Taille de Police
|
||||||
addPageNumbers.fontName=Font Name
|
addPageNumbers.fontName=Nom de la Police
|
||||||
pdfPrompt=Sélectionnez le(s) PDF
|
pdfPrompt=Sélectionnez le(s) PDF
|
||||||
multiPdfPrompt=Sélectionnez les PDF
|
multiPdfPrompt=Sélectionnez les PDF
|
||||||
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
|
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
|
||||||
imgPrompt=Choisir une image
|
imgPrompt=Choisir une image
|
||||||
genericSubmit=Envoyer
|
genericSubmit=Envoyer
|
||||||
processTimeWarning=Attention, ce processus peut prendre jusqu’à une minute en fonction de la taille du fichier.
|
processTimeWarning=Attention, ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier.
|
||||||
pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
||||||
pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
||||||
goToPage=Aller
|
goToPage=Aller
|
||||||
@@ -23,7 +23,7 @@ close=Fermer
|
|||||||
filesSelected=fichiers sélectionnés
|
filesSelected=fichiers sélectionnés
|
||||||
noFavourites=Aucun favori ajouté
|
noFavourites=Aucun favori ajouté
|
||||||
downloadComplete=Téléchargement terminé
|
downloadComplete=Téléchargement terminé
|
||||||
bored=Marre d’attendre ?
|
bored=Marre d'attendre ?
|
||||||
alphabet=Alphabet
|
alphabet=Alphabet
|
||||||
downloadPdf=Télécharger le PDF
|
downloadPdf=Télécharger le PDF
|
||||||
text=Texte
|
text=Texte
|
||||||
@@ -34,9 +34,9 @@ sizes.small=Petit
|
|||||||
sizes.medium=Moyen
|
sizes.medium=Moyen
|
||||||
sizes.large=Grand
|
sizes.large=Grand
|
||||||
sizes.x-large=Très grand
|
sizes.x-large=Très grand
|
||||||
error.pdfPassword=Le document PDF est protégé par un mot de passe qui n’a pas été fourni ou était incorrect
|
error.pdfPassword=Le document PDF est protégé par un mot de passe qui n'a pas été fourni ou était incorrect
|
||||||
delete=Supprimer
|
delete=Supprimer
|
||||||
username=Nom d’utilisateur
|
username=Nom d'utilisateur
|
||||||
password=Mot de passe
|
password=Mot de passe
|
||||||
welcome=Bienvenue
|
welcome=Bienvenue
|
||||||
property=Propriété
|
property=Propriété
|
||||||
@@ -54,12 +54,12 @@ changedCredsMessage=Les identifiants ont été mis à jour !
|
|||||||
notAuthenticatedMessage=Utilisateur non authentifié.
|
notAuthenticatedMessage=Utilisateur non authentifié.
|
||||||
userNotFoundMessage=Utilisateur non trouvé.
|
userNotFoundMessage=Utilisateur non trouvé.
|
||||||
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
|
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
|
||||||
usernameExistsMessage=Le nouveau nom d’utilisateur existe déjà.
|
usernameExistsMessage=Le nouveau nom d'utilisateur existe déjà.
|
||||||
invalidUsernameMessage=Nom d’utilisateur invalide, le nom d’utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
invalidUsernameMessage=Nom d'utilisateur invalide, le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
||||||
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
||||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||||
deleteCurrentUserMessage=Impossible de supprimer l’utilisateur actuellement connecté.
|
deleteCurrentUserMessage=Impossible de supprimer l'utilisateur actuellement connecté.
|
||||||
deleteUsernameExistsMessage=Le nom d’utilisateur n’existe pas et ne peut pas être supprimé.
|
deleteUsernameExistsMessage=Le nom d'utilisateur n'existe pas et ne peut pas être supprimé.
|
||||||
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
|
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
|
||||||
disabledCurrentUserMessage=The current user cannot be disabled
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
|
downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
|
||||||
@@ -68,7 +68,7 @@ userAlreadyExistsWebMessage=L'utilisateur existe déjà en tant qu'utilisateur W
|
|||||||
error=Erreur
|
error=Erreur
|
||||||
oops=Oups !
|
oops=Oups !
|
||||||
help=Aide
|
help=Aide
|
||||||
goHomepage=Aller à la page d’accueil
|
goHomepage=Aller à la page d'accueil
|
||||||
joinDiscord=Rejoignez notre serveur Discord
|
joinDiscord=Rejoignez notre serveur Discord
|
||||||
seeDockerHub=Consulter le Docker Hub
|
seeDockerHub=Consulter le Docker Hub
|
||||||
visitGithub=Visiter le dépôt Github
|
visitGithub=Visiter le dépôt Github
|
||||||
@@ -79,12 +79,14 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Politique de Confidentialité
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Conditions Générales
|
||||||
legal.accessibility=Accessibility
|
legal.accessibility=Accessibilité
|
||||||
legal.cookie=Cookie Policy
|
legal.cookie=Politique des Cookies
|
||||||
legal.impressum=Impressum
|
legal.impressum=Mentions Légales
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -114,21 +116,21 @@ pipelineOptions.validateButton=Valider
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Passer à Pro
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Cette fonctionnalité est uniquement disponible pour les utilisateurs Pro.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro prend en charge les fichiers de configuration YAML et d'autres fonctionnalités SSO.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Vous cherchez plus de fonctionnalités de gestion des utilisateurs ? Découvrez Stirling PDF Pro
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=Souhaitez-vous améliorer 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.paragraph1=Stirling PDF utilise des analyses volontaires pour nous aider à améliorer le produit. Nous ne suivons aucune information personnelle ni le contenu des fichiers.
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Veuillez envisager d'activer les analyses pour aider Stirling-PDF à se développer et pour nous permettre de mieux comprendre nos utilisateurs.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Activer les analyses
|
||||||
analytics.disable=Disable analytics
|
analytics.disable=Désactiver les analyses
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
analytics.settings=Vous pouvez modifier les paramètres des analyses dans le fichier config/settings.yml
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -145,7 +147,7 @@ navbar.sections.convertFrom=Convertir depuis PDF
|
|||||||
navbar.sections.security=Signature et sécurité
|
navbar.sections.security=Signature et sécurité
|
||||||
navbar.sections.advance=Mode avancé
|
navbar.sections.advance=Mode avancé
|
||||||
navbar.sections.edit=Voir et modifier
|
navbar.sections.edit=Voir et modifier
|
||||||
navbar.sections.popular=Popular
|
navbar.sections.popular=Populaire
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -153,8 +155,8 @@ navbar.sections.popular=Popular
|
|||||||
settings.title=Paramètres
|
settings.title=Paramètres
|
||||||
settings.update=Mise à jour disponible
|
settings.update=Mise à jour disponible
|
||||||
settings.updateAvailable={0} est la version actuellement installée. Une nouvelle version ({1}) est disponible.
|
settings.updateAvailable={0} est la version actuellement installée. Une nouvelle version ({1}) est disponible.
|
||||||
settings.appVersion=Version de l’application :
|
settings.appVersion=Version de l'application :
|
||||||
settings.downloadOption.title=Choisissez l’option de téléchargement (pour les téléchargements à fichier unique non ZIP) :
|
settings.downloadOption.title=Choisissez l'option de téléchargement (pour les téléchargements à fichier unique non ZIP) :
|
||||||
settings.downloadOption.1=Ouvrir dans la même fenêtre
|
settings.downloadOption.1=Ouvrir dans la même fenêtre
|
||||||
settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre
|
settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre
|
||||||
settings.downloadOption.3=Télécharger le fichier
|
settings.downloadOption.3=Télécharger le fichier
|
||||||
@@ -168,7 +170,7 @@ settings.cacheInputs.help=Permet de stocker les entrées précédemment utilisé
|
|||||||
changeCreds.title=Modifiez vos identifiants
|
changeCreds.title=Modifiez vos identifiants
|
||||||
changeCreds.header=Mettez à jour vos identifiants de connexion
|
changeCreds.header=Mettez à jour vos identifiants de connexion
|
||||||
changeCreds.changePassword=Vous utilisez les identifiants de connexion par défaut. Veuillez saisir un nouveau mot de passe
|
changeCreds.changePassword=Vous utilisez les identifiants de connexion par défaut. Veuillez saisir un nouveau mot de passe
|
||||||
changeCreds.newUsername=Nouveau nom d’utilisateur
|
changeCreds.newUsername=Nouveau nom d'utilisateur
|
||||||
changeCreds.oldPassword=Mot de passe actuel
|
changeCreds.oldPassword=Mot de passe actuel
|
||||||
changeCreds.newPassword=Nouveau mot de passe
|
changeCreds.newPassword=Nouveau mot de passe
|
||||||
changeCreds.confirmNewPassword=Confirmer le nouveau mot de passe
|
changeCreds.confirmNewPassword=Confirmer le nouveau mot de passe
|
||||||
@@ -178,10 +180,10 @@ changeCreds.submit=Soumettre les modifications
|
|||||||
|
|
||||||
account.title=Paramètres du compte
|
account.title=Paramètres du compte
|
||||||
account.accountSettings=Paramètres du compte
|
account.accountSettings=Paramètres du compte
|
||||||
account.adminSettings=Paramètres d’administration – Voir et ajouter des utilisateurs
|
account.adminSettings=Paramètres d'administration – Voir et ajouter des utilisateurs
|
||||||
account.userControlSettings=Contrôle des paramètres des utilisateurs
|
account.userControlSettings=Contrôle des paramètres des utilisateurs
|
||||||
account.changeUsername=Modifier le nom d’utilisateur
|
account.changeUsername=Modifier le nom d'utilisateur
|
||||||
account.newUsername=Nouveau nom d’utilisateur
|
account.newUsername=Nouveau nom d'utilisateur
|
||||||
account.password=Mot de passe de confirmation
|
account.password=Mot de passe de confirmation
|
||||||
account.oldPassword=Ancien mot de passe
|
account.oldPassword=Ancien mot de passe
|
||||||
account.newPassword=Nouveau mot de passe
|
account.newPassword=Nouveau mot de passe
|
||||||
@@ -202,29 +204,29 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
|
|||||||
adminUserSettings.admin=Administateur
|
adminUserSettings.admin=Administateur
|
||||||
adminUserSettings.user=Utilisateur
|
adminUserSettings.user=Utilisateur
|
||||||
adminUserSettings.addUser=Ajouter un utilisateur
|
adminUserSettings.addUser=Ajouter un utilisateur
|
||||||
adminUserSettings.deleteUser=Delete User
|
adminUserSettings.deleteUser=Supprimer l'utilisateur
|
||||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
adminUserSettings.confirmDeleteUser=Voulez vous vraiment supprimer l'utilisateur ?
|
||||||
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
adminUserSettings.confirmChangeUserStatus=Voulez vous vraiment déactiver/réactiver l'utilisateur ?
|
||||||
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
||||||
adminUserSettings.roles=Rôles
|
adminUserSettings.roles=Rôles
|
||||||
adminUserSettings.role=Rôle
|
adminUserSettings.role=Rôle
|
||||||
adminUserSettings.actions=Actions
|
adminUserSettings.actions=Actions
|
||||||
adminUserSettings.apiUser=Utilisateur API limité
|
adminUserSettings.apiUser=Utilisateur API limité
|
||||||
adminUserSettings.extraApiUser=Utilisateur limité supplémentaire de l’API
|
adminUserSettings.extraApiUser=Utilisateur limité supplémentaire de l'API
|
||||||
adminUserSettings.webOnlyUser=Utilisateur Web uniquement
|
adminUserSettings.webOnlyUser=Utilisateur Web uniquement
|
||||||
adminUserSettings.demoUser=Demo User (Paramètres par défaut)
|
adminUserSettings.demoUser=Demo User (Paramètres par défaut)
|
||||||
adminUserSettings.internalApiUser=Utilisateur de l'API interne
|
adminUserSettings.internalApiUser=Utilisateur de l'API interne
|
||||||
adminUserSettings.forceChange=Forcer l’utilisateur à changer son nom d’utilisateur/mot de passe lors de la connexion
|
adminUserSettings.forceChange=Forcer l'utilisateur à changer son nom d'utilisateur/mot de passe lors de la connexion
|
||||||
adminUserSettings.submit=Ajouter
|
adminUserSettings.submit=Ajouter
|
||||||
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
|
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
|
||||||
adminUserSettings.authenticated=Authentifié
|
adminUserSettings.authenticated=Authentifié
|
||||||
adminUserSettings.editOwnProfil=Edit own profile
|
adminUserSettings.editOwnProfil=Éditer son propre profil
|
||||||
adminUserSettings.enabledUser=enabled user
|
adminUserSettings.enabledUser=Utilisateur activé
|
||||||
adminUserSettings.disabledUser=disabled user
|
adminUserSettings.disabledUser=Utilisateur désactivé
|
||||||
adminUserSettings.activeUsers=Active Users:
|
adminUserSettings.activeUsers=Utilisateurs actifs :
|
||||||
adminUserSettings.disabledUsers=Disabled Users:
|
adminUserSettings.disabledUsers=Utilisateurs désactivés :
|
||||||
adminUserSettings.totalUsers=Total Users:
|
adminUserSettings.totalUsers=Utilisateurs au total :
|
||||||
adminUserSettings.lastRequest=Last Request
|
adminUserSettings.lastRequest=Dernière requête
|
||||||
|
|
||||||
|
|
||||||
database.title=Database Import/Export
|
database.title=Database Import/Export
|
||||||
@@ -243,7 +245,7 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
session.expired=Votre session a expiré. Veuillez recharger la page et réessayer.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -282,7 +284,7 @@ home.pdfToImage.desc=Convertissez un PDF en image (PNG, JPEG, GIF).
|
|||||||
pdfToImage.tags=conversion,img,jpg,image,photo
|
pdfToImage.tags=conversion,img,jpg,image,photo
|
||||||
|
|
||||||
home.pdfOrganiser.title=Organiser
|
home.pdfOrganiser.title=Organiser
|
||||||
home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n’importe quel ordre.
|
home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n'importe quel ordre.
|
||||||
pdfOrganiser.tags=organiser,recto-verso,duplex,even,odd,sort,move
|
pdfOrganiser.tags=organiser,recto-verso,duplex,even,odd,sort,move
|
||||||
|
|
||||||
|
|
||||||
@@ -292,7 +294,7 @@ addImage.tags=img,jpg,image,photo
|
|||||||
|
|
||||||
home.watermark.title=Ajouter un filigrane
|
home.watermark.title=Ajouter un filigrane
|
||||||
home.watermark.desc=Ajoutez un filigrane personnalisé à votre PDF.
|
home.watermark.desc=Ajoutez un filigrane personnalisé à votre PDF.
|
||||||
watermark.tags=texte,filigrane,label,propriété,droit d’auteur,marque déposée,img,jpg,image,photo,copyright,trademark
|
watermark.tags=texte,filigrane,label,propriété,droit d'auteur,marque déposée,img,jpg,image,photo,copyright,trademark
|
||||||
|
|
||||||
home.permissions.title=Modifier les permissions
|
home.permissions.title=Modifier les permissions
|
||||||
home.permissions.desc=Modifiez les permissions de votre PDF.
|
home.permissions.desc=Modifiez les permissions de votre PDF.
|
||||||
@@ -321,16 +323,16 @@ home.changeMetadata.desc=Modifiez, supprimez ou ajoutez des métadonnées à un
|
|||||||
changeMetadata.tags=métadonnées,titre,auteur,date,création,heure,éditeur,statistiques,title,author,date,creation,time,publisher,producer,stats,metadata
|
changeMetadata.tags=métadonnées,titre,auteur,date,création,heure,éditeur,statistiques,title,author,date,creation,time,publisher,producer,stats,metadata
|
||||||
|
|
||||||
home.fileToPDF.title=Fichier en PDF
|
home.fileToPDF.title=Fichier en PDF
|
||||||
home.fileToPDF.desc=Convertissez presque n’importe quel fichiers en PDF (DOCX, PNG, XLS, PPT, TXT et plus).
|
home.fileToPDF.desc=Convertissez presque n'importe quel fichier en PDF (DOCX, PNG, XLS, PPT, TXT, etc.).
|
||||||
fileToPDF.tags=convertion,transformation,format,document,image,slide,texte,conversion,office,docs,word,excel,powerpoint
|
fileToPDF.tags=convertion,transformation,format,document,image,slide,texte,conversion,office,docs,word,excel,powerpoint
|
||||||
|
|
||||||
home.ocr.title=OCR / Nettoyage des numérisations
|
home.ocr.title=OCR / Nettoyage des numérisations
|
||||||
home.ocr.desc=Utilisez l’OCR pour analyser et détecter le texte des images d’un PDF et le rajouter en tant que tel.
|
home.ocr.desc=Utilisez l'OCR pour analyser et détecter le texte des images d'un PDF et le rajouter en tant que tel.
|
||||||
ocr.tags=ocr,reconnaissance,texte,image,numérisation,scan,read,identify,detection,editable
|
ocr.tags=ocr,reconnaissance,texte,image,numérisation,scan,read,identify,detection,editable
|
||||||
|
|
||||||
|
|
||||||
home.extractImages.title=Extraire les images
|
home.extractImages.title=Extraire les images
|
||||||
home.extractImages.desc=Extrayez toutes les images d’un PDF et enregistrez-les dans un ZIP.
|
home.extractImages.desc=Extrayez toutes les images d'un PDF et enregistrez-les dans un ZIP.
|
||||||
extractImages.tags=image,photo,save,archive,zip,capture,grab
|
extractImages.tags=image,photo,save,archive,zip,capture,grab
|
||||||
|
|
||||||
home.pdfToPDFA.title=PDF en PDF/A
|
home.pdfToPDFA.title=PDF en PDF/A
|
||||||
@@ -359,7 +361,7 @@ home.PDFToXML.desc=Convertissez un PDF au format XML.
|
|||||||
PDFToXML.tags=xml,extraction de données,contenu structuré,interopérabilité,data-extraction,structured-content,interop,transformation,convert
|
PDFToXML.tags=xml,extraction de données,contenu structuré,interopérabilité,data-extraction,structured-content,interop,transformation,convert
|
||||||
|
|
||||||
home.ScannerImageSplit.title=Diviser les photos numérisées
|
home.ScannerImageSplit.title=Diviser les photos numérisées
|
||||||
home.ScannerImageSplit.desc=Divisez plusieurs photos à partir d’une photo ou d’un PDF.
|
home.ScannerImageSplit.desc=Divisez plusieurs photos à partir d'une photo ou d'un PDF.
|
||||||
ScannerImageSplit.tags=diviser,détecter automatiquement,numériser,separate,auto-detect,scans,multi-photo,organize
|
ScannerImageSplit.tags=diviser,détecter automatiquement,numériser,separate,auto-detect,scans,multi-photo,organize
|
||||||
|
|
||||||
home.sign.title=Signer
|
home.sign.title=Signer
|
||||||
@@ -367,7 +369,7 @@ home.sign.desc=Ajoutez une signature au PDF avec un dessin, du texte ou une imag
|
|||||||
sign.tags=signer,authorize,initials,drawn-signature,text-sign,image-signature
|
sign.tags=signer,authorize,initials,drawn-signature,text-sign,image-signature
|
||||||
|
|
||||||
home.flatten.title=Rendre inerte
|
home.flatten.title=Rendre inerte
|
||||||
home.flatten.desc=Supprimez tous les éléments et formulaires interactifs d’un PDF.
|
home.flatten.desc=Supprimez tous les éléments et formulaires interactifs d'un PDF.
|
||||||
flatten.tags=inerte,static,deactivate,non-interactive,streamline
|
flatten.tags=inerte,static,deactivate,non-interactive,streamline
|
||||||
|
|
||||||
home.repair.title=Réparer
|
home.repair.title=Réparer
|
||||||
@@ -375,11 +377,11 @@ home.repair.desc=Essayez de réparer un PDF corrompu ou cassé.
|
|||||||
repair.tags=réparer,restaurer,corriger,récupérer,fix,restore,correction,recover
|
repair.tags=réparer,restaurer,corriger,récupérer,fix,restore,correction,recover
|
||||||
|
|
||||||
home.removeBlanks.title=Supprimer les pages vierges
|
home.removeBlanks.title=Supprimer les pages vierges
|
||||||
home.removeBlanks.desc=Détectez et supprimez les pages vierges d’un PDF.
|
home.removeBlanks.desc=Détectez et supprimez les pages vierges d'un PDF.
|
||||||
removeBlanks.tags=pages vierges,supprimer,nettoyer,cleanup,streamline,non-content,organize
|
removeBlanks.tags=pages vierges,supprimer,nettoyer,cleanup,streamline,non-content,organize
|
||||||
|
|
||||||
home.removeAnnotations.title=Supprimer les annotations
|
home.removeAnnotations.title=Supprimer les annotations
|
||||||
home.removeAnnotations.desc=Supprimer tous les commentaires/annotations d’un PDF.
|
home.removeAnnotations.desc=Supprimer tous les commentaires/annotations d'un PDF.
|
||||||
removeAnnotations.tags=commentaires,supprimer,annotations,highlight,notes,markup,remove
|
removeAnnotations.tags=commentaires,supprimer,annotations,highlight,notes,markup,remove
|
||||||
|
|
||||||
home.compare.title=Comparer
|
home.compare.title=Comparer
|
||||||
@@ -390,16 +392,16 @@ home.certSign.title=Signer avec un certificat
|
|||||||
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
|
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
|
||||||
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
|
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
home.removeCertSign.title=Remove Certificate Sign
|
home.removeCertSign.title=Supprimer la signature par certificat
|
||||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
home.removeCertSign.desc=Supprimez la signature par certificat d'un PDF
|
||||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Fusionner des pages
|
home.pageLayout.title=Fusionner des pages
|
||||||
home.pageLayout.desc=Fusionnez plusieurs pages d’un PDF en une seule.
|
home.pageLayout.desc=Fusionnez plusieurs pages d'un PDF en une seule.
|
||||||
pageLayout.tags=fusionner,merge,composite,single-view,organize
|
pageLayout.tags=fusionner,merge,composite,single-view,organize
|
||||||
|
|
||||||
home.scalePages.title=Ajuster l’échelle ou la taille
|
home.scalePages.title=Ajuster l'échelle ou la taille
|
||||||
home.scalePages.desc=Modifiez la taille ou l’échelle d’une page et/ou de son contenu.
|
home.scalePages.desc=Modifiez la taille ou l'échelle d'une page et/ou de son contenu.
|
||||||
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
|
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Pipeline
|
home.pipeline.title=Pipeline
|
||||||
@@ -415,7 +417,7 @@ home.auto-rename.desc=Renommez automatiquement un fichier PDF en fonction de son
|
|||||||
auto-rename.tags=renommer,détection automatique,réétiqueter,auto-detect,header-based,organize,relabel
|
auto-rename.tags=renommer,détection automatique,réétiqueter,auto-detect,header-based,organize,relabel
|
||||||
|
|
||||||
home.adjust-contrast.title=Ajuster les couleurs
|
home.adjust-contrast.title=Ajuster les couleurs
|
||||||
home.adjust-contrast.desc=Ajustez le contraste, la saturation et la luminosité d’un PDF.
|
home.adjust-contrast.desc=Ajustez le contraste, la saturation et la luminosité d'un PDF.
|
||||||
adjust-contrast.tags=ajuster,couleurs,amélioration,color-correction,tune,modify,enhance
|
adjust-contrast.tags=ajuster,couleurs,amélioration,color-correction,tune,modify,enhance
|
||||||
|
|
||||||
home.crop.title=Redimensionner
|
home.crop.title=Redimensionner
|
||||||
@@ -431,16 +433,16 @@ home.sanitizePdf.desc=Supprimez les scripts et autres éléments des PDF.
|
|||||||
sanitizePdf.tags=assainir,sécurisé,clean,secure,safe,remove-threats
|
sanitizePdf.tags=assainir,sécurisé,clean,secure,safe,remove-threats
|
||||||
|
|
||||||
home.URLToPDF.title=URL en PDF
|
home.URLToPDF.title=URL en PDF
|
||||||
home.URLToPDF.desc=Convertissez n’importe quelle URL http(s) en PDF.
|
home.URLToPDF.desc=Convertissez n'importe quelle URL http(s) en PDF.
|
||||||
URLToPDF.tags=pdf,contenu Web,save-page,web-to-doc,archive
|
URLToPDF.tags=pdf,contenu Web,save-page,web-to-doc,archive
|
||||||
|
|
||||||
home.HTMLToPDF.title=HTML en PDF
|
home.HTMLToPDF.title=HTML en PDF
|
||||||
home.HTMLToPDF.desc=Convertissez n’importe quel fichier HTML ou ZIP en PDF.
|
home.HTMLToPDF.desc=Convertissez n'importe quel fichier HTML ou ZIP en PDF.
|
||||||
HTMLToPDF.tags=html,markup,contenu Web,transformation,convert
|
HTMLToPDF.tags=html,markup,contenu Web,transformation,convert
|
||||||
|
|
||||||
|
|
||||||
home.MarkdownToPDF.title=Markdown en PDF
|
home.MarkdownToPDF.title=Markdown en PDF
|
||||||
home.MarkdownToPDF.desc=Convertissez n’importe quel fichier Markdown en PDF.
|
home.MarkdownToPDF.desc=Convertissez n'importe quel fichier Markdown en PDF.
|
||||||
MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert
|
MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert
|
||||||
|
|
||||||
|
|
||||||
@@ -464,11 +466,11 @@ home.showJS.desc=Recherche et affiche tout JavaScript injecté dans un PDF.
|
|||||||
showJS.tags=JS
|
showJS.tags=JS
|
||||||
|
|
||||||
home.autoRedact.title=Caviarder automatiquement
|
home.autoRedact.title=Caviarder automatiquement
|
||||||
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d’un PDF.
|
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d'un PDF.
|
||||||
autoRedact.tags=caviarder,redact,auto
|
autoRedact.tags=caviarder,redact,auto
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF en CSV
|
home.tableExtraxt.title=PDF en CSV
|
||||||
home.tableExtraxt.desc=Extrait les tableaux d’un PDF et les transforme en CSV.
|
home.tableExtraxt.desc=Extrait les tableaux d'un PDF et les transforme en CSV.
|
||||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||||
|
|
||||||
|
|
||||||
@@ -478,15 +480,15 @@ autoSizeSplitPDF.tags=pdf,split,document,organization
|
|||||||
|
|
||||||
|
|
||||||
home.overlay-pdfs.title=Incrustation de PDF
|
home.overlay-pdfs.title=Incrustation de PDF
|
||||||
home.overlay-pdfs.desc=Incrustation d’un PDF sur un autre PDF.
|
home.overlay-pdfs.desc=Incrustation d'un PDF sur un autre PDF.
|
||||||
overlay-pdfs.tags=Overlay,incrustation
|
overlay-pdfs.tags=Overlay,incrustation
|
||||||
|
|
||||||
home.split-by-sections.title=Séparer un PDF en sections
|
home.split-by-sections.title=Séparer un PDF en sections
|
||||||
home.split-by-sections.desc=Diviser chaque page d’un PDF en sections horizontales/verticales plus petites.
|
home.split-by-sections.desc=Diviser chaque page d'un PDF en sections horizontales/verticales plus petites.
|
||||||
split-by-sections.tags=Sections,Diviser,Section Split, Divide, Customize
|
split-by-sections.tags=Sections,Diviser,Section Split, Divide, Customize
|
||||||
|
|
||||||
home.AddStampRequest.title=Ajouter un tampon sur un PDF
|
home.AddStampRequest.title=Ajouter un tampon sur un PDF
|
||||||
home.AddStampRequest.desc=Ajouter un texte ou l’image d’un tampon à un emplacement défini.
|
home.AddStampRequest.desc=Ajouter un texte ou l'image d'un tampon à un emplacement défini.
|
||||||
AddStampRequest.tags=Tampon,Ajouter,Stamp,Add image,center image,Watermark,PDF,Embed,Customize
|
AddStampRequest.tags=Tampon,Ajouter,Stamp,Add image,center image,Watermark,PDF,Embed,Customize
|
||||||
|
|
||||||
|
|
||||||
@@ -498,33 +500,33 @@ home.BookToPDF.title=eBook vers PDF
|
|||||||
home.BookToPDF.desc=Convertit les formats de livres/bandes dessinées en PDF à l'aide de calibre
|
home.BookToPDF.desc=Convertit les formats de livres/bandes dessinées en PDF à l'aide de calibre
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Remove image
|
home.removeImagePdf.title=Supprimer les images
|
||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Supprimez les images d'un PDF pour réduire sa taille
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Images,Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=Séparer un PDF par chapitres
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Séparez un PDF en fichiers multiples en fonction de sa structure par chapitres.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=séparer,chapitres,split,chapters,bookmarks,organize
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Remplacer-Inverser-Couleur
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Remplacer-Inverser Couleur PDF
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Remplacer et Inverser Couleur
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Remplacer la couleur pour le texte et l'arrière-plan dans le PDF et inverser la couleur complète du PDF pour réduire la taille du fichier
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Remplacer Couleur,Opérations de Page,Back-end,Côté serveur
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Options de Remplacement ou d'Inversion de Couleur
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=Par défaut (Couleurs à fort contraste par défaut)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=Personnalisé (Couleurs personnalisées)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Inversion complète (Inverser toutes les couleurs)
|
||||||
replace-color.selectText.5=High contrast color options
|
replace-color.selectText.5=Options de couleur à fort contraste
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=Texte blanc sur fond noir
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=Texte noir sur fond blanc
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=Texte jaune sur fond noir
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=Texte vert sur fond noir
|
||||||
replace-color.selectText.10=Choose text Color
|
replace-color.selectText.10=Choisir la couleur du texte
|
||||||
replace-color.selectText.11=Choose background Color
|
replace-color.selectText.11=Choisir la couleur de l'arrière-plan
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Remplacer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -538,7 +540,7 @@ login.title=Connexion
|
|||||||
login.header=Connexion
|
login.header=Connexion
|
||||||
login.signin=Connexion
|
login.signin=Connexion
|
||||||
login.rememberme=Se souvenir de moi
|
login.rememberme=Se souvenir de moi
|
||||||
login.invalid=Nom d’utilisateur ou mot de passe invalide.
|
login.invalid=Nom d'utilisateur ou mot de passe invalide.
|
||||||
login.locked=Votre compte a été verrouillé.
|
login.locked=Votre compte a été verrouillé.
|
||||||
login.signinTitle=Veuillez vous connecter
|
login.signinTitle=Veuillez vous connecter
|
||||||
login.ssoSignIn=Se connecter via l'authentification unique
|
login.ssoSignIn=Se connecter via l'authentification unique
|
||||||
@@ -550,11 +552,10 @@ login.oauth2invalidRequest=Requête invalide
|
|||||||
login.oauth2AccessDenied=Accès refusé
|
login.oauth2AccessDenied=Accès refusé
|
||||||
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
|
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
|
||||||
login.oauth2InvalidIdToken=Jeton d'identification invalide
|
login.oauth2InvalidIdToken=Jeton d'identification invalide
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=L'utilisateur est désactivé, la connexion est actuellement bloquée avec ce nom d'utilisateur. Veuillez contacter l'administrateur.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Vous êtes déjà connecté sur
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=appareils. Veuillez vous déconnecter des appareils et réessayer.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Vous avez trop de sessions actives.
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Caviarder automatiquement
|
autoRedact.title=Caviarder automatiquement
|
||||||
@@ -618,15 +619,15 @@ HTMLToPDF.header=HTML en PDF
|
|||||||
HTMLToPDF.help=Accepte les fichiers HTML et les ZIP contenant du HTML, du CSS, des images, etc. (requis).
|
HTMLToPDF.help=Accepte les fichiers HTML et les ZIP contenant du HTML, du CSS, des images, etc. (requis).
|
||||||
HTMLToPDF.submit=Convertir
|
HTMLToPDF.submit=Convertir
|
||||||
HTMLToPDF.credit=Utilise WeasyPrint.
|
HTMLToPDF.credit=Utilise WeasyPrint.
|
||||||
HTMLToPDF.zoom=Niveau de zoom pour l’affichage du site web.
|
HTMLToPDF.zoom=Niveau de zoom pour l'affichage du site web.
|
||||||
HTMLToPDF.pageWidth=Largeur de la page en centimètres. (Vide par défaut)
|
HTMLToPDF.pageWidth=Largeur de la page en centimètres. (Vide par défaut)
|
||||||
HTMLToPDF.pageHeight=Hauteur de la page en centimètres. (Vide par défaut)
|
HTMLToPDF.pageHeight=Hauteur de la page en centimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginTop=Marge supérieure de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginTop=Marge supérieure de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginBottom=Marge inférieure de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginBottom=Marge inférieure de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginLeft=Marge gauche de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginLeft=Marge gauche de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginRight=Marge droite de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginRight=Marge droite de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.printBackground=Restituer l’image de fond des sites web.
|
HTMLToPDF.printBackground=Restituer l'image de fond des sites web.
|
||||||
HTMLToPDF.defaultHeader=Activer l’entête par défaut (Nom et numéro de page)
|
HTMLToPDF.defaultHeader=Activer l'entête par défaut (Nom et numéro de page)
|
||||||
HTMLToPDF.cssMediaType=Modifier le type de média CSS de la page.
|
HTMLToPDF.cssMediaType=Modifier le type de média CSS de la page.
|
||||||
HTMLToPDF.none=Aucun
|
HTMLToPDF.none=Aucun
|
||||||
HTMLToPDF.print=Imprimer
|
HTMLToPDF.print=Imprimer
|
||||||
@@ -704,7 +705,7 @@ autoSplitPDF.header=Séparer automatiquement les pages
|
|||||||
autoSplitPDF.description=Imprimez, insérez, numérisez, téléchargez et laissez-nous séparer automatiquement vos documents. Aucun travail de tri manuel nécessaire.
|
autoSplitPDF.description=Imprimez, insérez, numérisez, téléchargez et laissez-nous séparer automatiquement vos documents. Aucun travail de tri manuel nécessaire.
|
||||||
autoSplitPDF.selectText.1=Imprimez des feuilles de séparation ci-dessous (le mode noir et blanc convient).
|
autoSplitPDF.selectText.1=Imprimez des feuilles de séparation ci-dessous (le mode noir et blanc convient).
|
||||||
autoSplitPDF.selectText.2=Numérisez tous vos documents en une seule fois en insérant les feuilles intercalaires entre eux.
|
autoSplitPDF.selectText.2=Numérisez tous vos documents en une seule fois en insérant les feuilles intercalaires entre eux.
|
||||||
autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Stirling PDF s’occuper du reste.
|
autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Stirling PDF s'occuper du reste.
|
||||||
autoSplitPDF.selectText.4=Les feuilles de séparation sont automatiquement détectées et supprimées, garantissant un document final soigné.
|
autoSplitPDF.selectText.4=Les feuilles de séparation sont automatiquement détectées et supprimées, garantissant un document final soigné.
|
||||||
autoSplitPDF.formPrompt=PDF contenant des feuilles de séparation de Stirling PDF :
|
autoSplitPDF.formPrompt=PDF contenant des feuilles de séparation de Stirling PDF :
|
||||||
autoSplitPDF.duplexMode=Mode recto-verso
|
autoSplitPDF.duplexMode=Mode recto-verso
|
||||||
@@ -726,11 +727,11 @@ pageLayout.submit=Fusionner
|
|||||||
|
|
||||||
|
|
||||||
#scalePages
|
#scalePages
|
||||||
scalePages.title=Ajuster la taille ou l’échelle
|
scalePages.title=Ajuster la taille ou l'échelle
|
||||||
scalePages.header=Ajuster la taille ou l’échelle
|
scalePages.header=Ajuster la taille ou l'échelle
|
||||||
scalePages.pageSize=Taille d’une page du document
|
scalePages.pageSize=Taille d'une page du document
|
||||||
scalePages.keepPageSize=Original Size
|
scalePages.keepPageSize=Original Size
|
||||||
scalePages.scaleFactor=Niveau de zoom (recadrage) d’une page
|
scalePages.scaleFactor=Niveau de zoom (recadrage) d'une page
|
||||||
scalePages.submit=Ajuster
|
scalePages.submit=Ajuster
|
||||||
|
|
||||||
|
|
||||||
@@ -738,10 +739,10 @@ scalePages.submit=Ajuster
|
|||||||
certSign.title=Signer avec un certificat
|
certSign.title=Signer avec un certificat
|
||||||
certSign.header=Signer avec un certificat (Travail en cours)
|
certSign.header=Signer avec un certificat (Travail en cours)
|
||||||
certSign.selectPDF=PDF à signer
|
certSign.selectPDF=PDF à signer
|
||||||
certSign.jksNote=Note: Si votre type de certificat n’est pas listé ci-dessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant l’outil en ligne de commande keytool. Puis choisissez l’option Fichier .jks ci-dessous.
|
certSign.jksNote=Note: Si votre type de certificat n'est pas listé ci-dessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant l'outil en ligne de commande keytool. Puis choisissez l'option Fichier .jks ci-dessous.
|
||||||
certSign.selectKey=Fichier de clé privée (format PKCS#8, peut être .pem ou .der)
|
certSign.selectKey=Fichier de clé privée (format PKCS#8, peut être .pem ou .der)
|
||||||
certSign.selectCert=Fichier de certificat (format X.509, peut être .pem ou .der)
|
certSign.selectCert=Fichier de certificat (format X.509, peut être .pem ou .der)
|
||||||
certSign.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s’il n’est fourni, il doit contenir votre clé privée et votre certificat)
|
certSign.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s'il n'est fourni, il doit contenir votre clé privée et votre certificat)
|
||||||
certSign.selectJKS=Sélectionner votre fichier Java Keystore File (.jks or .keystore):
|
certSign.selectJKS=Sélectionner votre fichier Java Keystore File (.jks or .keystore):
|
||||||
certSign.certType=Type de certificat
|
certSign.certType=Type de certificat
|
||||||
certSign.password=Mot de passe keystore ou clé privée le cas échéant
|
certSign.password=Mot de passe keystore ou clé privée le cas échéant
|
||||||
@@ -753,10 +754,10 @@ certSign.submit=Signer
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Remove Certificate Signature
|
removeCertSign.title=Supprimer la Signature de Certificat
|
||||||
removeCertSign.header=Remove the digital certificate from the PDF
|
removeCertSign.header=Supprimer le certificat numérique du PDF
|
||||||
removeCertSign.selectPDF=Select a PDF file:
|
removeCertSign.selectPDF=Sélectionnez un fichier PDF :
|
||||||
removeCertSign.submit=Remove Signature
|
removeCertSign.submit=Supprimer la Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
@@ -783,18 +784,21 @@ 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=Comparer
|
compare.submit=Comparer
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Livres et BD vers PDF
|
BookToPDF.title=Livres et BD vers PDF
|
||||||
BookToPDF.header=Livre vers PDF
|
BookToPDF.header=Livre vers PDF
|
||||||
BookToPDF.credit=Utiliser Calibre
|
BookToPDF.credit=Utilise Calibre
|
||||||
BookToPDF.submit=Convertir
|
BookToPDF.submit=Convertir
|
||||||
|
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDF vers Livre
|
PDFToBook.title=PDF vers Livre
|
||||||
PDFToBook.header=PDF vers Livre
|
PDFToBook.header=PDF vers Livre
|
||||||
PDFToBook.selectText.1=Format
|
PDFToBook.selectText.1=Format
|
||||||
PDFToBook.credit=Utiliser Calibre
|
PDFToBook.credit=Utilise Calibre
|
||||||
PDFToBook.submit=Convertir
|
PDFToBook.submit=Convertir
|
||||||
|
|
||||||
#sign
|
#sign
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Dessiner une signature
|
|||||||
sign.text=Saisir de texte
|
sign.text=Saisir de texte
|
||||||
sign.clear=Effacer
|
sign.clear=Effacer
|
||||||
sign.add=Ajouter
|
sign.add=Ajouter
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -822,9 +831,9 @@ flatten.submit=Rendre inerte
|
|||||||
|
|
||||||
#ScannerImageSplit
|
#ScannerImageSplit
|
||||||
ScannerImageSplit.selectText.1=Seuil de rotation
|
ScannerImageSplit.selectText.1=Seuil de rotation
|
||||||
ScannerImageSplit.selectText.2=Définit l’angle absolu minimum requis pour la rotation de l’image (par défaut : 10).
|
ScannerImageSplit.selectText.2=Définit l'angle absolu minimum requis pour la rotation de l'image (par défaut : 10).
|
||||||
ScannerImageSplit.selectText.3=Tolérance
|
ScannerImageSplit.selectText.3=Tolérance
|
||||||
ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d’arrière-plan estimée (par défaut : 20).
|
ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d'arrière-plan estimée (par défaut : 20).
|
||||||
ScannerImageSplit.selectText.5=Surface minimale
|
ScannerImageSplit.selectText.5=Surface minimale
|
||||||
ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut : 8 000).
|
ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut : 8 000).
|
||||||
ScannerImageSplit.selectText.7=Surface de contour minimale
|
ScannerImageSplit.selectText.7=Surface de contour minimale
|
||||||
@@ -840,24 +849,24 @@ ocr.header=OCR (Reconnaissance optique de caractères) / Nettoyage des numérisa
|
|||||||
ocr.selectText.1=Langues à détecter dans le PDF (celles listées sont celles actuellement détectées)
|
ocr.selectText.1=Langues à détecter dans le PDF (celles listées sont celles actuellement détectées)
|
||||||
ocr.selectText.2=Produire un fichier texte contenant le texte détecté à côté du PDF
|
ocr.selectText.2=Produire un fichier texte contenant le texte détecté à côté du PDF
|
||||||
ocr.selectText.3=Corriger les pages qui ont été numérisées à un angle oblique en les remettant en place
|
ocr.selectText.3=Corriger les pages qui ont été numérisées à un angle oblique en les remettant en place
|
||||||
ocr.selectText.4=Nettoyer la page afin qu’il soit moins probable que l’OCR trouve du texte dans le bruit de fond, sans modifier la sortie
|
ocr.selectText.4=Nettoyer la page afin qu'il soit moins probable que l'OCR trouve du texte dans le bruit de fond, sans modifier la sortie
|
||||||
ocr.selectText.5=Nettoyer la page afin qu’il soit moins probable que l’OCR trouve du texte dans le bruit de fond, en modifiant la sortie
|
ocr.selectText.5=Nettoyer la page afin qu'il soit moins probable que l'OCR trouve du texte dans le bruit de fond, en modifiant la sortie
|
||||||
ocr.selectText.6=Ignorer les pages contenant du texte interactif, n’analyser que les pages qui sont des images
|
ocr.selectText.6=Ignorer les pages contenant du texte interactif, n'analyser que les pages qui sont des images
|
||||||
ocr.selectText.7=Forcer l’OCR, analyser chaque page et supprimer tous les éléments de texte d’origine
|
ocr.selectText.7=Forcer l'OCR, analyser chaque page et supprimer tous les éléments de texte d'origine
|
||||||
ocr.selectText.8=Normal (génère une erreur si le PDF contient du texte)
|
ocr.selectText.8=Normal (génère une erreur si le PDF contient du texte)
|
||||||
ocr.selectText.9=Paramètres additionnels
|
ocr.selectText.9=Paramètres additionnels
|
||||||
ocr.selectText.10=Mode OCR
|
ocr.selectText.10=Mode OCR
|
||||||
ocr.selectText.11=Supprimer les images après l’OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l’étape de conversion)
|
ocr.selectText.11=Supprimer les images après l'OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l'étape de conversion)
|
||||||
ocr.selectText.12=Type de rendu (avancé)
|
ocr.selectText.12=Type de rendu (avancé)
|
||||||
ocr.help=Veuillez lire cette documentation pour savoir comment utiliser l’OCR pour d’autres langues ou une utilisation hors Docker :
|
ocr.help=Veuillez lire cette documentation pour savoir comment utiliser l'OCR pour d'autres langues ou une utilisation hors Docker :
|
||||||
ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l’OCR.
|
ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l'OCR.
|
||||||
ocr.submit=Traiter
|
ocr.submit=Traiter
|
||||||
|
|
||||||
|
|
||||||
#extractImages
|
#extractImages
|
||||||
extractImages.title=Extraire les images
|
extractImages.title=Extraire les images
|
||||||
extractImages.header=Extraire les images
|
extractImages.header=Extraire les images
|
||||||
extractImages.selectText=Format d’image dans lequel convertir les images extraites
|
extractImages.selectText=Format d'image dans lequel convertir les images extraites
|
||||||
extractImages.allowDuplicates=Save duplicate images
|
extractImages.allowDuplicates=Save duplicate images
|
||||||
extractImages.submit=Extraire
|
extractImages.submit=Extraire
|
||||||
|
|
||||||
@@ -873,10 +882,10 @@ fileToPDF.submit=Convertir
|
|||||||
|
|
||||||
#compress
|
#compress
|
||||||
compress.title=Compresser un PDF
|
compress.title=Compresser un PDF
|
||||||
compress.header=Compresser un PDF (lorsque c’est possible!)
|
compress.header=Compresser un PDF (lorsque c'est possible!)
|
||||||
compress.credit=Ce service utilise Ghostscript pour la compression et l’optimisation des PDF.
|
compress.credit=Ce service utilise Ghostscript pour la compression et l'optimisation des PDF.
|
||||||
compress.selectText.1=Mode manuel – de 1 à 4
|
compress.selectText.1=Mode manuel – de 1 à 4
|
||||||
compress.selectText.2=Niveau d’optimisation
|
compress.selectText.2=Niveau d'optimisation
|
||||||
compress.selectText.3=4 (terrible pour les images textuelles)
|
compress.selectText.3=4 (terrible pour les images textuelles)
|
||||||
compress.selectText.4=Mode automatique – ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
|
compress.selectText.4=Mode automatique – ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
|
||||||
compress.selectText.5=Taille PDF attendue (par exemple, 25 MB, 10,8 MB, 25 KB)
|
compress.selectText.5=Taille PDF attendue (par exemple, 25 MB, 10,8 MB, 25 KB)
|
||||||
@@ -961,9 +970,9 @@ split.submit=Diviser
|
|||||||
imageToPDF.title=Image en PDF
|
imageToPDF.title=Image en PDF
|
||||||
imageToPDF.header=Image en PDF
|
imageToPDF.header=Image en PDF
|
||||||
imageToPDF.submit=Convertir
|
imageToPDF.submit=Convertir
|
||||||
imageToPDF.selectLabel=Options d’ajustement de l’image
|
imageToPDF.selectLabel=Options d'ajustement de l'image
|
||||||
imageToPDF.fillPage=Remplir la page
|
imageToPDF.fillPage=Remplir la page
|
||||||
imageToPDF.fitDocumentToImage=Ajuster la page à l’image
|
imageToPDF.fitDocumentToImage=Ajuster la page à l'image
|
||||||
imageToPDF.maintainAspectRatio=Maintenir les proportions
|
imageToPDF.maintainAspectRatio=Maintenir les proportions
|
||||||
imageToPDF.selectText.2=Rotation automatique du PDF
|
imageToPDF.selectText.2=Rotation automatique du PDF
|
||||||
imageToPDF.selectText.3=Logique multi-fichiers (uniquement activée si vous travaillez avec plusieurs images)
|
imageToPDF.selectText.3=Logique multi-fichiers (uniquement activée si vous travaillez avec plusieurs images)
|
||||||
@@ -974,11 +983,11 @@ imageToPDF.selectText.5=Convertir en PDF séparés
|
|||||||
#pdfToImage
|
#pdfToImage
|
||||||
pdfToImage.title=Image en PDF
|
pdfToImage.title=Image en PDF
|
||||||
pdfToImage.header=Image en PDF
|
pdfToImage.header=Image en PDF
|
||||||
pdfToImage.selectText=Format d’image
|
pdfToImage.selectText=Format d'image
|
||||||
pdfToImage.singleOrMultiple=Type de résultat
|
pdfToImage.singleOrMultiple=Type de résultat
|
||||||
pdfToImage.single=Une seule grande image
|
pdfToImage.single=Une seule grande image
|
||||||
pdfToImage.multi=Plusieurs images
|
pdfToImage.multi=Plusieurs images
|
||||||
pdfToImage.colorType=Type d’impression
|
pdfToImage.colorType=Type d'impression
|
||||||
pdfToImage.color=Couleur
|
pdfToImage.color=Couleur
|
||||||
pdfToImage.grey=Niveaux de gris
|
pdfToImage.grey=Niveaux de gris
|
||||||
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
|
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
|
||||||
@@ -990,21 +999,21 @@ pdfToImage.info=Python is not installed. Required for WebP conversion.
|
|||||||
addPassword.title=Ajouter un mot de passe
|
addPassword.title=Ajouter un mot de passe
|
||||||
addPassword.header=Ajouter un mot de passe
|
addPassword.header=Ajouter un mot de passe
|
||||||
addPassword.selectText.1=PDF à chiffrer
|
addPassword.selectText.1=PDF à chiffrer
|
||||||
addPassword.selectText.2=Mot de passe de l’utilisateur
|
addPassword.selectText.2=Mot de passe de l'utilisateur
|
||||||
addPassword.selectText.3=Longueur de la clé de chiffrement
|
addPassword.selectText.3=Longueur de la clé de chiffrement
|
||||||
addPassword.selectText.4=Les valeurs plus élevées sont plus fortes, mais les valeurs plus faibles ont une meilleure compatibilité.
|
addPassword.selectText.4=Les valeurs plus élevées sont plus fortes, mais les valeurs plus faibles ont une meilleure compatibilité.
|
||||||
addPassword.selectText.5=Autorisations à définir (utilisation recommandée avec le mot de passe du propriétaire)
|
addPassword.selectText.5=Autorisations à définir (utilisation recommandée avec le mot de passe du propriétaire)
|
||||||
addPassword.selectText.6=Empêcher l’assemblage du document
|
addPassword.selectText.6=Empêcher l'assemblage du document
|
||||||
addPassword.selectText.7=Empêcher l’extraction de contenu
|
addPassword.selectText.7=Empêcher l'extraction de contenu
|
||||||
addPassword.selectText.8=Empêcher l’extraction pour l’accessibilité
|
addPassword.selectText.8=Empêcher l'extraction pour l'accessibilité
|
||||||
addPassword.selectText.9=Empêcher de remplir les formulaires
|
addPassword.selectText.9=Empêcher de remplir les formulaires
|
||||||
addPassword.selectText.10=Empêcher la modification
|
addPassword.selectText.10=Empêcher la modification
|
||||||
addPassword.selectText.11=Empêcher la modification des annotations
|
addPassword.selectText.11=Empêcher la modification des annotations
|
||||||
addPassword.selectText.12=Empêcher l’impression
|
addPassword.selectText.12=Empêcher l'impression
|
||||||
addPassword.selectText.13=Empêcher l’impression des différents formats
|
addPassword.selectText.13=Empêcher l'impression des différents formats
|
||||||
addPassword.selectText.14=Mot de passe du propriétaire
|
addPassword.selectText.14=Mot de passe du propriétaire
|
||||||
addPassword.selectText.15=Restreint ce qui peut être fait avec le document une fois qu’il est ouvert (non pris en charge par tous les lecteurs).
|
addPassword.selectText.15=Restreint ce qui peut être fait avec le document une fois qu'il est ouvert (non pris en charge par tous les lecteurs).
|
||||||
addPassword.selectText.16=Restreint l’ouverture du document lui-même.
|
addPassword.selectText.16=Restreint l'ouverture du document lui-même.
|
||||||
addPassword.submit=Chiffrer
|
addPassword.submit=Chiffrer
|
||||||
|
|
||||||
|
|
||||||
@@ -1032,14 +1041,14 @@ permissions.header=Modifier les permissions
|
|||||||
permissions.warning=Attention, pour que ces permissions soient immuables il est recommandé de les paramétrer avec un mot de passe via la page Ajouter un mot de passe.
|
permissions.warning=Attention, pour que ces permissions soient immuables il est recommandé de les paramétrer avec un mot de passe via la page Ajouter un mot de passe.
|
||||||
permissions.selectText.1=Sélectionnez le PDF
|
permissions.selectText.1=Sélectionnez le PDF
|
||||||
permissions.selectText.2=Permissions à définir
|
permissions.selectText.2=Permissions à définir
|
||||||
permissions.selectText.3=Empêcher l’assemblage du document
|
permissions.selectText.3=Empêcher l'assemblage du document
|
||||||
permissions.selectText.4=Empêcher l’extraction de contenu
|
permissions.selectText.4=Empêcher l'extraction de contenu
|
||||||
permissions.selectText.5=Empêcher l’extraction pour l’accessibilité
|
permissions.selectText.5=Empêcher l'extraction pour l'accessibilité
|
||||||
permissions.selectText.6=Empêcher de remplir les formulaires
|
permissions.selectText.6=Empêcher de remplir les formulaires
|
||||||
permissions.selectText.7=Empêcher la modification
|
permissions.selectText.7=Empêcher la modification
|
||||||
permissions.selectText.8=Empêcher la modification des annotations
|
permissions.selectText.8=Empêcher la modification des annotations
|
||||||
permissions.selectText.9=Empêcher l’impression
|
permissions.selectText.9=Empêcher l'impression
|
||||||
permissions.selectText.10=Empêcher l’impression des différents formats
|
permissions.selectText.10=Empêcher l'impression des différents formats
|
||||||
permissions.submit=Modifier
|
permissions.submit=Modifier
|
||||||
|
|
||||||
|
|
||||||
@@ -1064,7 +1073,7 @@ changeMetadata.keywords=Mots clés
|
|||||||
changeMetadata.modDate=Date de modification (yyyy/MM/dd HH:mm:ss)
|
changeMetadata.modDate=Date de modification (yyyy/MM/dd HH:mm:ss)
|
||||||
changeMetadata.producer=Producteur
|
changeMetadata.producer=Producteur
|
||||||
changeMetadata.subject=Sujet
|
changeMetadata.subject=Sujet
|
||||||
changeMetadata.trapped=Recouvrement (technique d’impression)
|
changeMetadata.trapped=Recouvrement (technique d'impression)
|
||||||
changeMetadata.selectText.4=Autres métadonnées
|
changeMetadata.selectText.4=Autres métadonnées
|
||||||
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée
|
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée
|
||||||
changeMetadata.submit=Modifier
|
changeMetadata.submit=Modifier
|
||||||
@@ -1077,7 +1086,7 @@ pdfToPDFA.credit=Ce service utilise ghostscript pour la conversion en PDF/A.
|
|||||||
pdfToPDFA.submit=Convertir
|
pdfToPDFA.submit=Convertir
|
||||||
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
|
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
|
||||||
pdfToPDFA.outputFormat=Format de sortie
|
pdfToPDFA.outputFormat=Format de sortie
|
||||||
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
pdfToPDFA.pdfWithDigitalSignature=Le PDF contient une signature numérique. Elle sera supprimée dans l'étape suivante.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
@@ -1139,13 +1148,13 @@ split-by-size-or-count.submit=Séparer
|
|||||||
overlay-pdfs.header=Incrustation de PDF
|
overlay-pdfs.header=Incrustation de PDF
|
||||||
overlay-pdfs.baseFile.label=Sélectionner le fichier PDF de base
|
overlay-pdfs.baseFile.label=Sélectionner le fichier PDF de base
|
||||||
overlay-pdfs.overlayFiles.label=Sélectionner les fichiers PDF à superposer
|
overlay-pdfs.overlayFiles.label=Sélectionner les fichiers PDF à superposer
|
||||||
overlay-pdfs.mode.label=Sélectionner le mode d’incrustation
|
overlay-pdfs.mode.label=Sélectionner le mode d'incrustation
|
||||||
overlay-pdfs.mode.sequential=Superposition séquentielle
|
overlay-pdfs.mode.sequential=Superposition séquentielle
|
||||||
overlay-pdfs.mode.interleaved=Superposition entrelacée
|
overlay-pdfs.mode.interleaved=Superposition entrelacée
|
||||||
overlay-pdfs.mode.fixedRepeat=Superposition à répétition fixe
|
overlay-pdfs.mode.fixedRepeat=Superposition à répétition fixe
|
||||||
overlay-pdfs.counts.label=Nombre de superpositions (pour le mode de répétition fixe)
|
overlay-pdfs.counts.label=Nombre de superpositions (pour le mode de répétition fixe)
|
||||||
overlay-pdfs.counts.placeholder=Compteurs (séparés par des virgules, exemple : 2,3,1)
|
overlay-pdfs.counts.placeholder=Compteurs (séparés par des virgules, exemple : 2,3,1)
|
||||||
overlay-pdfs.position.label=Définir la position de l’incrustation
|
overlay-pdfs.position.label=Définir la position de l'incrustation
|
||||||
overlay-pdfs.position.foreground=Premier plan
|
overlay-pdfs.position.foreground=Premier plan
|
||||||
overlay-pdfs.position.background=Arrière-plan
|
overlay-pdfs.position.background=Arrière-plan
|
||||||
overlay-pdfs.submit=Soumettre
|
overlay-pdfs.submit=Soumettre
|
||||||
@@ -1179,47 +1188,45 @@ licenses.version=Version
|
|||||||
licenses.license=Licence
|
licenses.license=Licence
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survey
|
survey.nav=Enquête
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Enquête Stirling-PDF
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF n'a pas de suivi, donc nous voulons entendre nos utilisateurs pour améliorer Stirling-PDF !
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
survey.changes=Stirling-PDF a changé depuis la dernière enquête ! Pour en savoir plus, veuillez consulter notre article de blog ici :
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
survey.changes2=Avec ces changements, nous obtenons un soutien commercial rémunéré et un financement
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Veuillez envisager de répondre à notre enquête !
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(La fenêtre contextuelle de l'enquête sera désactivée dans les mises à jour suivantes mais sera disponible en bas de page)
|
||||||
survey.button=Take Survey
|
survey.button=Répondre à l'enquête
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=Ne plus afficher
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
error.sorry=Désolé pour ce problème !
|
error.sorry=Désolé pour ce problème !
|
||||||
error.needHelp=Besoin d’aide / Vous avez trouvé un problème ?
|
error.needHelp=Besoin d'aide / Vous avez trouvé un problème ?
|
||||||
error.contactTip=Si vous avez encore des problèmes, n’hésitez pas à nous contacter pour obtenir de l’aide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord :
|
error.contactTip=Si vous avez encore des problèmes, n'hésitez pas à nous contacter pour obtenir de l'aide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord :
|
||||||
error.404.head=404 - Page non trouvée | oups on s’est foiré !
|
error.404.head=404 - Page non trouvée | oups on s'est foiré !
|
||||||
error.404.1=Nous ne parvenons pas à trouver la page que vous recherchez.
|
error.404.1=Nous ne parvenons pas à trouver la page que vous recherchez.
|
||||||
error.404.2=Quelque chose n’a pas fonctionné
|
error.404.2=Quelque chose n'a pas fonctionné
|
||||||
error.github=Créer un ticket sur GitHub
|
error.github=Créer un ticket sur GitHub
|
||||||
error.showStack=Afficher la Stack Trace
|
error.showStack=Afficher la Stack Trace
|
||||||
error.copyStack=Copier la Stack Trace
|
error.copyStack=Copier la Stack Trace
|
||||||
error.githubSubmit=GitHub - Créer un ticket
|
error.githubSubmit=GitHub - Créer un ticket
|
||||||
error.discordSubmit=Discord - Poster un message de demande d’assistance
|
error.discordSubmit=Discord - Poster un message de demande d'assistance
|
||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Remove image
|
removeImage.title=Supprimer l'image
|
||||||
removeImage.header=Remove image
|
removeImage.header=Supprimer l'image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Supprimer l'image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Supprimer l'image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
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.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.submit=Split PDF
|
|
||||||
|
|
||||||
|
|
||||||
|
splitByChapters.title=Diviser un PDF par Chapitres
|
||||||
|
splitByChapters.header=Diviser un PDF par Chapitres
|
||||||
|
splitByChapters.bookmarkLevel=Niveau de Signet
|
||||||
|
splitByChapters.includeMetadata=Inclure les Métadonnées
|
||||||
|
splitByChapters.allowDuplicates=Autoriser les Doublons
|
||||||
|
splitByChapters.desc.1=Cet outil divise un fichier PDF en plusieurs PDF en fonction de sa structure de chapitres.
|
||||||
|
splitByChapters.desc.2=Niveau de Signet : Choisissez le niveau de signets à utiliser pour la division (0 pour le niveau supérieur, 1 pour le deuxième niveau, etc...).
|
||||||
|
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.submit=Diviser le PDF
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Eolas
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Dath Aibhsithe 2:
|
|||||||
compare.document.1=Doiciméad 1
|
compare.document.1=Doiciméad 1
|
||||||
compare.document.2=Doiciméad 2
|
compare.document.2=Doiciméad 2
|
||||||
compare.submit=Déan comparáid idir
|
compare.submit=Déan comparáid idir
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Leabhair agus comics a PDF
|
BookToPDF.title=Leabhair agus comics a PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Tarraing Síniú
|
|||||||
sign.text=Ionchur Téacs
|
sign.text=Ionchur Téacs
|
||||||
sign.clear=Glan
|
sign.clear=Glan
|
||||||
sign.add=Cuir
|
sign.add=Cuir
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=पृष्ठ
|
page=पृष्ठ
|
||||||
pages=पृष्ठों
|
pages=पृष्ठों
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=स्वत: गोपनीयकरण
|
autoRedact.title=स्वत: गोपनीयकरण
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=दस्तावेज़ 1
|
compare.document.1=दस्तावेज़ 1
|
||||||
compare.document.2=दस्तावेज़ 2
|
compare.document.2=दस्तावेज़ 2
|
||||||
compare.submit=तुलना करें
|
compare.submit=तुलना करें
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=हस्ताक्षर बनाएँ
|
|||||||
sign.text=पाठ इनपुट
|
sign.text=पाठ इनपुट
|
||||||
sign.clear=साफ़ करें
|
sign.clear=साफ़ करें
|
||||||
sign.add=जोड़ें
|
sign.add=जोड़ें
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatsko uređivanje
|
autoRedact.title=Automatsko uređivanje
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Uporedi
|
compare.submit=Uporedi
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Knjige i stripovi u PDF
|
BookToPDF.title=Knjige i stripovi u PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Nacrtaj potpis
|
|||||||
sign.text=Tekstualni unos
|
sign.text=Tekstualni unos
|
||||||
sign.clear=Obriši
|
sign.clear=Obriši
|
||||||
sign.add=Dodaj
|
sign.add=Dodaj
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Érzékeny tartalom eltávolítása
|
autoRedact.title=Érzékeny tartalom eltávolítása
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokumentum 1
|
compare.document.1=Dokumentum 1
|
||||||
compare.document.2=Dokumentum 2
|
compare.document.2=Dokumentum 2
|
||||||
compare.submit=Összehasonlítás
|
compare.submit=Összehasonlítás
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Aláírás rajzolása
|
|||||||
sign.text=Szöveg beírása
|
sign.text=Szöveg beírása
|
||||||
sign.clear=Törlés
|
sign.clear=Törlés
|
||||||
sign.add=Hozzáadás
|
sign.add=Hozzáadás
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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=Font Size
|
addPageNumbers.fontSize=Ukuran Fonta
|
||||||
addPageNumbers.fontName=Font Name
|
addPageNumbers.fontName=Nama Fonta
|
||||||
pdfPrompt=Pilih PDF
|
pdfPrompt=Pilih PDF
|
||||||
multiPdfPrompt=Pilih PDF (2+)
|
multiPdfPrompt=Pilih PDF (2+)
|
||||||
multiPdfDropPrompt=Pilih (atau seret & letakkan)) semua PDF yang Anda butuhkan
|
multiPdfDropPrompt=Pilih (atau seret & letakkan)) semua PDF yang Anda butuhkan
|
||||||
@@ -12,17 +12,17 @@ imgPrompt=Pilih Gambar
|
|||||||
genericSubmit=Kirim
|
genericSubmit=Kirim
|
||||||
processTimeWarning=Peringatan: Proses ini dapat memakan waktu hingga satu menit, tergantung pada ukuran berkas
|
processTimeWarning=Peringatan: Proses ini dapat memakan waktu hingga satu menit, tergantung pada ukuran berkas
|
||||||
pageOrderPrompt=Urutan Halaman Khusus (Masukkan daftar nomor halaman yang dipisahkan dengan koma atau Fungsi seperti 2n + 1) :
|
pageOrderPrompt=Urutan Halaman Khusus (Masukkan daftar nomor halaman yang dipisahkan dengan koma atau Fungsi seperti 2n + 1) :
|
||||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
pageSelectionPrompt=Pemilihan Halaman Kustom (Masukkan daftar nomor halaman dipisahkan dengan koma 1,5,6 atau Fungsi seperti 2n+1) :
|
||||||
goToPage=Ke
|
goToPage=Ke
|
||||||
true=Benar
|
true=Benar
|
||||||
false=Salah
|
false=Salah
|
||||||
unknown=Tidak diketahui
|
unknown=Tidak diketahui
|
||||||
save=Simpan
|
save=Simpan
|
||||||
saveToBrowser=Save to Browser
|
saveToBrowser=Simpan ke Peramban
|
||||||
close=Tutup
|
close=Tutup
|
||||||
filesSelected=berkas dipilih
|
filesSelected=berkas dipilih
|
||||||
noFavourites=Tidak ada favorit yang ditambahkan
|
noFavourites=Tidak ada favorit yang ditambahkan
|
||||||
downloadComplete=Download Complete
|
downloadComplete=Unduhan Lengkap
|
||||||
bored=Bosan Menunggu?
|
bored=Bosan Menunggu?
|
||||||
alphabet=Abjad
|
alphabet=Abjad
|
||||||
downloadPdf=Unduh PDF
|
downloadPdf=Unduh PDF
|
||||||
@@ -46,113 +46,115 @@ red=Merah
|
|||||||
green=Hijau
|
green=Hijau
|
||||||
blue=Biru
|
blue=Biru
|
||||||
custom=Kustom...
|
custom=Kustom...
|
||||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
WorkInProgess=Pekerjaan sedang diproses, Mungkin tidak berfungsi atau terdapat kutu, Silakan laporkan masalah apa pun!
|
||||||
poweredBy=Powered by
|
poweredBy=Ditenagai oleh
|
||||||
yes=Yes
|
yes=Ya
|
||||||
no=No
|
no=Tidak
|
||||||
changedCredsMessage=Kredensial berubah!!
|
changedCredsMessage=Kredensial berubah!!
|
||||||
notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
|
notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
|
||||||
userNotFoundMessage=Pengguna tidak ditemukan.
|
userNotFoundMessage=Pengguna tidak ditemukan.
|
||||||
incorrectPasswordMessage=Kata sandi saat ini salah.
|
incorrectPasswordMessage=Kata sandi saat ini salah.
|
||||||
usernameExistsMessage=Nama pengguna baru sudah ada.
|
usernameExistsMessage=Nama pengguna baru sudah ada.
|
||||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
invalidUsernameMessage=Nama pengguna tidak valid, nama pengguna hanya boleh mengandung huruf, angka, dan karakter khusus berikut @._+- atau harus berupa alamat email yang valid.
|
||||||
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
invalidPasswordMessage=Kata sandi tidak boleh kosong dan tidak boleh memiliki spasi di awal atau akhir.
|
||||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
confirmPasswordErrorMessage=Kata Sandi Baru dan Konfirmasi Kata Sandi Baru harus sama.
|
||||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
deleteCurrentUserMessage=Pengguna yang sedang masuk tidak dapat dihapus.
|
||||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
deleteUsernameExistsMessage=Nama pengguna tidak ada dan tidak dapat dihapus.
|
||||||
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
|
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
|
||||||
disabledCurrentUserMessage=The current user cannot be disabled
|
disabledCurrentUserMessage=Pengguna saat ini tidak dapat dinonaktifkan
|
||||||
downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
|
downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
|
||||||
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
|
userAlreadyExistsOAuthMessage=Pengguna sudah ada sebagai pengguna OAuth2.
|
||||||
userAlreadyExistsWebMessage=The user already exists as an web user.
|
userAlreadyExistsWebMessage=Pengguna sudah ada sebagai pengguna web.
|
||||||
error=Error
|
error=Kesalahan
|
||||||
oops=Oops!
|
oops=Ups!
|
||||||
help=Help
|
help=Bantuan
|
||||||
goHomepage=Go to Homepage
|
goHomepage=Kembali ke Beranda
|
||||||
joinDiscord=Join our Discord server
|
joinDiscord=Bergabung dengan server Discord kami
|
||||||
seeDockerHub=See Docker Hub
|
seeDockerHub=Lihat Docker Hub
|
||||||
visitGithub=Visit Github Repository
|
visitGithub=Kunjungi Repositori Github
|
||||||
donate=Donate
|
donate=Donasi
|
||||||
color=Color
|
color=Warna
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Halaman
|
||||||
pages=Pages
|
pages=Halaman-halaman
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Kebijakan Privasi
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Syarat dan Ketentuan
|
||||||
legal.accessibility=Accessibility
|
legal.accessibility=Aksesibilitas
|
||||||
legal.cookie=Cookie Policy
|
legal.cookie=Kebijakan Kuki
|
||||||
legal.impressum=Impressum
|
legal.impressum=Impresum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=Pipeline Menu (Beta)
|
pipeline.header=Menu Pipeline (Beta)
|
||||||
pipeline.uploadButton=Upload Custom
|
pipeline.uploadButton=Unggah Kustom
|
||||||
pipeline.configureButton=Configure
|
pipeline.configureButton=Konfigurasi
|
||||||
pipeline.defaultOption=Custom
|
pipeline.defaultOption=Kustom
|
||||||
pipeline.submitButton=Submit
|
pipeline.submitButton=Kirim
|
||||||
pipeline.help=Pipeline Help
|
pipeline.help=Bantuan Pipeline
|
||||||
pipeline.scanHelp=Folder Scanning Help
|
pipeline.scanHelp=Bantuan Pemindaian Folder
|
||||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
pipeline.deletePrompt=Apakah Anda yakin ingin menghapus pipeline
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
######################
|
######################
|
||||||
pipelineOptions.header=Pipeline Configuration
|
pipelineOptions.header=Konfigurasi Pipeline
|
||||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
pipelineOptions.pipelineNameLabel=Nama Pipeline
|
||||||
pipelineOptions.saveSettings=Save Operation Settings
|
pipelineOptions.saveSettings=Simpan Pengaturan Operasi
|
||||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
pipelineOptions.pipelineNamePrompt=Masukkan nama pipeline di sini
|
||||||
pipelineOptions.selectOperation=Select Operation
|
pipelineOptions.selectOperation=Pilih Operasi
|
||||||
pipelineOptions.addOperationButton=Add operation
|
pipelineOptions.addOperationButton=Tambah operasi
|
||||||
pipelineOptions.pipelineHeader=Pipeline:
|
pipelineOptions.pipelineHeader=Pipeline:
|
||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Unduh
|
||||||
pipelineOptions.validateButton=Validate
|
pipelineOptions.validateButton=Validasi
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Upgrade ke Pro
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Fitur ini hanya tersedia untuk pengguna Pro.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro mendukung berkas konfigurasi YAML dan fitur SSO lainnya.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Mencari lebih banyak fitur manajemen pengguna? Lihat Stirling PDF Pro
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=Apakah Anda ingin membuat Stirling PDF lebih baik?
|
||||||
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.paragraph1=Stirling PDF memiliki analitik yang dapat diaktifkan untuk membantu kami meningkatkan produk. Kami tidak melacak informasi pribadi atau konten berkas.
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Silakan pertimbangkan untuk mengaktifkan analitik agar Stirling PDF dapat berkembang dan untuk memungkinkan kami memahami pengguna kami dengan lebih baik.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Aktifkan analitik
|
||||||
analytics.disable=Disable analytics
|
analytics.disable=Nonaktifkan analitik
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
analytics.settings=Anda dapat mengubah pengaturan untuk analitik di berkas config/settings.yml
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
#############
|
#############
|
||||||
navbar.favorite=Favorites
|
navbar.favorite=Favorit
|
||||||
navbar.darkmode=Mode Gelap
|
navbar.darkmode=Mode Gelap
|
||||||
navbar.language=Languages
|
navbar.language=Bahasa
|
||||||
navbar.settings=Pengaturan
|
navbar.settings=Pengaturan
|
||||||
navbar.allTools=Tools
|
navbar.allTools=Alat
|
||||||
navbar.multiTool=Multi Tools
|
navbar.multiTool=Alat Multi
|
||||||
navbar.sections.organize=Organize
|
navbar.sections.organize=Atur
|
||||||
navbar.sections.convertTo=Convert to PDF
|
navbar.sections.convertTo=Konversi ke PDF
|
||||||
navbar.sections.convertFrom=Convert from PDF
|
navbar.sections.convertFrom=Konversi dari PDF
|
||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Tanda Tangan & Keamanan
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Langkah Lanjut
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=Melihat & Mengedit
|
||||||
navbar.sections.popular=Popular
|
navbar.sections.popular=Populer
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
#############
|
#############
|
||||||
settings.title=Pengaturan
|
settings.title=Pengaturan
|
||||||
settings.update=Pembaruan tersedia
|
settings.update=Pembaruan tersedia
|
||||||
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
|
settings.updateAvailable={0} adalah versi yang terpasang saat ini. Versi baru ({1}) tersedia.
|
||||||
settings.appVersion=Versi Aplikasi:
|
settings.appVersion=Versi Aplikasi:
|
||||||
settings.downloadOption.title=Pilih opsi unduhan (Untuk unduhan berkas tunggal non zip):
|
settings.downloadOption.title=Pilih opsi unduhan (Untuk unduhan berkas tunggal non zip):
|
||||||
settings.downloadOption.1=Buka di jendela yang sama
|
settings.downloadOption.1=Buka di jendela yang sama
|
||||||
@@ -161,13 +163,13 @@ settings.downloadOption.3=Unduh berkas
|
|||||||
settings.zipThreshold=Berkas zip ketika jumlah berkas yang diunduh melebihi
|
settings.zipThreshold=Berkas zip ketika jumlah berkas yang diunduh melebihi
|
||||||
settings.signOut=Keluar
|
settings.signOut=Keluar
|
||||||
settings.accountSettings=Pengaturan Akun
|
settings.accountSettings=Pengaturan Akun
|
||||||
settings.bored.help=Enables easter egg game
|
settings.bored.help=Mengaktifkan permainan telur paskah
|
||||||
settings.cacheInputs.name=Save form inputs
|
settings.cacheInputs.name=Simpan input formulir
|
||||||
settings.cacheInputs.help=Enable to store previously used inputs for future runs
|
settings.cacheInputs.help=Aktifkan untuk menyimpan input yang pernah digunakan untuk menjalankan di masa depan
|
||||||
|
|
||||||
changeCreds.title=Ubah Kredensial
|
changeCreds.title=Ubah Kredensial
|
||||||
changeCreds.header=Perbarui Detail Akun Anda
|
changeCreds.header=Perbarui Detail Akun Anda
|
||||||
changeCreds.changePassword=You are using default login credentials. Please enter a new password
|
changeCreds.changePassword=Anda menggunakan kredensial login default. Silakan masukkan kata sandi baru
|
||||||
changeCreds.newUsername=Nama Pengguna Baru
|
changeCreds.newUsername=Nama Pengguna Baru
|
||||||
changeCreds.oldPassword=Kata Sandi Saat Ini
|
changeCreds.oldPassword=Kata Sandi Saat Ini
|
||||||
changeCreds.newPassword=Kata Sandi Baru
|
changeCreds.newPassword=Kata Sandi Baru
|
||||||
@@ -202,48 +204,48 @@ adminUserSettings.header=Pengaturan Kontrol Admin
|
|||||||
adminUserSettings.admin=Admin
|
adminUserSettings.admin=Admin
|
||||||
adminUserSettings.user=Pengguna
|
adminUserSettings.user=Pengguna
|
||||||
adminUserSettings.addUser=Tambahkan Pengguna Baru
|
adminUserSettings.addUser=Tambahkan Pengguna Baru
|
||||||
adminUserSettings.deleteUser=Delete User
|
adminUserSettings.deleteUser=Hapus Pengguna
|
||||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
adminUserSettings.confirmDeleteUser=Haruskah pengguna dihapus?
|
||||||
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
adminUserSettings.confirmChangeUserStatus=Haruskah pengguna dinonaktifkan/diaktifkan?
|
||||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
adminUserSettings.usernameInfo=Nama pengguna hanya boleh mengandung huruf, angka, dan karakter khusus berikut @._+- atau harus berupa alamat email yang valid.
|
||||||
adminUserSettings.roles=Peran
|
adminUserSettings.roles=Peran
|
||||||
adminUserSettings.role=Peran
|
adminUserSettings.role=Peran
|
||||||
adminUserSettings.actions=Tindakan
|
adminUserSettings.actions=Tindakan
|
||||||
adminUserSettings.apiUser=Pengguna API Terbatas
|
adminUserSettings.apiUser=Pengguna API Terbatas
|
||||||
adminUserSettings.extraApiUser=Additional Limited API User
|
adminUserSettings.extraApiUser=Additional Limited API User
|
||||||
adminUserSettings.webOnlyUser=Pengguna Khusus Web
|
adminUserSettings.webOnlyUser=Pengguna Khusus Web
|
||||||
adminUserSettings.demoUser=Demo User (No custom settings)
|
adminUserSettings.demoUser=Pengguna Demo (Tanpa pengaturan kustom)
|
||||||
adminUserSettings.internalApiUser=Internal API User
|
adminUserSettings.internalApiUser=Pengguna API Internal
|
||||||
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
|
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
|
||||||
adminUserSettings.submit=Simpan Pengguna
|
adminUserSettings.submit=Simpan Pengguna
|
||||||
adminUserSettings.changeUserRole=Ubah Peran Pengguna
|
adminUserSettings.changeUserRole=Ubah Peran Pengguna
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Terautentikasi
|
||||||
adminUserSettings.editOwnProfil=Edit own profile
|
adminUserSettings.editOwnProfil=Edit profil sendiri
|
||||||
adminUserSettings.enabledUser=enabled user
|
adminUserSettings.enabledUser=Pengguna diaktifkan
|
||||||
adminUserSettings.disabledUser=disabled user
|
adminUserSettings.disabledUser=Pengguna dinonaktifkan
|
||||||
adminUserSettings.activeUsers=Active Users:
|
adminUserSettings.activeUsers=Pengguna Aktif:
|
||||||
adminUserSettings.disabledUsers=Disabled Users:
|
adminUserSettings.disabledUsers=Pengguna Dinonaktifkan:
|
||||||
adminUserSettings.totalUsers=Total Users:
|
adminUserSettings.totalUsers=Total Pengguna:
|
||||||
adminUserSettings.lastRequest=Last Request
|
adminUserSettings.lastRequest=Permintaan Terakhir
|
||||||
|
|
||||||
|
|
||||||
database.title=Database Import/Export
|
database.title=Impor/Ekspor Database
|
||||||
database.header=Database Import/Export
|
database.header=Impor/Ekspor Database
|
||||||
database.fileName=File Name
|
database.fileName=Nama Berkas
|
||||||
database.creationDate=Creation Date
|
database.creationDate=Tanggal Pembuatan
|
||||||
database.fileSize=File Size
|
database.fileSize=Ukuran Berkas
|
||||||
database.deleteBackupFile=Delete Backup File
|
database.deleteBackupFile=Hapus Berkas Cadangan
|
||||||
database.importBackupFile=Import Backup File
|
database.importBackupFile=Impor Berkas Cadangan
|
||||||
database.downloadBackupFile=Download Backup File
|
database.downloadBackupFile=Unduh Berkas Cadangan
|
||||||
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
database.info_1=Ketika mengimpor data, sangat penting untuk memastikan struktur yang benar. Jika Anda tidak yakin dengan apa yang Anda lakukan, cari nasihat dan dukungan dari seorang profesional. Kesalahan dalam struktur dapat menyebabkan malfungsi aplikasi, bahkan hingga tidak dapat menjalankan aplikasi sama sekali.
|
||||||
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
database.info_2=Nama berkas tidak menjadi masalah saat mengunggah. Nama berkas akan diubah setelahnya mengikuti format backup_user_yyyyMMddHHmm.sql, memastikan konsistensi dalam penamaan.
|
||||||
database.submit=Import Backup
|
database.submit=Impor Cadangan
|
||||||
database.importIntoDatabaseSuccessed=Import into database successed
|
database.importIntoDatabaseSuccessed=Impor ke database berhasil
|
||||||
database.fileNotFound=File not Found
|
database.fileNotFound=Berkas tidak Ditemukan
|
||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=Berkas tidak boleh null atau kosong
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Impor Berkas Gagal
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
session.expired=Sesi Anda telah kedaluwarsa. Silakan muat ulang halaman dan coba lagi.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -313,7 +315,7 @@ removePassword.tags=aman,Dekripsi,keamanan,buka kata sandi,hapus kata sandi
|
|||||||
|
|
||||||
home.compressPdfs.title=Kompres
|
home.compressPdfs.title=Kompres
|
||||||
home.compressPdfs.desc=Kompres PDF untuk mengurangi ukuran berkas.
|
home.compressPdfs.desc=Kompres PDF untuk mengurangi ukuran berkas.
|
||||||
compressPdfs.tags=squish, kecil, kecil
|
compressPdfs.tags=remas, kecil, mini
|
||||||
|
|
||||||
|
|
||||||
home.changeMetadata.title=Ubah Metadata
|
home.changeMetadata.title=Ubah Metadata
|
||||||
@@ -490,41 +492,41 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
|
|||||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF to Book
|
home.PDFToBook.title=PDF ke Buku
|
||||||
home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
|
home.PDFToBook.desc=Mengonversi PDF ke format Buku/Komik menggunakan calibre
|
||||||
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
PDFToBook.tags=Buku,Komik,Calibre,Konversi,manga,amazon,kindle
|
||||||
|
|
||||||
home.BookToPDF.title=Book to PDF
|
home.BookToPDF.title=Buku ke PDF
|
||||||
home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
|
home.BookToPDF.desc=Mengonversi format Buku/Komik ke PDF menggunakan calibre
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
BookToPDF.tags=Buku,Komik,Calibre,Konversi,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Remove image
|
home.removeImagePdf.title=Hapus Gambar
|
||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Hapus gambar dari PDF untuk mengurangi ukuran file
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Hapus Gambar,Operasi Halaman,Backend,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=Pisahkan PDF berdasarkan Bab
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Memisahkan PDF menjadi beberapa file berdasarkan struktur babnya.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=pemisahan,bab,bookmark,atur
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Ganti-Inversi-Warna
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Ganti-Inversi Warna PDF
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Ganti dan Inversi Warna
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Ganti warna untuk teks dan latar belakang dalam PDF dan inversi seluruh warna PDF untuk mengurangi ukuran file
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Ganti Warna,Operasi Halaman,Backend,server side
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Opsi Ganti atau Inversi warna
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=Default(Warna kontras tinggi default)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=Kustom(Warna yang disesuaikan)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Full-Inversi(Inversi semua warna)
|
||||||
replace-color.selectText.5=High contrast color options
|
replace-color.selectText.5=Opsi warna kontras tinggi
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=teks putih di latar belakang hitam
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=teks hitam di latar belakang putih
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=teks kuning di latar belakang hitam
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=teks hijau di latar belakang hitam
|
||||||
replace-color.selectText.10=Choose text Color
|
replace-color.selectText.10=Pilih warna teks
|
||||||
replace-color.selectText.11=Choose background Color
|
replace-color.selectText.11=Pilih warna latar belakang
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Ganti
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -543,18 +545,17 @@ login.locked=Akun Anda telah dikunci.
|
|||||||
login.signinTitle=Silakan masuk
|
login.signinTitle=Silakan masuk
|
||||||
login.ssoSignIn=Masuk melalui Single Sign - on
|
login.ssoSignIn=Masuk melalui Single Sign - on
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
|
login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
|
||||||
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
login.oauth2AdminBlockedUser=Registrasi atau login pengguna yang tidak terdaftar saat ini diblokir. Silakan hubungi administrator.
|
||||||
login.oauth2RequestNotFound=Authorization request not found
|
login.oauth2RequestNotFound=Permintaan otorisasi tidak ditemukan
|
||||||
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
login.oauth2InvalidUserInfoResponse=Respons Info Pengguna Tidak Valid
|
||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Permintaan Tidak Valid
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Akses Ditolak
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Respons Token Tidak Valid
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Token ID Tidak Valid
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=Pengguna dinonaktifkan, login saat ini diblokir dengan nama pengguna ini. Silakan hubungi administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Anda sudah login ke
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=perangkat. Silakan keluar dari perangkat dan coba lagi.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Anda memiliki terlalu banyak sesi aktif
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redaksional Otomatis
|
autoRedact.title=Redaksional Otomatis
|
||||||
@@ -618,37 +619,37 @@ HTMLToPDF.header=HTML Ke PDF
|
|||||||
HTMLToPDF.help=Menerima berkas HTML dan ZIP yang berisi html / css / gambar, dll yang diperlukan
|
HTMLToPDF.help=Menerima berkas HTML dan ZIP yang berisi html / css / gambar, dll yang diperlukan
|
||||||
HTMLToPDF.submit=Konversi
|
HTMLToPDF.submit=Konversi
|
||||||
HTMLToPDF.credit=Menggunakan WeasyPrint
|
HTMLToPDF.credit=Menggunakan WeasyPrint
|
||||||
HTMLToPDF.zoom=Zoom level for displaying the website.
|
HTMLToPDF.zoom=Tingkat perbersan untuk menampilkan situs web.
|
||||||
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
|
HTMLToPDF.pageWidth=Lebar halaman dalam sentimeter. (Kosong untuk default)
|
||||||
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
|
HTMLToPDF.pageHeight=Tinggi halaman dalam sentimeter. (Kosong untuk default)
|
||||||
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
|
HTMLToPDF.marginTop=Margin atas halaman dalam milimeter. (Kosong untuk default)
|
||||||
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
|
HTMLToPDF.marginBottom=Margin bawah halaman dalam milimeter. (Kosong untuk default)
|
||||||
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
|
HTMLToPDF.marginLeft=Margin kiri halaman dalam milimeter. (Kosong untuk default)
|
||||||
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
|
HTMLToPDF.marginRight=Margin kanan halaman dalam milimeter. (Kosong untuk default)
|
||||||
HTMLToPDF.printBackground=Render the background of websites.
|
HTMLToPDF.printBackground=Render latar belakang situs web.
|
||||||
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
|
HTMLToPDF.defaultHeader=Aktifkan Header Default (Nama dan nomor halaman)
|
||||||
HTMLToPDF.cssMediaType=Change the CSS media type of the page.
|
HTMLToPDF.cssMediaType=Ubah jenis media CSS halaman.
|
||||||
HTMLToPDF.none=None
|
HTMLToPDF.none=Tidak ada
|
||||||
HTMLToPDF.print=Print
|
HTMLToPDF.print=Cetak
|
||||||
HTMLToPDF.screen=Screen
|
HTMLToPDF.screen=Layar
|
||||||
|
|
||||||
|
|
||||||
#AddStampRequest
|
#AddStampRequest
|
||||||
AddStampRequest.header=Stamp PDF
|
AddStampRequest.header=Stampel PDF
|
||||||
AddStampRequest.title=Stamp PDF
|
AddStampRequest.title=Stampel PDF
|
||||||
AddStampRequest.stampType=Stamp Type
|
AddStampRequest.stampType=Jenis Stampel
|
||||||
AddStampRequest.stampText=Stamp Text
|
AddStampRequest.stampText=Teks Stampel
|
||||||
AddStampRequest.stampImage=Stamp Image
|
AddStampRequest.stampImage=Gambar Stampel
|
||||||
AddStampRequest.alphabet=Alphabet
|
AddStampRequest.alphabet=Alfabet
|
||||||
AddStampRequest.fontSize=Font/Image Size
|
AddStampRequest.fontSize=Ukuran Font/Gambar
|
||||||
AddStampRequest.rotation=Rotation
|
AddStampRequest.rotation=Rotasi
|
||||||
AddStampRequest.opacity=Opacity
|
AddStampRequest.opacity=Transparansi
|
||||||
AddStampRequest.position=Position
|
AddStampRequest.position=Posisi
|
||||||
AddStampRequest.overrideX=Override X Coordinate
|
AddStampRequest.overrideX=Timpa Koordinat X
|
||||||
AddStampRequest.overrideY=Override Y Coordinate
|
AddStampRequest.overrideY=Timpa Koordinat Y
|
||||||
AddStampRequest.customMargin=Custom Margin
|
AddStampRequest.customMargin=Margin Kustom
|
||||||
AddStampRequest.customColor=Custom Text Color
|
AddStampRequest.customColor=Warna Teks Kustom
|
||||||
AddStampRequest.submit=Submit
|
AddStampRequest.submit=Kirim
|
||||||
|
|
||||||
|
|
||||||
#sanitizePDF
|
#sanitizePDF
|
||||||
@@ -738,7 +739,7 @@ scalePages.submit=Kirim
|
|||||||
certSign.title=Penandatanganan Sertifikat
|
certSign.title=Penandatanganan Sertifikat
|
||||||
certSign.header=Menandatangani PDF dengan sertifikat Anda (Sedang dalam proses)
|
certSign.header=Menandatangani PDF dengan sertifikat Anda (Sedang dalam proses)
|
||||||
certSign.selectPDF=Pilih Berkas PDF untuk Penandatanganan:
|
certSign.selectPDF=Pilih Berkas PDF untuk Penandatanganan:
|
||||||
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
|
certSign.jksNote=Catatan: Jika tipe sertifikat Anda tidak terdaftar di bawah, silakan konversi ke file Java Keystore (.jks) menggunakan alat baris perintah keytool. Kemudian, pilih opsi file .jks di bawah.
|
||||||
certSign.selectKey=Pilih Berkas Kunci Pribadi Anda (format PKCS # 8, bisa .pem atau .der):
|
certSign.selectKey=Pilih Berkas Kunci Pribadi Anda (format PKCS # 8, bisa .pem atau .der):
|
||||||
certSign.selectCert=Pilih Berkas Sertifikat Anda (format X.509, bisa .pem atau .der):
|
certSign.selectCert=Pilih Berkas Sertifikat Anda (format X.509, bisa .pem atau .der):
|
||||||
certSign.selectP12=Pilih Berkas Keystore PKCS #12 Anda (.p12 atau .pfx) (Opsional, Jika disediakan, berkas tersebut harus berisi kunci pribadi dan sertifikat Anda):
|
certSign.selectP12=Pilih Berkas Keystore PKCS #12 Anda (.p12 atau .pfx) (Opsional, Jika disediakan, berkas tersebut harus berisi kunci pribadi dan sertifikat Anda):
|
||||||
@@ -753,15 +754,15 @@ certSign.submit=Tanda tangani PDF
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Remove Certificate Signature
|
removeCertSign.title=Hapus Tanda Tangan Sertifikat
|
||||||
removeCertSign.header=Remove the digital certificate from the PDF
|
removeCertSign.header=Hapus sertifikat digital dari PDF
|
||||||
removeCertSign.selectPDF=Select a PDF file:
|
removeCertSign.selectPDF=Pilih file PDF:
|
||||||
removeCertSign.submit=Remove Signature
|
removeCertSign.submit=Hapus Tanda Tangan
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Hapus Halaman Kosong
|
removeBlanks.title=Hapus yang Kosong
|
||||||
removeBlanks.header=Remove Blank Pages
|
removeBlanks.header=Hapus Halaman Kosong
|
||||||
removeBlanks.threshold=Ambang Batas Keputihan Piksel:
|
removeBlanks.threshold=Ambang Batas Keputihan Piksel:
|
||||||
removeBlanks.thresholdDesc=Ambang batas untuk menentukan seberapa putih piksel putih yang harus diklasifikasikan sebagai 'Putih'. 0=Hitam, 255 putih murni.
|
removeBlanks.thresholdDesc=Ambang batas untuk menentukan seberapa putih piksel putih yang harus diklasifikasikan sebagai 'Putih'. 0=Hitam, 255 putih murni.
|
||||||
removeBlanks.whitePercent=Persen Putih (%):
|
removeBlanks.whitePercent=Persen Putih (%):
|
||||||
@@ -778,24 +779,27 @@ removeAnnotations.submit=Hapus
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Bandingkan
|
compare.title=Bandingkan
|
||||||
compare.header=Bandingkan PDF
|
compare.header=Bandingkan PDF
|
||||||
compare.highlightColor.1=Highlight Color 1:
|
compare.highlightColor.1=Warna Sorotan 1:
|
||||||
compare.highlightColor.2=Highlight Color 2:
|
compare.highlightColor.2=Warna Sorotan 2:
|
||||||
compare.document.1=Dokumen 1
|
compare.document.1=Dokumen 1
|
||||||
compare.document.2=Dokumen 2
|
compare.document.2=Dokumen 2
|
||||||
compare.submit=Bandingkan
|
compare.submit=Bandingkan
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Buku dan Komik ke PDF
|
||||||
BookToPDF.header=Book to PDF
|
BookToPDF.header=Buku ke PDF
|
||||||
BookToPDF.credit=Uses Calibre
|
BookToPDF.credit=Menggunakan Calibre
|
||||||
BookToPDF.submit=Convert
|
BookToPDF.submit=Konversi
|
||||||
|
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDF to Book
|
PDFToBook.title=PDF ke Buku
|
||||||
PDFToBook.header=PDF to Book
|
PDFToBook.header=PDF ke Buku
|
||||||
PDFToBook.selectText.1=Format
|
PDFToBook.selectText.1=Format
|
||||||
PDFToBook.credit=Uses Calibre
|
PDFToBook.credit=Menggunakan Calibre
|
||||||
PDFToBook.submit=Convert
|
PDFToBook.submit=Konversi
|
||||||
|
|
||||||
#sign
|
#sign
|
||||||
sign.title=Tanda
|
sign.title=Tanda
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Gambar Tanda Tangan
|
|||||||
sign.text=Masukan Teks
|
sign.text=Masukan Teks
|
||||||
sign.clear=Hapus
|
sign.clear=Hapus
|
||||||
sign.add=Tambah
|
sign.add=Tambah
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -831,7 +840,7 @@ ScannerImageSplit.selectText.7=Area Kontur Minimum:
|
|||||||
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
|
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
|
||||||
ScannerImageSplit.selectText.9=Ukuran Batas:
|
ScannerImageSplit.selectText.9=Ukuran Batas:
|
||||||
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
|
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
|
||||||
ScannerImageSplit.info=Python is not installed. It is required to run.
|
ScannerImageSplit.info=Python tidak terinstal. Ini diperlukan untuk menjalankan.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -905,16 +914,16 @@ pdfOrganiser.title=Pengaturan Halaman
|
|||||||
pdfOrganiser.header=Pengaturan Halaman PDF
|
pdfOrganiser.header=Pengaturan Halaman PDF
|
||||||
pdfOrganiser.submit=Susun ulang halaman
|
pdfOrganiser.submit=Susun ulang halaman
|
||||||
pdfOrganiser.mode=Mode
|
pdfOrganiser.mode=Mode
|
||||||
pdfOrganiser.mode.1=Custom Page Order
|
pdfOrganiser.mode.1=Urutan Halaman Kustom
|
||||||
pdfOrganiser.mode.2=Reverse Order
|
pdfOrganiser.mode.2=Urutan Terbalik
|
||||||
pdfOrganiser.mode.3=Duplex Sort
|
pdfOrganiser.mode.3=Sortir Duplex
|
||||||
pdfOrganiser.mode.4=Booklet Sort
|
pdfOrganiser.mode.4=Sortir Buku
|
||||||
pdfOrganiser.mode.5=Side Stitch Booklet Sort
|
pdfOrganiser.mode.5=Sortir Buku Jahitan Samping
|
||||||
pdfOrganiser.mode.6=Odd-Even Split
|
pdfOrganiser.mode.6=Pemisahan Genap-Ganjil
|
||||||
pdfOrganiser.mode.7=Remove First
|
pdfOrganiser.mode.7=Hapus Pertama
|
||||||
pdfOrganiser.mode.8=Remove Last
|
pdfOrganiser.mode.8=Hapus Terakhir
|
||||||
pdfOrganiser.mode.9=Remove First and Last
|
pdfOrganiser.mode.9=Hapus Pertama dan Terakhir
|
||||||
pdfOrganiser.mode.10=Odd-Even Merge
|
pdfOrganiser.mode.10=Penggabungan Genap-Ganjil
|
||||||
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
|
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
|
||||||
|
|
||||||
|
|
||||||
@@ -983,7 +992,7 @@ pdfToImage.color=Warna
|
|||||||
pdfToImage.grey=Skala abu-abu
|
pdfToImage.grey=Skala abu-abu
|
||||||
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
|
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
|
||||||
pdfToImage.submit=Konversi
|
pdfToImage.submit=Konversi
|
||||||
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
pdfToImage.info=Python tidak terinstal. Diperlukan untuk konversi WebP.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1061,7 +1070,7 @@ changeMetadata.author=Penulis:
|
|||||||
changeMetadata.creationDate=Tanggal Dibuat (yyyy/MM/dd HH:mm:ss):
|
changeMetadata.creationDate=Tanggal Dibuat (yyyy/MM/dd HH:mm:ss):
|
||||||
changeMetadata.creator=Pencipta:
|
changeMetadata.creator=Pencipta:
|
||||||
changeMetadata.keywords=Kata kunci:
|
changeMetadata.keywords=Kata kunci:
|
||||||
changeMetadata.modDate=Tangal Diupdate (yyyy/MM/dd HH:mm:ss):
|
changeMetadata.modDate=Tangal Diperbarui (yyyy/MM/dd HH:mm:ss):
|
||||||
changeMetadata.producer=Produser:
|
changeMetadata.producer=Produser:
|
||||||
changeMetadata.subject=Subjek:
|
changeMetadata.subject=Subjek:
|
||||||
changeMetadata.trapped=Terperangkap:
|
changeMetadata.trapped=Terperangkap:
|
||||||
@@ -1075,13 +1084,13 @@ pdfToPDFA.title=PDF Ke PDF/A
|
|||||||
pdfToPDFA.header=PDF ke PDF/A
|
pdfToPDFA.header=PDF ke PDF/A
|
||||||
pdfToPDFA.credit=Layanan ini menggunakan ghostscript untuk konversi PDF/A.
|
pdfToPDFA.credit=Layanan ini menggunakan ghostscript untuk konversi PDF/A.
|
||||||
pdfToPDFA.submit=Konversi
|
pdfToPDFA.submit=Konversi
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Saat ini tidak dapat digunakan untuk beberapa input sekaligus
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Format keluaran
|
||||||
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
pdfToPDFA.pdfWithDigitalSignature=PDF ini mengandung tanda tangan digital. Ini akan dihapus pada langkah berikutnya.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
PDFToWord.title=PDF Ke Word
|
PDFToWord.title=PDF ke Word
|
||||||
PDFToWord.header=PDF ke Word
|
PDFToWord.header=PDF ke Word
|
||||||
PDFToWord.selectText.1=Hasil format berkas
|
PDFToWord.selectText.1=Hasil format berkas
|
||||||
PDFToWord.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
PDFToWord.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
||||||
@@ -1097,7 +1106,7 @@ PDFToPresentation.submit=Konversi
|
|||||||
|
|
||||||
|
|
||||||
#PDFToText
|
#PDFToText
|
||||||
PDFToText.title=PDF Ke RTF (Text)
|
PDFToText.title=PDF ke RTF (Text)
|
||||||
PDFToText.header=PDF ke RTF (Text)
|
PDFToText.header=PDF ke RTF (Text)
|
||||||
PDFToText.selectText.1=Hasil format berkas
|
PDFToText.selectText.1=Hasil format berkas
|
||||||
PDFToText.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
PDFToText.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
||||||
@@ -1105,20 +1114,20 @@ PDFToText.submit=Konversi
|
|||||||
|
|
||||||
|
|
||||||
#PDFToHTML
|
#PDFToHTML
|
||||||
PDFToHTML.title=PDF Ke HTML
|
PDFToHTML.title=PDF ke HTML
|
||||||
PDFToHTML.header=PDF ke HTML
|
PDFToHTML.header=PDF ke HTML
|
||||||
PDFToHTML.credit=Layanan ini menggunakan pdftohtml untuk konversi berkas.
|
PDFToHTML.credit=Layanan ini menggunakan pdftohtml untuk konversi berkas.
|
||||||
PDFToHTML.submit=Konversi
|
PDFToHTML.submit=Konversi
|
||||||
|
|
||||||
|
|
||||||
#PDFToXML
|
#PDFToXML
|
||||||
PDFToXML.title=PDF Ke XML
|
PDFToXML.title=PDF ke XML
|
||||||
PDFToXML.header=PDF ke XML
|
PDFToXML.header=PDF ke XML
|
||||||
PDFToXML.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
PDFToXML.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
||||||
PDFToXML.submit=Konversi
|
PDFToXML.submit=Konversi
|
||||||
|
|
||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF Ke CSV
|
PDFToCSV.title=PDF ke CSV
|
||||||
PDFToCSV.header=PDF ke CSV
|
PDFToCSV.header=PDF ke CSV
|
||||||
PDFToCSV.prompt=Pilih halaman untuk mengambil tabel
|
PDFToCSV.prompt=Pilih halaman untuk mengambil tabel
|
||||||
PDFToCSV.submit=Ektraksi
|
PDFToCSV.submit=Ektraksi
|
||||||
@@ -1159,67 +1168,65 @@ split-by-sections.vertical.label=Pembagian Vertikal
|
|||||||
split-by-sections.horizontal.placeholder=Input angka untuk pembagian horizontal
|
split-by-sections.horizontal.placeholder=Input angka untuk pembagian horizontal
|
||||||
split-by-sections.vertical.placeholder=Input angka untuk pembagian vertikal
|
split-by-sections.vertical.placeholder=Input angka untuk pembagian vertikal
|
||||||
split-by-sections.submit=Pisahkan PDF
|
split-by-sections.submit=Pisahkan PDF
|
||||||
split-by-sections.merge=Merge Into One PDF
|
split-by-sections.merge=Gabung Menjadi Berkas PDF Tunggal
|
||||||
|
|
||||||
|
|
||||||
#printFile
|
#printFile
|
||||||
printFile.title=Print File
|
printFile.title=Cetak File
|
||||||
printFile.header=Print File to Printer
|
printFile.header=Cetak File ke Printer
|
||||||
printFile.selectText.1=Select File to Print
|
printFile.selectText.1=Pilih File untuk Dicetak
|
||||||
printFile.selectText.2=Enter Printer Name
|
printFile.selectText.2=Masukkan Nama Printer
|
||||||
printFile.submit=Print
|
printFile.submit=Cetak
|
||||||
|
|
||||||
|
|
||||||
#licenses
|
#licenses
|
||||||
licenses.nav=Licenses
|
licenses.nav=Lisensi
|
||||||
licenses.title=3rd Party Licenses
|
licenses.title=Lisensi Pihak Ketiga
|
||||||
licenses.header=3rd Party Licenses
|
licenses.header=Lisensi Pihak Ketiga
|
||||||
licenses.module=Module
|
licenses.module=Modul
|
||||||
licenses.version=Version
|
licenses.version=Versi
|
||||||
licenses.license=License
|
licenses.license=Lisensi
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survey
|
survey.nav=Survei
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Survei Stirling-PDF
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF tidak memiliki pelacakan, jadi kami ingin mendengar dari pengguna kami untuk meningkatkan Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
survey.changes=Stirling-PDF telah berubah sejak survei terakhir! Untuk mengetahui lebih lanjut, silakan periksa posting blog kami di sini:
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
survey.changes2=Dengan perubahan ini, kami mendapatkan dukungan bisnis yang dibayar dan pendanaan
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Silakan pertimbangkan untuk mengikuti survei kami!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Popup survei akan dinonaktifkan dalam pembaruan berikutnya tetapi tersedia di bagian bawah halaman)
|
||||||
survey.button=Take Survey
|
survey.button=Ikuti Survei
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=Jangan tampilkan lagi
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
error.sorry=Sorry for the issue!
|
error.sorry=Maaf atas masalah ini!
|
||||||
error.needHelp=Need help / Found an issue?
|
error.needHelp=Butuh bantuan / Menemukan masalah?
|
||||||
error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
|
error.contactTip=Jika Anda masih mengalami kesulitan, jangan ragu untuk menghubungi kami untuk bantuan. Anda dapat mengirim tiket di halaman GitHub kami atau menghubungi kami melalui Discord:
|
||||||
error.404.head=404 - Page Not Found | Oops, we tripped in the code!
|
error.404.head=404 - Halaman Tidak Ditemukan | Ups, kami tersandung dalam kode!
|
||||||
error.404.1=We can't seem to find the page you're looking for.
|
error.404.1=Kami tidak dapat menemukan halaman yang Anda cari.
|
||||||
error.404.2=Something went wrong
|
error.404.2=Terjadi kesalahan
|
||||||
error.github=Submit a ticket on GitHub
|
error.github=Kirim tiket di GitHub
|
||||||
error.showStack=Show Stack Trace
|
error.showStack=Tampilkan Stack Trace
|
||||||
error.copyStack=Copy Stack Trace
|
error.copyStack=Salin Stack Trace
|
||||||
error.githubSubmit=GitHub - Submit a ticket
|
error.githubSubmit=GitHub - Kirim tiket
|
||||||
error.discordSubmit=Discord - Submit Support post
|
error.discordSubmit=Discord - Kirim pos dukungan
|
||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Remove image
|
removeImage.title=Hapus gambar
|
||||||
removeImage.header=Remove image
|
removeImage.header=Hapus gambar
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Hapus gambar
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Hapus gambar
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
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.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.submit=Split PDF
|
|
||||||
|
|
||||||
|
|
||||||
|
splitByChapters.title=Pecah PDF berdasarkan Bab
|
||||||
|
splitByChapters.header=Pecah PDF berdasarkan Bab
|
||||||
|
splitByChapters.bookmarkLevel=Tingkatan Markah
|
||||||
|
splitByChapters.includeMetadata=Termasuk Metadata
|
||||||
|
splitByChapters.allowDuplicates=Izinkan Duplikat
|
||||||
|
splitByChapters.desc.1=Alat ini membagi file PDF menjadi beberapa PDF berdasarkan struktur babnya.
|
||||||
|
splitByChapters.desc.2=Tingkatan Markah: Pilih tingkatan markah yang digunakan untuk membagi (0 untuk tingkat atas, 1 untuk tingkat kedua, dll.).
|
||||||
|
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.submit=Pecah PDF
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Pagina
|
page=Pagina
|
||||||
pages=Pagine
|
pages=Pagine
|
||||||
|
loading=Caricamento...
|
||||||
|
addToDoc=Aggiungi al documento
|
||||||
|
|
||||||
legal.privacy=Informativa sulla privacy
|
legal.privacy=Informativa sulla privacy
|
||||||
legal.terms=Termini e Condizioni
|
legal.terms=Termini e Condizioni
|
||||||
@@ -145,7 +147,7 @@ navbar.sections.convertFrom=Converti da PDF
|
|||||||
navbar.sections.security=Firma & Sicurezza
|
navbar.sections.security=Firma & Sicurezza
|
||||||
navbar.sections.advance=Avanzate
|
navbar.sections.advance=Avanzate
|
||||||
navbar.sections.edit=Visualizza & Modifica
|
navbar.sections.edit=Visualizza & Modifica
|
||||||
navbar.sections.popular=Populare
|
navbar.sections.popular=Popolare
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=L'utente è disattivato, l'accesso è attualmente bloccato
|
|||||||
login.alreadyLoggedIn=Hai già effettuato l'accesso a
|
login.alreadyLoggedIn=Hai già effettuato l'accesso a
|
||||||
login.alreadyLoggedIn2=dispositivi. Esci dai dispositivi e riprova.
|
login.alreadyLoggedIn2=dispositivi. Esci dai dispositivi e riprova.
|
||||||
login.toManySessions=Hai troppe sessioni attive
|
login.toManySessions=Hai troppe sessioni attive
|
||||||
login.toManySessions2=Si prega di uscire dai dispositivi e riprovare. In alternativa, è possibile effettuare l'upgrade a Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redazione automatica
|
autoRedact.title=Redazione automatica
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Evidenzia colore 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Compara
|
compare.submit=Compara
|
||||||
|
compare.complex.message=Uno o entrambi i documenti forniti sono file di grandi dimensioni, l'accuratezza del confronto potrebbe risultare ridotta
|
||||||
|
compare.large.file.message=Uno o entrambi i documenti forniti sono troppo grandi per essere elaborati
|
||||||
|
compare.no.text.message=Uno o entrambi i PDF selezionati non hanno contenuto di testo. Si prega di scegliere PDF con testo per il confronto.
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Libri e fumetti in PDF
|
BookToPDF.title=Libri e fumetti in PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Disegna Firma
|
|||||||
sign.text=Testo
|
sign.text=Testo
|
||||||
sign.clear=Cancella
|
sign.clear=Cancella
|
||||||
sign.add=Aggiungi
|
sign.add=Aggiungi
|
||||||
|
sign.saved=Firme salvate
|
||||||
|
sign.save=Firma salvata
|
||||||
|
sign.personalSigs=Firme personali
|
||||||
|
sign.sharedSigs=Firme condivise
|
||||||
|
sign.noSavedSigs=Nessuna firma salvata trovata
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=プライバシーポリシー
|
legal.privacy=プライバシーポリシー
|
||||||
legal.terms=利用規約
|
legal.terms=利用規約
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=ユーザーは非アクティブ化されており、現
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自動塗りつぶし
|
autoRedact.title=自動塗りつぶし
|
||||||
@@ -783,6 +784,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=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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に変換
|
||||||
@@ -805,6 +809,11 @@ sign.draw=署名を書く
|
|||||||
sign.text=テキスト入力
|
sign.text=テキスト入力
|
||||||
sign.clear=クリア
|
sign.clear=クリア
|
||||||
sign.add=追加
|
sign.add=追加
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=자동 검열
|
autoRedact.title=자동 검열
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=문서 1
|
compare.document.1=문서 1
|
||||||
compare.document.2=문서 2
|
compare.document.2=문서 2
|
||||||
compare.submit=비교
|
compare.submit=비교
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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로
|
||||||
@@ -805,6 +809,11 @@ sign.draw=서명 그리기
|
|||||||
sign.text=텍스트 입력
|
sign.text=텍스트 입력
|
||||||
sign.clear=초기화
|
sign.clear=초기화
|
||||||
sign.add=추가
|
sign.add=추가
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisch censureren
|
autoRedact.title=Automatisch censureren
|
||||||
@@ -783,6 +784,9 @@ 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=Vergelijken
|
compare.submit=Vergelijken
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Boeken en strips naar PDF
|
BookToPDF.title=Boeken en strips naar PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Handtekening tekenen
|
|||||||
sign.text=Tekstinvoer
|
sign.text=Tekstinvoer
|
||||||
sign.clear=Wissen
|
sign.clear=Wissen
|
||||||
sign.add=Toevoegen
|
sign.add=Toevoegen
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisk Sensurering
|
autoRedact.title=Automatisk Sensurering
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Uthevingsfarge 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Sammenlign
|
compare.submit=Sammenlign
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Bøker og Tegneserier til PDF
|
BookToPDF.title=Bøker og Tegneserier til PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Tegn signatur
|
|||||||
sign.text=Tekstinput
|
sign.text=Tekstinput
|
||||||
sign.clear=Slett
|
sign.clear=Slett
|
||||||
sign.add=Legg til
|
sign.add=Legg til
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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=Font Size
|
addPageNumbers.fontSize=Rozmiar Czcionki
|
||||||
addPageNumbers.fontName=Font Name
|
addPageNumbers.fontName=Nazwa Czcionki
|
||||||
pdfPrompt=Wybierz PDF
|
pdfPrompt=Wybierz PDF
|
||||||
multiPdfPrompt=Wybierz PDF (2+)
|
multiPdfPrompt=Wybierz PDF (2+)
|
||||||
multiPdfDropPrompt=Wybierz (lub przeciągnij i puść) wszystkie dokumenty PDF
|
multiPdfDropPrompt=Wybierz (lub przeciągnij i puść) wszystkie dokumenty PDF
|
||||||
@@ -56,12 +56,12 @@ userNotFoundMessage=Brak użytkownika.
|
|||||||
incorrectPasswordMessage=Nieprawidłowe hasło.
|
incorrectPasswordMessage=Nieprawidłowe hasło.
|
||||||
usernameExistsMessage=Taki uzytkownik już istnieje.
|
usernameExistsMessage=Taki uzytkownik już istnieje.
|
||||||
invalidUsernameMessage=Niewłaściwa nazwa użytkownika - musi zawierać litery, cyfry i @._+- LUB być adresem email.
|
invalidUsernameMessage=Niewłaściwa nazwa użytkownika - musi zawierać litery, cyfry i @._+- LUB być adresem email.
|
||||||
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
invalidPasswordMessage=Hasło nie może być puste i nie może zawierać spacji na początku ani na końcu.
|
||||||
confirmPasswordErrorMessage=Wpisz poprawnie hasło w OBA pola.
|
confirmPasswordErrorMessage=Wpisz poprawnie hasło w OBA pola.
|
||||||
deleteCurrentUserMessage=Nie można usunąć zalogowanego użytkownika
|
deleteCurrentUserMessage=Nie można usunąć zalogowanego użytkownika
|
||||||
deleteUsernameExistsMessage=Nie można usunąć zalogowanego użytkownika
|
deleteUsernameExistsMessage=Nie można usunąć zalogowanego użytkownika
|
||||||
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
|
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
|
||||||
disabledCurrentUserMessage=The current user cannot be disabled
|
disabledCurrentUserMessage=Nie można wyłączyć bieżącego użytkownika
|
||||||
downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
|
downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
|
||||||
userAlreadyExistsOAuthMessage=Takie konto użytkownika istnieje - stworzone za pomocą OAuth2.
|
userAlreadyExistsOAuthMessage=Takie konto użytkownika istnieje - stworzone za pomocą OAuth2.
|
||||||
userAlreadyExistsWebMessage=Takie konto użytkownika istnieje - stworzone za pomocą przeglądarki.
|
userAlreadyExistsWebMessage=Takie konto użytkownika istnieje - stworzone za pomocą przeglądarki.
|
||||||
@@ -77,14 +77,16 @@ color=kolor
|
|||||||
sponsor=sponsor
|
sponsor=sponsor
|
||||||
info=informacje
|
info=informacje
|
||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Strona
|
||||||
pages=Pages
|
pages=Strony
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Polityka Prywatności
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Zasady i Postanowienia
|
||||||
legal.accessibility=Accessibility
|
legal.accessibility=Dostępność
|
||||||
legal.cookie=Cookie Policy
|
legal.cookie=Polityka plików cookie
|
||||||
legal.impressum=Impressum
|
legal.impressum=Impresja
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -114,21 +116,21 @@ pipelineOptions.validateButton=Waliduj
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Uaktualnij do wersji Pro
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Ta funkcja jest dostępna tylko dla użytkowników Pro.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro obsługuje pliki konfiguracyjne YAML i inne funkcje SSO.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Szukasz więcej funkcji zarządzania użytkownikami? Sprawdź Stirling PDF Pro
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=Czy chcesz ulepszyć 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.paragraph1=Stirling PDF ma opcję analizy, która pomaga nam udoskonalać produkt. Nie śledzimy żadnych danych osobowych ani zawartości plików.
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Rozważ włączenie funkcji analitycznych, które pomogą w rozwoju Stirling-PDF i pozwolą nam lepiej zrozumieć naszych użytkowników.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Włącz analitykę
|
||||||
analytics.disable=Disable analytics
|
analytics.disable=Wyłącz analitykę
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
analytics.settings=Możesz zmienić ustawienia analityki w pliku config/settings.yml
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -138,14 +140,14 @@ navbar.darkmode=Tryb nocny
|
|||||||
navbar.language=Języki
|
navbar.language=Języki
|
||||||
navbar.settings=Ustawienia
|
navbar.settings=Ustawienia
|
||||||
navbar.allTools=Narzędzia
|
navbar.allTools=Narzędzia
|
||||||
navbar.multiTool=Multi Tools
|
navbar.multiTool=Narzędzie Wielofunkcyjne
|
||||||
navbar.sections.organize=Organizuj
|
navbar.sections.organize=Organizuj
|
||||||
navbar.sections.convertTo=Przetwórz na PDF
|
navbar.sections.convertTo=Przetwórz na PDF
|
||||||
navbar.sections.convertFrom=Przetwórz z PDF
|
navbar.sections.convertFrom=Przetwórz z PDF
|
||||||
navbar.sections.security=Podpis i bezpieczeństwo
|
navbar.sections.security=Podpis i bezpieczeństwo
|
||||||
navbar.sections.advance=Zaawansowane
|
navbar.sections.advance=Zaawansowane
|
||||||
navbar.sections.edit=Podgląd i edycja
|
navbar.sections.edit=Podgląd i edycja
|
||||||
navbar.sections.popular=Popular
|
navbar.sections.popular=Popularne
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -218,13 +220,13 @@ adminUserSettings.forceChange=Wymuś zmianę hasło po zalogowaniu
|
|||||||
adminUserSettings.submit=Zapisz użytkownika
|
adminUserSettings.submit=Zapisz użytkownika
|
||||||
adminUserSettings.changeUserRole=Zmień rolę użytkownika
|
adminUserSettings.changeUserRole=Zmień rolę użytkownika
|
||||||
adminUserSettings.authenticated=Zalogowany
|
adminUserSettings.authenticated=Zalogowany
|
||||||
adminUserSettings.editOwnProfil=Edit own profile
|
adminUserSettings.editOwnProfil=Edytuj własny profil
|
||||||
adminUserSettings.enabledUser=enabled user
|
adminUserSettings.enabledUser=włączony użytkownik
|
||||||
adminUserSettings.disabledUser=disabled user
|
adminUserSettings.disabledUser=wyłączony użytkownik
|
||||||
adminUserSettings.activeUsers=Active Users:
|
adminUserSettings.activeUsers=Aktywni Użytkownicy:
|
||||||
adminUserSettings.disabledUsers=Disabled Users:
|
adminUserSettings.disabledUsers=Wyłączeni Użytkownicy:
|
||||||
adminUserSettings.totalUsers=Total Users:
|
adminUserSettings.totalUsers=Łączna Liczba Użytkowników:
|
||||||
adminUserSettings.lastRequest=Last Request
|
adminUserSettings.lastRequest=Ostatnie Zgłoszenie
|
||||||
|
|
||||||
|
|
||||||
database.title=Import/Eksport bazy danych
|
database.title=Import/Eksport bazy danych
|
||||||
@@ -243,7 +245,7 @@ database.fileNotFound=Plik nie znaleziony
|
|||||||
database.fileNullOrEmpty=Plik nie może być pusty
|
database.fileNullOrEmpty=Plik nie może być pusty
|
||||||
database.failedImportFile=Nie udało się zaimportować pliku
|
database.failedImportFile=Nie udało się zaimportować pliku
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
session.expired=Twoja sesja wygasła. Odśwież stronę i spróbuj ponownie.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -256,207 +258,207 @@ home.viewPdf.title=Podejrzyj PDF
|
|||||||
home.viewPdf.desc=Wyświetl, adnotuj, dodaj tekst lub obrazy
|
home.viewPdf.desc=Wyświetl, adnotuj, dodaj tekst lub obrazy
|
||||||
viewPdf.tags=wyświetl,czytaj,adnotuj,tekst,obraz
|
viewPdf.tags=wyświetl,czytaj,adnotuj,tekst,obraz
|
||||||
|
|
||||||
home.multiTool.title=Multi narzędzie PDF
|
home.multiTool.title=Wielofunkcyjne Narzędzie PDF
|
||||||
home.multiTool.desc=Łącz, dziel, obracaj, zmieniaj kolejność i usuwaj strony
|
home.multiTool.desc=Łącz, dziel, obracaj, zmieniaj kolejność i usuwaj strony
|
||||||
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
|
multiTool.tags=Wielofunkcyjne narzędzie, obsługa wielu operacji, interfejs użytkownika, przeciąganie kliknięć, front-end, strona klienta
|
||||||
|
|
||||||
home.merge.title=Połącz
|
home.merge.title=Połącz
|
||||||
home.merge.desc=Łatwe łączenie wielu dokumentów PDF w jeden.
|
home.merge.desc=Łatwe łączenie wielu dokumentów PDF w jeden.
|
||||||
merge.tags=merge,Page operations,Back end,server side
|
merge.tags=scalanie, operacje na stronach, back-end, po stronie serwera
|
||||||
|
|
||||||
home.split.title=Podziel
|
home.split.title=Podziel
|
||||||
home.split.desc=Podziel dokument PDF na wiele dokumentów
|
home.split.desc=Podziel dokument PDF na wiele dokumentów
|
||||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
split.tags=Operacje na stronach, dzielenie, wiele stron, cięcie, po stronie serwera
|
||||||
|
|
||||||
home.rotate.title=Obróć
|
home.rotate.title=Obróć
|
||||||
home.rotate.desc=Łatwo obracaj dokumenty PDF.
|
home.rotate.desc=Łatwo obracaj dokumenty PDF.
|
||||||
rotate.tags=server side
|
rotate.tags=strona serwera
|
||||||
|
|
||||||
|
|
||||||
home.imageToPdf.title=Obraz na PDF
|
home.imageToPdf.title=Obraz na PDF
|
||||||
home.imageToPdf.desc=Konwertuj obraz (PNG, JPEG, GIF) do dokumentu PDF.
|
home.imageToPdf.desc=Konwertuj obraz (PNG, JPEG, GIF) do dokumentu PDF.
|
||||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
imageToPdf.tags=konwersja,img,jpg,obraz,zdjęcie
|
||||||
|
|
||||||
home.pdfToImage.title=PDF na Obraz
|
home.pdfToImage.title=PDF na Obraz
|
||||||
home.pdfToImage.desc=Konwertuj plik PDF na obraz (PNG, JPEG, GIF).
|
home.pdfToImage.desc=Konwertuj plik PDF na obraz (PNG, JPEG, GIF).
|
||||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
pdfToImage.tags=konwersja,img,jpg,obraz,zdjęcie
|
||||||
|
|
||||||
home.pdfOrganiser.title=Uporządkuj
|
home.pdfOrganiser.title=Uporządkuj
|
||||||
home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności
|
home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności
|
||||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
pdfOrganiser.tags=duplex,parzyste,nieparzyste,sortuj,przenieś
|
||||||
|
|
||||||
|
|
||||||
home.addImage.title=Dodaj obraz
|
home.addImage.title=Dodaj obraz
|
||||||
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF
|
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF
|
||||||
addImage.tags=img,jpg,picture,photo
|
addImage.tags=img,jpg,obraz,zdjęcie
|
||||||
|
|
||||||
home.watermark.title=Dodaj znak wodny
|
home.watermark.title=Dodaj znak wodny
|
||||||
home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF.
|
home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF.
|
||||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
watermark.tags=Tekst,powtarzanie,etykieta,własne,prawa autorskie,znak wodny,img,jpg,obraz,zdjęcie
|
||||||
|
|
||||||
home.permissions.title=Zmień uprawnienia
|
home.permissions.title=Zmień uprawnienia
|
||||||
home.permissions.desc=Zmień uprawnienia dokumentu PDF
|
home.permissions.desc=Zmień uprawnienia dokumentu PDF
|
||||||
permissions.tags=read,write,edit,print
|
permissions.tags=odczyt,zapis,edycja,drukowanie
|
||||||
|
|
||||||
|
|
||||||
home.removePages.title=Usuń
|
home.removePages.title=Usuń
|
||||||
home.removePages.desc=Usuń niechciane strony z dokumentu PDF.
|
home.removePages.desc=Usuń niechciane strony z dokumentu PDF.
|
||||||
removePages.tags=Remove pages,delete pages
|
removePages.tags=Usuń strony,usuwaj strony
|
||||||
|
|
||||||
home.addPassword.title=Dodaj hasło
|
home.addPassword.title=Dodaj hasło
|
||||||
home.addPassword.desc=Zaszyfruj dokument PDF za pomocą hasła.
|
home.addPassword.desc=Zaszyfruj dokument PDF za pomocą hasła.
|
||||||
addPassword.tags=secure,security
|
addPassword.tags=bezpieczeństwo,ochrona
|
||||||
|
|
||||||
home.removePassword.title=Usuń hasło
|
home.removePassword.title=Usuń hasło
|
||||||
home.removePassword.desc=Usuń ochronę hasłem z dokumentu PDF.
|
home.removePassword.desc=Usuń ochronę hasłem z dokumentu PDF.
|
||||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
removePassword.tags=zabezpieczenie,odszyfrowanie,bezpieczeństwo,odhasłowanie,usunięcie hasła
|
||||||
|
|
||||||
home.compressPdfs.title=Kompresuj
|
home.compressPdfs.title=Kompresuj
|
||||||
home.compressPdfs.desc=Kompresuj dokumenty PDF, aby zmniejszyć ich rozmiar.
|
home.compressPdfs.desc=Kompresuj dokumenty PDF, aby zmniejszyć ich rozmiar.
|
||||||
compressPdfs.tags=squish,small,tiny
|
compressPdfs.tags=zgniatać,mały,malutki
|
||||||
|
|
||||||
|
|
||||||
home.changeMetadata.title=Zmień metadane
|
home.changeMetadata.title=Zmień metadane
|
||||||
home.changeMetadata.desc=Zmień/Usuń/Dodaj metadane w dokumencie PDF
|
home.changeMetadata.desc=Zmień/Usuń/Dodaj metadane w dokumencie PDF
|
||||||
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
|
changeMetadata.tags=Tytuł,autor,data,utworzenie,czas,wydawca,producent,statystyki
|
||||||
|
|
||||||
home.fileToPDF.title=Konwertuj plik do PDF
|
home.fileToPDF.title=Konwertuj plik do PDF
|
||||||
home.fileToPDF.desc=Konwertuj dowolny plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
home.fileToPDF.desc=Konwertuj dowolny plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
||||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
fileToPDF.tags=transformacja,format,dokument,obraz,slajd,tekst,konwersja,office,dokumenty,word,excel,powerpoint
|
||||||
|
|
||||||
home.ocr.title=OCR / Zamiana na tekst
|
home.ocr.title=OCR / Zamiana na tekst
|
||||||
home.ocr.desc=OCR skanuje i wykrywa tekst z obrazów w dokumencie PDF i zamienia go na tekst.
|
home.ocr.desc=OCR skanuje i wykrywa tekst z obrazów w dokumencie PDF i zamienia go na tekst.
|
||||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
ocr.tags=rozpoznawanie, tekst, obraz, skanowanie, odczyt, identyfikacja, wykrywanie, edytowalność
|
||||||
|
|
||||||
|
|
||||||
home.extractImages.title=Wyodrębnij obrazy
|
home.extractImages.title=Wyodrębnij obrazy
|
||||||
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
|
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
|
||||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
extractImages.tags=obraz, zdjęcie, zapisz, archiwum, zip, przechwyć, złap
|
||||||
|
|
||||||
home.pdfToPDFA.title=PDF na PDF/A
|
home.pdfToPDFA.title=PDF na PDF/A
|
||||||
home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
|
home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
|
||||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
pdfToPDFA.tags=archiwum, długoterminowe, standardowe, konwersja, przechowywanie, konserwacja
|
||||||
|
|
||||||
home.PDFToWord.title=PDF na Word
|
home.PDFToWord.title=PDF na Word
|
||||||
home.PDFToWord.desc=Konwertuj dokument PDF na formaty Word (DOC, DOCX i ODT)
|
home.PDFToWord.desc=Konwertuj dokument PDF na formaty Word (DOC, DOCX i ODT)
|
||||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
PDFToWord.tags=doc,docx,odt,word, przekształcenie, transformacja, konwersja, office, microsoft, plik doc
|
||||||
|
|
||||||
home.PDFToPresentation.title=PDF na Prezentację
|
home.PDFToPresentation.title=PDF na Prezentację
|
||||||
home.PDFToPresentation.desc=Konwertuj dokument PDF na formaty prezentacji (PPT, PPTX i ODP)
|
home.PDFToPresentation.desc=Konwertuj dokument PDF na formaty prezentacji (PPT, PPTX i ODP)
|
||||||
PDFToPresentation.tags=slides,show,office,microsoft
|
PDFToPresentation.tags=slajdy, pokaz, office, microsoft
|
||||||
|
|
||||||
home.PDFToText.title=PDF na Tekst/RTF
|
home.PDFToText.title=PDF na Tekst/RTF
|
||||||
home.PDFToText.desc=Konwertuj dokument PDF na tekst lub format RTF
|
home.PDFToText.desc=Konwertuj dokument PDF na tekst lub format RTF
|
||||||
PDFToText.tags=richformat,richtextformat,rich text format
|
PDFToText.tags=format tekstu sformatowanego,rtf format
|
||||||
|
|
||||||
home.PDFToHTML.title=PDF na HTML
|
home.PDFToHTML.title=PDF na HTML
|
||||||
home.PDFToHTML.desc=Konwertuj dokument PDF na format HTML
|
home.PDFToHTML.desc=Konwertuj dokument PDF na format HTML
|
||||||
PDFToHTML.tags=web content,browser friendly
|
PDFToHTML.tags=zawartość internetowa, przyjazne dla przeglądarek
|
||||||
|
|
||||||
|
|
||||||
home.PDFToXML.title=PDF na XML
|
home.PDFToXML.title=PDF na XML
|
||||||
home.PDFToXML.desc=Konwertuj dokument PDF na format XML
|
home.PDFToXML.desc=Konwertuj dokument PDF na format XML
|
||||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
PDFToXML.tags=ekstrakcja danych, zawartość strukturalna, współdziałanie, transformacja, konwertowanie
|
||||||
|
|
||||||
home.ScannerImageSplit.title=Wykryj/Podziel zeskanowane zdjęcia
|
home.ScannerImageSplit.title=Wykryj/Podziel zeskanowane zdjęcia
|
||||||
home.ScannerImageSplit.desc=Podziel na wiele zdjęć z jednego zdjęcia/PDF
|
home.ScannerImageSplit.desc=Podziel na wiele zdjęć z jednego zdjęcia/PDF
|
||||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
ScannerImageSplit.tags=oddzielne, automatyczne wykrywanie, skanowanie, wiele zdjęć, porządkowanie
|
||||||
|
|
||||||
home.sign.title=Podpis
|
home.sign.title=Podpis
|
||||||
home.sign.desc=Dodaje podpis do dokumentu PDF za pomocą rysunku, tekstu lub obrazu
|
home.sign.desc=Dodaje podpis do dokumentu PDF za pomocą rysunku, tekstu lub obrazu
|
||||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
sign.tags=autoryzacja, inicjały, podpis odręczny, podpis tekstowy, podpis graficzny
|
||||||
|
|
||||||
home.flatten.title=Spłaszcz
|
home.flatten.title=Spłaszcz
|
||||||
home.flatten.desc=Usuń wszystkie interaktywne elementy i formularze z dokumentu PDF
|
home.flatten.desc=Usuń wszystkie interaktywne elementy i formularze z dokumentu PDF
|
||||||
flatten.tags=static,deactivate,non-interactive,streamline
|
flatten.tags=statyczny, dezaktywacja, nieinteraktywny, opływowy, streamline
|
||||||
|
|
||||||
home.repair.title=Napraw
|
home.repair.title=Napraw
|
||||||
home.repair.desc=Spróbuj naprawić uszkodzony dokument PDF
|
home.repair.desc=Spróbuj naprawić uszkodzony dokument PDF
|
||||||
repair.tags=fix,restore,correction,recover
|
repair.tags=naprawianie, naprawa, przywracanie, poprawianie, odzyskiwanie
|
||||||
|
|
||||||
home.removeBlanks.title=Usuń puste strony
|
home.removeBlanks.title=Usuń puste strony
|
||||||
home.removeBlanks.desc=Wykrywa i usuwa puste strony z dokumentu PDF
|
home.removeBlanks.desc=Wykrywa i usuwa puste strony z dokumentu PDF
|
||||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
removeBlanks.tags=czyszczenie, usprawnianie, brak treści, organizowanie
|
||||||
|
|
||||||
home.removeAnnotations.title=Usuń notatki/przypisy
|
home.removeAnnotations.title=Usuń notatki/przypisy
|
||||||
home.removeAnnotations.desc=Usuwa wszystkie notatki i przypisy z dokumentu PDF
|
home.removeAnnotations.desc=Usuwa wszystkie notatki i przypisy z dokumentu PDF
|
||||||
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
removeAnnotations.tags=komentarze, podświetlanie, notatki, znaczniki, usuwanie
|
||||||
|
|
||||||
home.compare.title=Porównaj
|
home.compare.title=Porównaj
|
||||||
home.compare.desc=Porównuje i pokazuje różnice między dwoma dokumentami PDF
|
home.compare.desc=Porównuje i pokazuje różnice między dwoma dokumentami PDF
|
||||||
compare.tags=differentiate,contrast,changes,analysis
|
compare.tags=rozróżnienie, kontrast, zmiany, analiza
|
||||||
|
|
||||||
home.certSign.title=Podpisz certyfikatem
|
home.certSign.title=Podpisz certyfikatem
|
||||||
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=uwierzytelnianie, PEM, P12, oficjalny, szyfrowanie
|
||||||
|
|
||||||
home.removeCertSign.title=Usuń podpis certyfikatem
|
home.removeCertSign.title=Usuń podpis certyfikatem
|
||||||
home.removeCertSign.desc=Usuń podpis certyfikatem z dokumentu PDF
|
home.removeCertSign.desc=Usuń podpis certyfikatem z dokumentu PDF
|
||||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=uwierzytelnianie, PEM, P12, oficjalny, odszyfrowywanie
|
||||||
|
|
||||||
home.pageLayout.title=Układ wielu stron
|
home.pageLayout.title=Układ wielu stron
|
||||||
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=scalanie, kompozycja, pojedynczy widok, organizowanie, porządkowanie
|
||||||
|
|
||||||
home.scalePages.title=Dopasuj rozmiar stron
|
home.scalePages.title=Dopasuj rozmiar stron
|
||||||
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
||||||
scalePages.tags=resize,modify,dimension,adapt
|
scalePages.tags=zmiana rozmiaru, modyfikacja, rozmiar, dostosowanie
|
||||||
|
|
||||||
home.pipeline.title=Automatyzacja
|
home.pipeline.title=Automatyzacja
|
||||||
home.pipeline.desc=Wykonaj wiele akcji na dokumentach PDF, tworząc automatyzację
|
home.pipeline.desc=Wykonaj wiele akcji na dokumentach PDF, tworząc automatyzację
|
||||||
pipeline.tags=automate,sequence,scripted,batch-process
|
pipeline.tags=automatyzacja, sekwencja, skrypt, przetwarzanie wsadowe
|
||||||
|
|
||||||
home.add-page-numbers.title=Dodaj numery stron
|
home.add-page-numbers.title=Dodaj numery stron
|
||||||
home.add-page-numbers.desc=Dodaj numery strony w dokumencie PDF w podanej lokalizacji
|
home.add-page-numbers.desc=Dodaj numery strony w dokumencie PDF w podanej lokalizacji
|
||||||
add-page-numbers.tags=paginate,label,organize,index
|
add-page-numbers.tags=stronicowanie, etykieta, organizowanie, indeks, index
|
||||||
|
|
||||||
home.auto-rename.title=Automatycznie zmień nazwę PDF
|
home.auto-rename.title=Automatycznie zmień nazwę PDF
|
||||||
home.auto-rename.desc=Automatycznie zmień nazwę PDF bazując na nagłówku
|
home.auto-rename.desc=Automatycznie zmień nazwę PDF bazując na nagłówku
|
||||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
auto-rename.tags=automatyczne wykrywanie, oparte na nagłówkach, organizowanie, ponowne etykietowanie
|
||||||
|
|
||||||
home.adjust-contrast.title=Zmień kolor/nasycenie/jasność
|
home.adjust-contrast.title=Zmień kolor/nasycenie/jasność
|
||||||
home.adjust-contrast.desc=Zmień kolor/nasycenie/jasność w dokumencie PDF
|
home.adjust-contrast.desc=Zmień kolor/nasycenie/jasność w dokumencie PDF
|
||||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
adjust-contrast.tags=Korekcja kolorów, dostrajanie, modyfikacja, ulepszanie
|
||||||
|
|
||||||
home.crop.title=Przytnij PDF
|
home.crop.title=Przytnij PDF
|
||||||
home.crop.desc=Przytnij dokument PDF w celu zmniejszenia rozmiaru
|
home.crop.desc=Przytnij dokument PDF w celu zmniejszenia rozmiaru
|
||||||
crop.tags=trim,shrink,edit,shape
|
crop.tags=przycinanie, zmniejszanie, edycja, kształtowanie
|
||||||
|
|
||||||
home.autoSplitPDF.title=Automatycznie podziel strony
|
home.autoSplitPDF.title=Automatycznie podziel strony
|
||||||
home.autoSplitPDF.desc=Automatycznie podziel dokument na strony
|
home.autoSplitPDF.desc=Automatycznie podziel dokument na strony
|
||||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
autoSplitPDF.tags=Oparty na QR, rozdzielanie, skanowanie, organizowanie
|
||||||
|
|
||||||
home.sanitizePdf.title=Dezynfekcja
|
home.sanitizePdf.title=Dezynfekcja
|
||||||
home.sanitizePdf.desc=Usuń skrypt i inne elementy z dokumentu PDF
|
home.sanitizePdf.desc=Usuń skrypt i inne elementy z dokumentu PDF
|
||||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
sanitizePdf.tags=czyszczenie, ochrona, bezpieczeństwo, usuwanie zagrożeń
|
||||||
|
|
||||||
home.URLToPDF.title=Strona WWW do PDFa
|
home.URLToPDF.title=Strona WWW do PDFa
|
||||||
home.URLToPDF.desc=Zapisuje podany adres WWW do PDFa
|
home.URLToPDF.desc=Zapisuje podany adres WWW do PDFa
|
||||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
URLToPDF.tags=przechwytywanie stron internetowych, zapisywanie strony, strona internetowa do dokumentu, archiwizacja
|
||||||
|
|
||||||
home.HTMLToPDF.title=HTML do PDF
|
home.HTMLToPDF.title=HTML do PDF
|
||||||
home.HTMLToPDF.desc=Zapisuje podany plik HTML/ZIP do PDF
|
home.HTMLToPDF.desc=Zapisuje podany plik HTML/ZIP do PDF
|
||||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
HTMLToPDF.tags=znaczniki, treść internetowa, transformacja, konwertowanie
|
||||||
|
|
||||||
|
|
||||||
home.MarkdownToPDF.title=Markdown do PDF
|
home.MarkdownToPDF.title=Markdown do PDF
|
||||||
home.MarkdownToPDF.desc=Zapisuje dokument Markdown do PDF
|
home.MarkdownToPDF.desc=Zapisuje dokument Markdown do PDF
|
||||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
MarkdownToPDF.tags=znaczniki, treść internetowa, transformacja, konwertowanie
|
||||||
|
|
||||||
|
|
||||||
home.getPdfInfo.title=Pobierz informacje o pliku PDF
|
home.getPdfInfo.title=Pobierz informacje o pliku PDF
|
||||||
home.getPdfInfo.desc=Pobiera wszelkie informacje o pliku PDF
|
home.getPdfInfo.desc=Pobiera wszelkie informacje o pliku PDF
|
||||||
getPdfInfo.tags=infomation,data,stats,statistics
|
getPdfInfo.tags=informacje, dane, statystyka, statystyki
|
||||||
|
|
||||||
|
|
||||||
home.extractPage.title=Wyciągnij stronę z PDF
|
home.extractPage.title=Wyciągnij stronę z PDF
|
||||||
home.extractPage.desc=Wyciąga stronę z dokumentu PDF
|
home.extractPage.desc=Wyciąga stronę z dokumentu PDF
|
||||||
extractPage.tags=extract
|
extractPage.tags=wydobycie,separacja,wyciaganie
|
||||||
|
|
||||||
|
|
||||||
home.PdfToSinglePage.title=PDF do jednej strony
|
home.PdfToSinglePage.title=PDF do jednej strony
|
||||||
home.PdfToSinglePage.desc=Łączy wszystkie strony PDFa w jedną wielką stronę PDF
|
home.PdfToSinglePage.desc=Łączy wszystkie strony PDFa w jedną wielką stronę PDF
|
||||||
PdfToSinglePage.tags=single page
|
PdfToSinglePage.tags=pojedyncza strona
|
||||||
|
|
||||||
|
|
||||||
home.showJS.title=Pokaż kod JavaScript
|
home.showJS.title=Pokaż kod JavaScript
|
||||||
@@ -465,66 +467,66 @@ showJS.tags=JS
|
|||||||
|
|
||||||
home.autoRedact.title=Zaciemnij
|
home.autoRedact.title=Zaciemnij
|
||||||
home.autoRedact.desc=Zaciemnia dokument PDF bazując na podanej wartości
|
home.autoRedact.desc=Zaciemnia dokument PDF bazując na podanej wartości
|
||||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
autoRedact.tags=Redagowanie, ukrywanie, zaciemnianie, zaczernianie, zaznaczanie, ukrywanie
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF do CSV
|
home.tableExtraxt.title=PDF do CSV
|
||||||
home.tableExtraxt.desc=Konwertuje tabele z PDF do pliku CSV
|
home.tableExtraxt.desc=Konwertuje tabele z PDF do pliku CSV
|
||||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
tableExtraxt.tags=CSV, ekstrakcja tabeli, ekstrakcja, konwersja, wydobywanie
|
||||||
|
|
||||||
|
|
||||||
home.autoSizeSplitPDF.title=Podziel (Rozmiar/Ilość stron)
|
home.autoSizeSplitPDF.title=Podziel (Rozmiar/Ilość stron)
|
||||||
home.autoSizeSplitPDF.desc=Rozdziela dokument PDF na wiele dokumentów bazując na podanym rozmiarze, ilości stron bądź ilości dokumentów
|
home.autoSizeSplitPDF.desc=Rozdziela dokument PDF na wiele dokumentów bazując na podanym rozmiarze, ilości stron bądź ilości dokumentów
|
||||||
autoSizeSplitPDF.tags=pdf,split,document,organization
|
autoSizeSplitPDF.tags=pdf, dzielenie, dokument, organizacja
|
||||||
|
|
||||||
|
|
||||||
home.overlay-pdfs.title=Nałóż PDFa
|
home.overlay-pdfs.title=Nałóż PDFa
|
||||||
home.overlay-pdfs.desc=Nakłada dokumenty PDF na siebie
|
home.overlay-pdfs.desc=Nakłada dokumenty PDF na siebie
|
||||||
overlay-pdfs.tags=Overlay
|
overlay-pdfs.tags=Nakładka
|
||||||
|
|
||||||
home.split-by-sections.title=Podziel PDF na sekcje
|
home.split-by-sections.title=Podziel PDF na sekcje
|
||||||
home.split-by-sections.desc=Podziel strony PDF w mniejsze sekcje
|
home.split-by-sections.desc=Podziel strony PDF w mniejsze sekcje
|
||||||
split-by-sections.tags=Section Split, Divide, Customize
|
split-by-sections.tags=Podział sekcji, dzielenie, dostosowywanie
|
||||||
|
|
||||||
home.AddStampRequest.title=Dodaj pieczęć
|
home.AddStampRequest.title=Dodaj pieczęć
|
||||||
home.AddStampRequest.desc=Dodaj pieczęć tekstową/obrazową w wyznaczonej lokalizacji dokumentu
|
home.AddStampRequest.desc=Dodaj pieczęć tekstową/obrazową w wyznaczonej lokalizacji dokumentu
|
||||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
AddStampRequest.tags=Stempel, dodawanie obrazu, wyśrodkowanie obrazu, znak wodny, PDF, osadzanie, dostosowywanie
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF do eBooka
|
home.PDFToBook.title=PDF do eBooka
|
||||||
home.PDFToBook.desc=Zapisuje dokument PDF w formacie eBooka za pomocą Calibre
|
home.PDFToBook.desc=Zapisuje dokument PDF w formacie eBooka za pomocą Calibre
|
||||||
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
PDFToBook.tags=Książka,komiks,Calibre, konwertowanie, manga, amazon, kindle
|
||||||
|
|
||||||
home.BookToPDF.title=eBook do PDF
|
home.BookToPDF.title=eBook do PDF
|
||||||
home.BookToPDF.desc=Zapisuje ebooka do PDF za pomocą Calibre
|
home.BookToPDF.desc=Zapisuje ebooka do PDF za pomocą Calibre
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Remove image
|
home.removeImagePdf.title=Usuń obraz
|
||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Usuń obraz z pliku PDF, aby zmniejszyć rozmiar pliku
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Usuń obraz, operacje na stronie, back-end, strona serwera
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=Podziel PDF według rozdziałów
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Podział pliku PDF na wiele plików na podstawie struktury rozdziałów.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=podział, rozdziały, zakładki, porządkowanie, organizacja
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Zamień-Odwróć-Kolor
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Zamień-Odwróć kolor PDF
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Zastąp i Odwróć Kolor
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Zastąp kolor tekstu i tła w pliku PDF i odwróć pełen kolor pliku PDF, aby zmniejszyć rozmiar pliku
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Zastąp kolor, operacje na stronach, back-end, strona serwera
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Zastąp lub Odwróć opcje kolorów
|
||||||
replace-color.selectText.2=Default(Default high contrast colors)
|
replace-color.selectText.2=Domyślnie (domyślne kolory o wysokim kontraście)
|
||||||
replace-color.selectText.3=Custom(Customized colors)
|
replace-color.selectText.3=Niestandardowe (kolory niestandardowe)
|
||||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
replace-color.selectText.4=Całkowita-Odwrotność (Odwrócenie wszystkich kolorów)
|
||||||
replace-color.selectText.5=High contrast color options
|
replace-color.selectText.5=Wysoki kontrast opcji kolorystycznych
|
||||||
replace-color.selectText.6=white text on black background
|
replace-color.selectText.6=biały tekst na czarnym tle
|
||||||
replace-color.selectText.7=Black text on white background
|
replace-color.selectText.7=Czarny tekst na białym tle
|
||||||
replace-color.selectText.8=Yellow text on black background
|
replace-color.selectText.8=Żółty tekst na czarnym tle
|
||||||
replace-color.selectText.9=Green text on black background
|
replace-color.selectText.9=Zielony tekst na czarnym tle
|
||||||
replace-color.selectText.10=Choose text Color
|
replace-color.selectText.10=Wybierz Kolor tekstu
|
||||||
replace-color.selectText.11=Choose background Color
|
replace-color.selectText.11=Wybierz Kolor tła
|
||||||
replace-color.submit=Replace
|
replace-color.submit=Zamień
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -543,18 +545,17 @@ login.locked=Konto jest zablokowane
|
|||||||
login.signinTitle=Zaloguj się
|
login.signinTitle=Zaloguj się
|
||||||
login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
|
login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
|
||||||
login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
|
login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
|
||||||
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
login.oauth2AdminBlockedUser=Rejestracja lub logowanie niezarejestrowanych użytkowników jest obecnie zablokowane. Prosimy o kontakt z administratorem.
|
||||||
login.oauth2RequestNotFound=Błąd logowania OAuth2
|
login.oauth2RequestNotFound=Błąd logowania OAuth2
|
||||||
login.oauth2InvalidUserInfoResponse=Niewłaściwe dane logowania
|
login.oauth2InvalidUserInfoResponse=Niewłaściwe dane logowania
|
||||||
login.oauth2invalidRequest=Nieprawidłowe żądanie
|
login.oauth2invalidRequest=Nieprawidłowe żądanie
|
||||||
login.oauth2AccessDenied=Brak dostępu
|
login.oauth2AccessDenied=Brak dostępu
|
||||||
login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token
|
login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token
|
||||||
login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu
|
login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=Użytkownik jest nieaktywny, logowanie przy użyciu tej nazwy użytkownika jest obecnie zablokowane. Prosimy o kontakt z administratorem.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Jesteś już zalogowany na
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=urządzeniach. Wyloguj się z tych urządzeń i spróbuj ponownie.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Masz zbyt wiele aktywnych sesji
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatyczne zaciemnienie
|
autoRedact.title=Automatyczne zaciemnienie
|
||||||
@@ -778,11 +779,14 @@ removeAnnotations.submit=Usuń
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Porównaj
|
compare.title=Porównaj
|
||||||
compare.header=Porównaj PDF(y)
|
compare.header=Porównaj PDF(y)
|
||||||
compare.highlightColor.1=Highlight Color 1:
|
compare.highlightColor.1=Kolor Podświetlenia 1:
|
||||||
compare.highlightColor.2=Highlight Color 2:
|
compare.highlightColor.2=Kolor Podświetlenia 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porównaj
|
compare.submit=Porównaj
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=eBooki do PDF
|
BookToPDF.title=eBooki do PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Narysuj podpis
|
|||||||
sign.text=Wprowadź tekst
|
sign.text=Wprowadź tekst
|
||||||
sign.clear=Wyczyść
|
sign.clear=Wyczyść
|
||||||
sign.add=Dodaj
|
sign.add=Dodaj
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -831,7 +840,7 @@ ScannerImageSplit.selectText.7=Minimalny obszar konturu:
|
|||||||
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
|
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
|
||||||
ScannerImageSplit.selectText.9=Rozmiar obramowania:
|
ScannerImageSplit.selectText.9=Rozmiar obramowania:
|
||||||
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
|
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
|
||||||
ScannerImageSplit.info=Python is not installed. It is required to run.
|
ScannerImageSplit.info=Python nie został zainstalowany. Jest on wymagany do uruchomienia.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -858,7 +867,7 @@ ocr.submit=Przetwarzaj PDF za pomocą OCR
|
|||||||
extractImages.title=Wyodrębnij obrazy
|
extractImages.title=Wyodrębnij obrazy
|
||||||
extractImages.header=Wyodrębnij obrazy
|
extractImages.header=Wyodrębnij obrazy
|
||||||
extractImages.selectText=Wybierz format obrazu, na który chcesz przekonwertować wyodrębniony obraz.
|
extractImages.selectText=Wybierz format obrazu, na który chcesz przekonwertować wyodrębniony obraz.
|
||||||
extractImages.allowDuplicates=Save duplicate images
|
extractImages.allowDuplicates=Zapisz zduplikowane obrazy
|
||||||
extractImages.submit=Wyodrębnij
|
extractImages.submit=Wyodrębnij
|
||||||
|
|
||||||
|
|
||||||
@@ -919,8 +928,8 @@ pdfOrganiser.placeholder=(przykład 1,3,2 lub 4-8,2,10-12 lub 2n-1)
|
|||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=Multi narzędzie PDF
|
multiTool.title=Narzędzie Wielofunkcyjne PDF
|
||||||
multiTool.header=Multi narzędzie PDF
|
multiTool.header=Narzędzie Wielofunkcyjne PDF
|
||||||
multiTool.uploadPrompts=Nazwa pliku
|
multiTool.uploadPrompts=Nazwa pliku
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
@@ -983,7 +992,7 @@ pdfToImage.color=Kolor
|
|||||||
pdfToImage.grey=Odcień szarości
|
pdfToImage.grey=Odcień szarości
|
||||||
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
|
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
|
||||||
pdfToImage.submit=Konwertuj
|
pdfToImage.submit=Konwertuj
|
||||||
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
pdfToImage.info=Python nie został zainstalowany. Jest wymagany do konwersji WebP.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1020,7 +1029,7 @@ watermark.selectText.6=Odstęp w pionie (odstęp między każdym znakiem wodnym
|
|||||||
watermark.selectText.7=Nieprzezroczystość (0% - 100%):
|
watermark.selectText.7=Nieprzezroczystość (0% - 100%):
|
||||||
watermark.selectText.8=Typ znaku wodnego:
|
watermark.selectText.8=Typ znaku wodnego:
|
||||||
watermark.selectText.9=Obraz znaku wodnego:
|
watermark.selectText.9=Obraz znaku wodnego:
|
||||||
watermark.selectText.10=Convert PDF to PDF-Image
|
watermark.selectText.10=Konwertuj PDF do PDF-Image
|
||||||
watermark.submit=Dodaj znak wodny
|
watermark.submit=Dodaj znak wodny
|
||||||
watermark.type.1=Tekst
|
watermark.type.1=Tekst
|
||||||
watermark.type.2=Obraz
|
watermark.type.2=Obraz
|
||||||
@@ -1120,7 +1129,7 @@ PDFToXML.submit=Konwertuj
|
|||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF na CSV
|
PDFToCSV.title=PDF na CSV
|
||||||
PDFToCSV.header=PDF na CSV
|
PDFToCSV.header=PDF na CSV
|
||||||
PDFToCSV.prompt=Choose page to extract table
|
PDFToCSV.prompt=Wybierz stronę do wyodrębnienia tabeli
|
||||||
PDFToCSV.submit=Zatwierdź
|
PDFToCSV.submit=Zatwierdź
|
||||||
|
|
||||||
#split-by-size-or-count
|
#split-by-size-or-count
|
||||||
@@ -1182,8 +1191,8 @@ licenses.license=Licencja
|
|||||||
survey.nav=Ankieta
|
survey.nav=Ankieta
|
||||||
survey.title=Ankieta Stirling-PDF
|
survey.title=Ankieta Stirling-PDF
|
||||||
survey.description=Stirling-PDF nie śledzi swoich użytkowników, więc chciałby poznać opinie swoich użytkowników!
|
survey.description=Stirling-PDF nie śledzi swoich użytkowników, więc chciałby poznać opinie swoich użytkowników!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
survey.changes=Stirling-PDF zmieniło się od czasu ostatniej ankiety! Aby dowiedzieć się więcej, sprawdź nasz wpis na blogu tutaj:
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
survey.changes2=Dzięki tym zmianom otrzymujemy płatne wsparcie biznesowe i finansowanie
|
||||||
survey.please=Wypełnij proszę ankietę dla nas!
|
survey.please=Wypełnij proszę ankietę dla nas!
|
||||||
survey.disabled=(Blokada wyskakującego okienka z ankieta zostanie dodane w następnych aktualizacjach, ale będzie dostępna na dole strony)
|
survey.disabled=(Blokada wyskakującego okienka z ankieta zostanie dodane w następnych aktualizacjach, ale będzie dostępna na dole strony)
|
||||||
survey.button=Wypełnij ankietę
|
survey.button=Wypełnij ankietę
|
||||||
@@ -1205,21 +1214,19 @@ error.discordSubmit=Discord - wyślij posta z prośbą o pomoc
|
|||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Remove image
|
removeImage.title=Usuń obraz
|
||||||
removeImage.header=Remove image
|
removeImage.header=Usuń obraz
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Usuń obraz
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Usuń obraz
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
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.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.submit=Split PDF
|
|
||||||
|
|
||||||
|
|
||||||
|
splitByChapters.title=Podziel PDF według Rozdziałów
|
||||||
|
splitByChapters.header=Podziel PDF według Rozdziałów
|
||||||
|
splitByChapters.bookmarkLevel=Poziom Zakładek
|
||||||
|
splitByChapters.includeMetadata=Dołącz Metadane
|
||||||
|
splitByChapters.allowDuplicates=Zezwalaj na Duplikaty
|
||||||
|
splitByChapters.desc.1=Narzędzie to dzieli plik PDF na wiele plików PDF w oparciu o strukturę rozdziałów.
|
||||||
|
splitByChapters.desc.2=Poziom Zakładek: Wybierz poziom zakładek, który ma zostać użyty do podziału (0 dla najwyższego poziomu, 1 dla drugiego poziomu itd.).
|
||||||
|
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.submit=Podziel PDF
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Informações
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Página
|
page=Página
|
||||||
pages=Páginas
|
pages=Páginas
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Política de Privacidade
|
legal.privacy=Política de Privacidade
|
||||||
legal.terms=Termos e Condições
|
legal.terms=Termos e Condições
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=O usuário está desativado, o login está atualmente bloqu
|
|||||||
login.alreadyLoggedIn=Você já está conectado
|
login.alreadyLoggedIn=Você já está conectado
|
||||||
login.alreadyLoggedIn2=aparelhos. Por favor saia dos aparelhos e tente novamente.
|
login.alreadyLoggedIn2=aparelhos. Por favor saia dos aparelhos e tente novamente.
|
||||||
login.toManySessions=Você tem muitas sessões ativas
|
login.toManySessions=Você tem muitas sessões ativas
|
||||||
login.toManySessions2=Por favor saida dos aparelhos e tente novamente. Alternativamente você pode adquirir Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redação Automática de Dados
|
autoRedact.title=Redação Automática de Dados
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Cor de destaque 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Livros e Quadrinhos para PDF
|
BookToPDF.title=Livros e Quadrinhos para PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Desenhar Assinatura
|
|||||||
sign.text=Inserir texto
|
sign.text=Inserir texto
|
||||||
sign.clear=Limpar
|
sign.clear=Limpar
|
||||||
sign.add=Adicionar
|
sign.add=Adicionar
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,3 @@ splitByChapters.desc.2=Nível de Marcador: Escolha o nível de marcador a ser us
|
|||||||
splitByChapters.desc.3=Incluir Metadados: Se marcado, os metadados do PDF original serão incluidos em cada divisão do PDF.
|
splitByChapters.desc.3=Incluir Metadados: Se marcado, os metadados do PDF original serão incluidos em cada divisão do PDF.
|
||||||
splitByChapters.desc.4=Permitir Cópias: Se marcado, habilita vários marcadores na mesma página para criar PDFs separados.
|
splitByChapters.desc.4=Permitir Cópias: Se marcado, habilita vários marcadores na mesma página para criar PDFs separados.
|
||||||
splitByChapters.submit=Dividir PDF
|
splitByChapters.submit=Dividir PDF
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Edição Automática
|
autoRedact.title=Edição Automática
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Desenhar Assinatura
|
|||||||
sign.text=Inserir Texto
|
sign.text=Inserir Texto
|
||||||
sign.clear=Limpar
|
sign.clear=Limpar
|
||||||
sign.add=Adicionar
|
sign.add=Adicionar
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Informații
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=Utilizatorul este dezactivat, conectarea este în prezent b
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redactare Automată
|
autoRedact.title=Redactare Automată
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Culoare Evidențiere 2:
|
|||||||
compare.document.1=Documentul 1
|
compare.document.1=Documentul 1
|
||||||
compare.document.2=Documentul 2
|
compare.document.2=Documentul 2
|
||||||
compare.submit=Compară
|
compare.submit=Compară
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Cărți și Benzi Desenate în PDF
|
BookToPDF.title=Cărți și Benzi Desenate în PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Desenează Semnătura
|
|||||||
sign.text=Introdu Textul
|
sign.text=Introdu Textul
|
||||||
sign.clear=Curăță
|
sign.clear=Curăță
|
||||||
sign.add=Adaugă
|
sign.add=Adaugă
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматическое редактирование
|
autoRedact.title=Автоматическое редактирование
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Сравнить
|
compare.submit=Сравнить
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Нарисовать подпись
|
|||||||
sign.text=Ввод текста
|
sign.text=Ввод текста
|
||||||
sign.clear=Очистить
|
sign.clear=Очистить
|
||||||
sign.add=Добавить
|
sign.add=Добавить
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatické redigovanie
|
autoRedact.title=Automatické redigovanie
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porovnať
|
compare.submit=Porovnať
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Knihy a komiksy do PDF
|
BookToPDF.title=Knihy a komiksy do PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Kresliť podpis
|
|||||||
sign.text=Textový vstup
|
sign.text=Textový vstup
|
||||||
sign.clear=Vymazať
|
sign.clear=Vymazať
|
||||||
sign.add=Pridať
|
sign.add=Pridať
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Cenzura
|
autoRedact.title=Auto Cenzura
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Uporedi
|
compare.submit=Uporedi
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Nacrtaj potpis
|
|||||||
sign.text=Tekstualni unos
|
sign.text=Tekstualni unos
|
||||||
sign.clear=Obriši
|
sign.clear=Obriši
|
||||||
sign.add=Dodaj
|
sign.add=Dodaj
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -114,16 +116,16 @@ pipelineOptions.validateButton=Validera
|
|||||||
########################
|
########################
|
||||||
# ENTERPRISE EDITION #
|
# ENTERPRISE EDITION #
|
||||||
########################
|
########################
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
enterpriseEdition.button=Uppgradera till Pro
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
enterpriseEdition.warning=Den här funktionen är endast tillgänglig för Pro-användare.
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
enterpriseEdition.yamlAdvert=Stirling PDF Pro stöder YAML-konfigurationsfiler och andra SSO funktioner.
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
enterpriseEdition.ssoAdvert=Söker du fler funktioner för användarhantering? Spana in Stirling PDF Pro.
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Analytics #
|
# Analytics #
|
||||||
#################
|
#################
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
analytics.title=Vill du göra Stirling PDF bättre?
|
||||||
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.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=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
||||||
analytics.enable=Enable analytics
|
analytics.enable=Enable analytics
|
||||||
@@ -145,7 +147,7 @@ navbar.sections.convertFrom=Konvertera från PDF
|
|||||||
navbar.sections.security=Signera & Säkerhet
|
navbar.sections.security=Signera & Säkerhet
|
||||||
navbar.sections.advance=Avancerat
|
navbar.sections.advance=Avancerat
|
||||||
navbar.sections.edit=Visa & Redigera
|
navbar.sections.edit=Visa & Redigera
|
||||||
navbar.sections.popular=Popular
|
navbar.sections.popular=Populära
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,7 +245,7 @@ database.fileNotFound=Filen hittades inte
|
|||||||
database.fileNullOrEmpty=Filen får inte vara null eller tom
|
database.fileNullOrEmpty=Filen får inte vara null eller tom
|
||||||
database.failedImportFile=Misslyckades med att importera fil
|
database.failedImportFile=Misslyckades med att importera fil
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
session.expired=Din session har löpt ut. Uppdatera sidan och försök igen.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -503,9 +505,9 @@ home.removeImagePdf.desc=Ta bort bild från PDF för att minska filstorlek
|
|||||||
removeImagePdf.tags=Ta bort bild,Sidoperationer,Backend,serversida
|
removeImagePdf.tags=Ta bort bild,Sidoperationer,Backend,serversida
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
home.splitPdfByChapters.title=Dela upp PDF efter kapitel
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
home.splitPdfByChapters.desc=Dela upp en PDF till flera filer baserat på dess kapitelstruktur.
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
splitPdfByChapters.tags=dela,kapitel,bokmärken,organisera
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
@@ -551,10 +553,9 @@ login.oauth2AccessDenied=Åtkomst nekad
|
|||||||
login.oauth2InvalidTokenResponse=Ogiltigt token-svar
|
login.oauth2InvalidTokenResponse=Ogiltigt token-svar
|
||||||
login.oauth2InvalidIdToken=Ogiltigt Id-token
|
login.oauth2InvalidIdToken=Ogiltigt Id-token
|
||||||
login.userIsDisabled=Användaren är inaktiverad, inloggning är för närvarande blockerad med detta användarnamn. Kontakta administratören.
|
login.userIsDisabled=Användaren är inaktiverad, inloggning är för närvarande blockerad med detta användarnamn. Kontakta administratören.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=Du är redan inloggad på
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=enheter. Logga ut från enheterna och försök igen.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=Du har för många aktiva sessioner
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto-redigera
|
autoRedact.title=Auto-redigera
|
||||||
@@ -729,7 +730,7 @@ pageLayout.submit=Skicka
|
|||||||
scalePages.title=Justera sidskala
|
scalePages.title=Justera sidskala
|
||||||
scalePages.header=Justera sidskala
|
scalePages.header=Justera sidskala
|
||||||
scalePages.pageSize=Storlek på en sida i dokumentet.
|
scalePages.pageSize=Storlek på en sida i dokumentet.
|
||||||
scalePages.keepPageSize=Original Size
|
scalePages.keepPageSize=Originalstorlek
|
||||||
scalePages.scaleFactor=Zoomnivå (beskärning) för en sida.
|
scalePages.scaleFactor=Zoomnivå (beskärning) för en sida.
|
||||||
scalePages.submit=Skicka
|
scalePages.submit=Skicka
|
||||||
|
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Markeringsfärg 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Jämför
|
compare.submit=Jämför
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Böcker och serier till PDF
|
BookToPDF.title=Böcker och serier till PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Rita signatur
|
|||||||
sign.text=Textinmatning
|
sign.text=Textinmatning
|
||||||
sign.clear=Rensa
|
sign.clear=Rensa
|
||||||
sign.add=Lägg till
|
sign.add=Lägg till
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1182,7 +1191,7 @@ licenses.license=Licens
|
|||||||
survey.nav=Undersökning
|
survey.nav=Undersökning
|
||||||
survey.title=Stirling-PDF-undersökning
|
survey.title=Stirling-PDF-undersökning
|
||||||
survey.description=Stirling-PDF har ingen spårning så vi vill höra från våra användare för att förbättra Stirling-PDF!
|
survey.description=Stirling-PDF har ingen spårning så vi vill höra från våra användare för att förbättra Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
survey.changes=Stirling-PDF har ändrats sedan den senaste undersökningen. Lär dig mer på vår blogg här:
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
survey.changes2=With these changes we are getting paid business support and funding
|
||||||
survey.please=Vänligen överväg att delta i vår undersökning!
|
survey.please=Vänligen överväg att delta i vår undersökning!
|
||||||
survey.disabled=(Undersökningspopup kommer att inaktiveras i kommande uppdateringar men finns tillgänglig längst ner på sidan)
|
survey.disabled=(Undersökningspopup kommer att inaktiveras i kommande uppdateringar men finns tillgänglig längst ner på sidan)
|
||||||
@@ -1211,15 +1220,13 @@ removeImage.removeImage=Ta bort bild
|
|||||||
removeImage.submit=Ta bort bild
|
removeImage.submit=Ta bort bild
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
splitByChapters.title=Dela upp PDF efter kapitel
|
||||||
splitByChapters.header=Split PDF by Chapters
|
splitByChapters.header=Dela upp PDF efter kapitel
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
splitByChapters.bookmarkLevel=Bokmärkesnivå
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
splitByChapters.includeMetadata=Inkludera Metadata
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
splitByChapters.allowDuplicates=Tillåt Dubletter
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
splitByChapters.desc.1=Detta verktyg delar upp en PDF till flera PDFer baserat på dess kapitelstruktur.
|
||||||
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=Split PDF
|
splitByChapters.submit=Dela upp PDF
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=ข้อมูล
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=ซ่อนข้อมูลอัตโนมัติ
|
autoRedact.title=ซ่อนข้อมูลอัตโนมัติ
|
||||||
@@ -783,6 +784,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=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=วาดลายเซ็น
|
|||||||
sign.text=ป้อนข้อความ
|
sign.text=ป้อนข้อความ
|
||||||
sign.clear=ล้าง
|
sign.clear=ล้าง
|
||||||
sign.add=เพิ่ม
|
sign.add=เพิ่ม
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Bilgi
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Gizlilik Politikası
|
legal.privacy=Gizlilik Politikası
|
||||||
legal.terms=Şartlar ve koşullar
|
legal.terms=Şartlar ve koşullar
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=Kullanıcı devre dışı bırakıldı, şu anda bu kullan
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Otomatik Karartma
|
autoRedact.title=Otomatik Karartma
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Vurgu Rengi 2:
|
|||||||
compare.document.1=Belge 1
|
compare.document.1=Belge 1
|
||||||
compare.document.2=Belge 2
|
compare.document.2=Belge 2
|
||||||
compare.submit=Karşılaştır
|
compare.submit=Karşılaştır
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Kitapları ve Çizgi Romanları PDF'e Dönüştürme
|
BookToPDF.title=Kitapları ve Çizgi Romanları PDF'e Dönüştürme
|
||||||
@@ -805,6 +809,11 @@ sign.draw=İmza Çiz
|
|||||||
sign.text=Metin Girişi
|
sign.text=Metin Girişi
|
||||||
sign.clear=Temizle
|
sign.clear=Temizle
|
||||||
sign.add=Ekle
|
sign.add=Ekle
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Інформація
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматичне редагування
|
autoRedact.title=Автоматичне редагування
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Порівняти
|
compare.submit=Порівняти
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Намалювати підпис
|
|||||||
sign.text=Ввід тексту
|
sign.text=Ввід тексту
|
||||||
sign.clear=Очистити
|
sign.clear=Очистити
|
||||||
sign.add=Додати
|
sign.add=Додати
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=Thông tin
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Tự động biên tập
|
autoRedact.title=Tự động biên tập
|
||||||
@@ -783,6 +784,9 @@ compare.highlightColor.2=Màu đánh dấu 2:
|
|||||||
compare.document.1=Tài liệu 1
|
compare.document.1=Tài liệu 1
|
||||||
compare.document.2=Tài liệu 2
|
compare.document.2=Tài liệu 2
|
||||||
compare.submit=So sánh
|
compare.submit=So sánh
|
||||||
|
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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=Sách và truyện tranh sang PDF
|
BookToPDF.title=Sách và truyện tranh sang PDF
|
||||||
@@ -805,6 +809,11 @@ sign.draw=Vẽ chữ ký
|
|||||||
sign.text=Nhập văn bản
|
sign.text=Nhập văn bản
|
||||||
sign.clear=Xóa
|
sign.clear=Xóa
|
||||||
sign.add=Thêm
|
sign.add=Thêm
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ info=信息
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=用户被禁用,登录已被阻止。请联系管理员
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自动删除
|
autoRedact.title=自动删除
|
||||||
@@ -783,6 +784,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=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=绘制签名
|
|||||||
sign.text=文本输入
|
sign.text=文本输入
|
||||||
sign.clear=清除
|
sign.clear=清除
|
||||||
sign.add=添加
|
sign.add=添加
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ save=儲存
|
|||||||
saveToBrowser=儲存到瀏覽器
|
saveToBrowser=儲存到瀏覽器
|
||||||
close=關閉
|
close=關閉
|
||||||
filesSelected=已選擇的檔案
|
filesSelected=已選擇的檔案
|
||||||
noFavourites=未新增收藏
|
noFavourites=還沒有功能被收藏
|
||||||
downloadComplete=下載完成
|
downloadComplete=下載完成
|
||||||
bored=等待時覺得無聊?
|
bored=等待時覺得無聊?
|
||||||
alphabet=字母表
|
alphabet=字母表
|
||||||
@@ -79,6 +79,8 @@ info=資訊
|
|||||||
pro=專業版
|
pro=專業版
|
||||||
page=頁面
|
page=頁面
|
||||||
pages=頁面
|
pages=頁面
|
||||||
|
loading=Loading...
|
||||||
|
addToDoc=Add to Document
|
||||||
|
|
||||||
legal.privacy=隱私權政策
|
legal.privacy=隱私權政策
|
||||||
legal.terms=使用條款
|
legal.terms=使用條款
|
||||||
@@ -90,7 +92,7 @@ legal.impressum=版本說明
|
|||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=管道功能選單(測試版)
|
pipeline.header=管道功能選單(測試版)
|
||||||
pipeline.uploadButton=上傳自訂
|
pipeline.uploadButton=上傳自訂設定
|
||||||
pipeline.configureButton=設定
|
pipeline.configureButton=設定
|
||||||
pipeline.defaultOption=自訂
|
pipeline.defaultOption=自訂
|
||||||
pipeline.submitButton=送出
|
pipeline.submitButton=送出
|
||||||
@@ -256,9 +258,9 @@ home.viewPdf.title=檢視 PDF
|
|||||||
home.viewPdf.desc=檢視、註釋、新增文字或圖片
|
home.viewPdf.desc=檢視、註釋、新增文字或圖片
|
||||||
viewPdf.tags=檢視,閱讀,註釋,文字,圖片
|
viewPdf.tags=檢視,閱讀,註釋,文字,圖片
|
||||||
|
|
||||||
home.multiTool.title=PDF 多工具
|
home.multiTool.title=PDF 複合工具
|
||||||
home.multiTool.desc=合併、旋轉、重新排列和移除頁面
|
home.multiTool.desc=合併、旋轉、重新排列和移除頁面
|
||||||
multiTool.tags=多工具,多操作,UI,點選拖動,前端,客戶端,互動,可互動,移動
|
multiTool.tags=複合工具,多功能,UI,點選拖曳,前端,客戶端,互動,互動式,移動
|
||||||
|
|
||||||
home.merge.title=合併
|
home.merge.title=合併
|
||||||
home.merge.desc=輕鬆將多個 PDF 合併為一個。
|
home.merge.desc=輕鬆將多個 PDF 合併為一個。
|
||||||
@@ -554,7 +556,6 @@ login.userIsDisabled=使用者已停用,目前此使用者無法登入。請
|
|||||||
login.alreadyLoggedIn=您已經登入了
|
login.alreadyLoggedIn=您已經登入了
|
||||||
login.alreadyLoggedIn2=個裝置。請登出其他裝置後再試一次。
|
login.alreadyLoggedIn2=個裝置。請登出其他裝置後再試一次。
|
||||||
login.toManySessions=您有太多使用中的工作階段
|
login.toManySessions=您有太多使用中的工作階段
|
||||||
login.toManySessions2=請登出其他裝置後再試一次。或者,您可以升級至 Stirling PDF 專業版。
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自動塗黑
|
autoRedact.title=自動塗黑
|
||||||
@@ -783,6 +784,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=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||||
|
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||||
|
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
|
||||||
@@ -805,6 +809,11 @@ sign.draw=繪製簽章
|
|||||||
sign.text=文字輸入
|
sign.text=文字輸入
|
||||||
sign.clear=清除
|
sign.clear=清除
|
||||||
sign.add=新增
|
sign.add=新增
|
||||||
|
sign.saved=Saved Signatures
|
||||||
|
sign.save=Save Signature
|
||||||
|
sign.personalSigs=Personal Signatures
|
||||||
|
sign.sharedSigs=Shared Signatures
|
||||||
|
sign.noSavedSigs=No saved signatures found
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -840,8 +849,8 @@ ocr.header=清理掃描 / OCR(光學字元識別)
|
|||||||
ocr.selectText.1=選擇要在 PDF 中偵測的語言(列出的是目前可以偵測的語言):
|
ocr.selectText.1=選擇要在 PDF 中偵測的語言(列出的是目前可以偵測的語言):
|
||||||
ocr.selectText.2=產生包含 OCR 文字的文字文件,並與 OCR 的 PDF 一起
|
ocr.selectText.2=產生包含 OCR 文字的文字文件,並與 OCR 的 PDF 一起
|
||||||
ocr.selectText.3=修正掃描的頁面傾斜角度,將它們旋轉回原位
|
ocr.selectText.3=修正掃描的頁面傾斜角度,將它們旋轉回原位
|
||||||
ocr.selectText.4=清理頁面,使 OCR 不太可能在背景噪音中找到文字。(無輸出變化)
|
ocr.selectText.4=清理頁面以降低 OCR 在背景雜訊中識別文字的機率。(無輸出變化)
|
||||||
ocr.selectText.5=清理頁面,使 OCR 不太可能在背景噪音中找到文字,保持清理的輸出。
|
ocr.selectText.5=清理頁面以降低 OCR 在背景雜訊中識別文字的機率,保持乾淨的輸出。
|
||||||
ocr.selectText.6=忽略具有互動文字的頁面,只對影像頁面進行 OCR
|
ocr.selectText.6=忽略具有互動文字的頁面,只對影像頁面進行 OCR
|
||||||
ocr.selectText.7=強制 OCR,將對每一頁進行 OCR,移除所有原始文字元素
|
ocr.selectText.7=強制 OCR,將對每一頁進行 OCR,移除所有原始文字元素
|
||||||
ocr.selectText.8=正常(如果 PDF 包含文字將出錯)
|
ocr.selectText.8=正常(如果 PDF 包含文字將出錯)
|
||||||
@@ -858,7 +867,7 @@ ocr.submit=使用 OCR 處理 PDF
|
|||||||
extractImages.title=提取圖片
|
extractImages.title=提取圖片
|
||||||
extractImages.header=提取圖片
|
extractImages.header=提取圖片
|
||||||
extractImages.selectText=選擇要轉換提取影像的影像格式
|
extractImages.selectText=選擇要轉換提取影像的影像格式
|
||||||
extractImages.allowDuplicates=Save duplicate images
|
extractImages.allowDuplicates=儲存重複的圖片
|
||||||
extractImages.submit=提取
|
extractImages.submit=提取
|
||||||
|
|
||||||
|
|
||||||
@@ -876,10 +885,10 @@ compress.title=壓縮
|
|||||||
compress.header=壓縮 PDF
|
compress.header=壓縮 PDF
|
||||||
compress.credit=此服務使用 Ghostscript 進行 PDF 壓縮/最佳化。
|
compress.credit=此服務使用 Ghostscript 進行 PDF 壓縮/最佳化。
|
||||||
compress.selectText.1=手動模式 - 從 1 到 4
|
compress.selectText.1=手動模式 - 從 1 到 4
|
||||||
compress.selectText.2=最佳化級別:
|
compress.selectText.2=最佳化等級:
|
||||||
compress.selectText.3=4(對於文字影像非常糟糕)
|
compress.selectText.3=4(對於含有文字的影像來說結果很糟)
|
||||||
compress.selectText.4=自動模式 - 自動調整品質以使 PDF 達到確定大小
|
compress.selectText.4=自動模式 - 自動調整品質使 PDF 達到指定的檔案大小
|
||||||
compress.selectText.5=預期的 PDF 大小(例如 25MB, 10.8MB, 25KB)
|
compress.selectText.5=指定的 PDF 檔案大小(例如 25MB, 10.8MB, 25KB)
|
||||||
compress.submit=壓縮
|
compress.submit=壓縮
|
||||||
|
|
||||||
|
|
||||||
@@ -919,8 +928,8 @@ pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1)
|
|||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=PDF 多工具
|
multiTool.title=PDF 複合工具
|
||||||
multiTool.header=PDF 多工具
|
multiTool.header=PDF 複合工具
|
||||||
multiTool.uploadPrompts=檔名
|
multiTool.uploadPrompts=檔名
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
@@ -1221,5 +1230,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,20 +47,31 @@ security:
|
|||||||
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:
|
||||||
|
enabled: false # Currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true
|
||||||
|
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
|
||||||
|
registrationId: stirling
|
||||||
|
idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata
|
||||||
|
idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml
|
||||||
|
idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml
|
||||||
|
idpIssuer: http://www.okta.com/externalKey
|
||||||
|
idpCert: classpath:octa.crt
|
||||||
|
privateKey: classpath:saml-private-key.key
|
||||||
|
spCert: classpath:saml-public-cert.crt
|
||||||
|
|
||||||
# Enterprise edition settings unused for now please ignore!
|
|
||||||
enterpriseEdition:
|
enterpriseEdition:
|
||||||
enabled: false # set to 'true' to enable enterprise edition
|
enabled: false # set to 'true' to enable enterprise edition
|
||||||
key: 00000000-0000-0000-0000-000000000000
|
key: 00000000-0000-0000-0000-000000000000
|
||||||
CustomMetadata:
|
CustomMetadata:
|
||||||
autoUpdateMetadata: true # set to 'true' to automatically update metadata with below values
|
autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values
|
||||||
author: username # Supports text such as 'John Doe' or types such as username
|
author: username # Supports text such as 'John Doe' or types such as username to autopopulate with users username
|
||||||
creator: Stirling-PDF # Supports text such as 'Company-PDF'
|
creator: Stirling-PDF # Supports text such as 'Company-PDF'
|
||||||
producer: Stirling-PDF # Supports text such as 'Company-PDF'
|
producer: Stirling-PDF # Supports text such as 'Company-PDF'
|
||||||
|
|
||||||
legal:
|
legal:
|
||||||
termsAndConditions: '' # URL to the terms and conditions of your application (e.g. https://example.com/terms) Empty string to disable or filename to load from local file in static folder
|
termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms) Empty string to disable or filename to load from local file in static folder
|
||||||
privacyPolicy: '' # URL to the privacy policy of your application (e.g. https://example.com/privacy) Empty string to disable or filename to load from local file in static folder
|
privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy) Empty string to disable or filename to load from local file in static folder
|
||||||
accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility) Empty string to disable or filename to load from local file in static folder
|
accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility) Empty string to disable or filename to load from local file in static folder
|
||||||
cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie) Empty string to disable or filename to load from local file in static folder
|
cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie) Empty string to disable or filename to load from local file in static folder
|
||||||
impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum) Empty string to disable or filename to load from local file in static folder
|
impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum) Empty string to disable or filename to load from local file in static folder
|
||||||
|
|||||||
@@ -3,17 +3,24 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "ch.qos.logback:logback-classic",
|
"moduleName": "ch.qos.logback:logback-classic",
|
||||||
"moduleUrl": "http://www.qos.ch",
|
"moduleUrl": "http://www.qos.ch",
|
||||||
"moduleVersion": "1.5.8",
|
"moduleVersion": "1.5.11",
|
||||||
"moduleLicense": "GNU Lesser General Public License",
|
"moduleLicense": "GNU Lesser General Public License",
|
||||||
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "ch.qos.logback:logback-core",
|
"moduleName": "ch.qos.logback:logback-core",
|
||||||
"moduleUrl": "http://www.qos.ch",
|
"moduleUrl": "http://www.qos.ch",
|
||||||
"moduleVersion": "1.5.8",
|
"moduleVersion": "1.5.11",
|
||||||
"moduleLicense": "GNU Lesser General Public License",
|
"moduleLicense": "GNU Lesser General Public License",
|
||||||
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"moduleName": "com.adobe.xmp:xmpcore",
|
||||||
|
"moduleUrl": "https://www.adobe.com/devnet/xmp/library/eula-xmp-library-java.html",
|
||||||
|
"moduleVersion": "6.1.11",
|
||||||
|
"moduleLicense": "The BSD 3-Clause License (BSD3)",
|
||||||
|
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-3-Clause"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.bucket4j:bucket4j_jdk17-core",
|
"moduleName": "com.bucket4j:bucket4j_jdk17-core",
|
||||||
"moduleUrl": "http://github.com/bucket4j/bucket4j/bucket4j_jdk17-core",
|
"moduleUrl": "http://github.com/bucket4j/bucket4j/bucket4j_jdk17-core",
|
||||||
@@ -21,6 +28,20 @@
|
|||||||
"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"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"moduleName": "com.coveo:saml-client",
|
||||||
|
"moduleUrl": "https://github.com/coveo/saml-client",
|
||||||
|
"moduleVersion": "5.0.0",
|
||||||
|
"moduleLicense": "MIT",
|
||||||
|
"moduleLicenseUrl": "https://opensource.org/licenses/MIT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"moduleName": "com.drewnoakes:metadata-extractor",
|
||||||
|
"moduleUrl": "https://drewnoakes.com/code/exif/",
|
||||||
|
"moduleVersion": "2.19.0",
|
||||||
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.core:jackson-annotations",
|
"moduleName": "com.fasterxml.jackson.core:jackson-annotations",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson",
|
"moduleUrl": "https://github.com/FasterXML/jackson",
|
||||||
@@ -393,7 +414,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-commons",
|
"moduleName": "io.micrometer:micrometer-commons",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.13.4",
|
"moduleVersion": "1.13.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"
|
||||||
},
|
},
|
||||||
@@ -407,14 +428,14 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-jakarta9",
|
"moduleName": "io.micrometer:micrometer-jakarta9",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.13.4",
|
"moduleVersion": "1.13.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": "io.micrometer:micrometer-observation",
|
"moduleName": "io.micrometer:micrometer-observation",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.13.4",
|
"moduleVersion": "1.13.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"
|
||||||
},
|
},
|
||||||
@@ -674,7 +695,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
||||||
"moduleUrl": "https://tomcat.apache.org/",
|
"moduleUrl": "https://tomcat.apache.org/",
|
||||||
"moduleVersion": "10.1.30",
|
"moduleVersion": "10.1.31",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@@ -742,14 +763,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.commonmark:commonmark",
|
"moduleName": "org.commonmark:commonmark",
|
||||||
"moduleVersion": "0.23.0",
|
"moduleVersion": "0.24.0",
|
||||||
"moduleLicense": "BSD 2-Clause License",
|
"moduleLicense": "BSD-2-Clause",
|
||||||
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.commonmark:commonmark-ext-gfm-tables",
|
"moduleName": "org.commonmark:commonmark-ext-gfm-tables",
|
||||||
"moduleVersion": "0.23.0",
|
"moduleVersion": "0.24.0",
|
||||||
"moduleLicense": "BSD 2-Clause License",
|
"moduleLicense": "BSD-2-Clause",
|
||||||
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -769,182 +790,182 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-client",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-common",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-common",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-servlet",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-servlet",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-annotations",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-annotations",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-plus",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-plus",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlet",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlet",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlets",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlets",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-webapp",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-webapp",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-client",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-common",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-common",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-server",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-api",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-api",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-common",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-common",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-alpn-client",
|
"moduleName": "org.eclipse.jetty:jetty-alpn-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-client",
|
"moduleName": "org.eclipse.jetty:jetty-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-ee",
|
"moduleName": "org.eclipse.jetty:jetty-ee",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-http",
|
"moduleName": "org.eclipse.jetty:jetty-http",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-io",
|
"moduleName": "org.eclipse.jetty:jetty-io",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-plus",
|
"moduleName": "org.eclipse.jetty:jetty-plus",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-security",
|
"moduleName": "org.eclipse.jetty:jetty-security",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-server",
|
"moduleName": "org.eclipse.jetty:jetty-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-session",
|
"moduleName": "org.eclipse.jetty:jetty-session",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-util",
|
"moduleName": "org.eclipse.jetty:jetty-util",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-xml",
|
"moduleName": "org.eclipse.jetty:jetty-xml",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.13",
|
"moduleVersion": "12.0.14",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
@@ -1132,273 +1153,273 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot",
|
"moduleName": "org.springframework.boot:spring-boot",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-actuator",
|
"moduleName": "org.springframework.boot:spring-boot-actuator",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-actuator-autoconfigure",
|
"moduleName": "org.springframework.boot:spring-boot-actuator-autoconfigure",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-autoconfigure",
|
"moduleName": "org.springframework.boot:spring-boot-autoconfigure",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-devtools",
|
"moduleName": "org.springframework.boot:spring-boot-devtools",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter",
|
"moduleName": "org.springframework.boot:spring-boot-starter",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-actuator",
|
"moduleName": "org.springframework.boot:spring-boot-starter-actuator",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-aop",
|
"moduleName": "org.springframework.boot:spring-boot-starter-aop",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-data-jpa",
|
"moduleName": "org.springframework.boot:spring-boot-starter-data-jpa",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-jdbc",
|
"moduleName": "org.springframework.boot:spring-boot-starter-jdbc",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-jetty",
|
"moduleName": "org.springframework.boot:spring-boot-starter-jetty",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-json",
|
"moduleName": "org.springframework.boot:spring-boot-starter-json",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-logging",
|
"moduleName": "org.springframework.boot:spring-boot-starter-logging",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-oauth2-client",
|
"moduleName": "org.springframework.boot:spring-boot-starter-oauth2-client",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-security",
|
"moduleName": "org.springframework.boot:spring-boot-starter-security",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-thymeleaf",
|
"moduleName": "org.springframework.boot:spring-boot-starter-thymeleaf",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.boot:spring-boot-starter-web",
|
"moduleName": "org.springframework.boot:spring-boot-starter-web",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.data:spring-data-commons",
|
"moduleName": "org.springframework.data:spring-data-commons",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-data",
|
"moduleUrl": "https://spring.io/projects/spring-data",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.data:spring-data-jpa",
|
"moduleName": "org.springframework.data:spring-data-jpa",
|
||||||
"moduleUrl": "https://projects.spring.io/spring-data-jpa",
|
"moduleUrl": "https://projects.spring.io/spring-data-jpa",
|
||||||
"moduleVersion": "3.3.4",
|
"moduleVersion": "3.3.5",
|
||||||
"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.security:spring-security-config",
|
"moduleName": "org.springframework.security:spring-security-config",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-core",
|
"moduleName": "org.springframework.security:spring-security-core",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-crypto",
|
"moduleName": "org.springframework.security:spring-security-crypto",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-oauth2-client",
|
"moduleName": "org.springframework.security:spring-security-oauth2-client",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-oauth2-core",
|
"moduleName": "org.springframework.security:spring-security-oauth2-core",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-oauth2-jose",
|
"moduleName": "org.springframework.security:spring-security-oauth2-jose",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-saml2-service-provider",
|
"moduleName": "org.springframework.security:spring-security-saml2-service-provider",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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.security:spring-security-web",
|
"moduleName": "org.springframework.security:spring-security-web",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.3.3",
|
"moduleVersion": "6.3.4",
|
||||||
"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:spring-aop",
|
"moduleName": "org.springframework:spring-aop",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-aspects",
|
"moduleName": "org.springframework:spring-aspects",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-beans",
|
"moduleName": "org.springframework:spring-beans",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-context",
|
"moduleName": "org.springframework:spring-context",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-core",
|
"moduleName": "org.springframework:spring-core",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-expression",
|
"moduleName": "org.springframework:spring-expression",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-jcl",
|
"moduleName": "org.springframework:spring-jcl",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-jdbc",
|
"moduleName": "org.springframework:spring-jdbc",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-orm",
|
"moduleName": "org.springframework:spring-orm",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-tx",
|
"moduleName": "org.springframework:spring-tx",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-web",
|
"moduleName": "org.springframework:spring-web",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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:spring-webmvc",
|
"moduleName": "org.springframework:spring-webmvc",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.13",
|
"moduleVersion": "6.1.14",
|
||||||
"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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
select#font-select,
|
select#font-select,
|
||||||
select#font-select option {
|
select#font-select option {
|
||||||
height: 60px; /* Adjust as needed */
|
height: 60px;
|
||||||
font-size: 30px; /* Adjust as needed */
|
/* Adjust as needed */
|
||||||
|
font-size: 30px;
|
||||||
|
/* Adjust as needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawing-pad-container {
|
.drawing-pad-container {
|
||||||
@@ -13,10 +15,12 @@ select#font-select option {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#box-drag-container {
|
#box-drag-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-buttons-box {
|
.draggable-buttons-box {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -24,16 +28,87 @@ select#font-select option {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
z-index: 5;
|
||||||
}
|
}
|
||||||
.draggable-buttons-box > button {
|
|
||||||
z-index: 10;
|
.draggable-buttons-box>button {
|
||||||
|
z-index: 4;
|
||||||
background-color: rgba(13, 110, 253, 0.1);
|
background-color: rgba(13, 110, 253, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-canvas {
|
.draggable-canvas {
|
||||||
border: 1px solid red;
|
border: 2px solid #3498db;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
z-index: 100;
|
||||||
|
cursor: grab;
|
||||||
|
transition: transform 0.1s ease-out;
|
||||||
|
background-color: rgba(52, 152, 219, 0.1);
|
||||||
|
/* Light blue background */
|
||||||
|
}
|
||||||
|
|
||||||
|
.draggable-canvas:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||||
|
/* Shadow on active drag */
|
||||||
|
}
|
||||||
|
|
||||||
|
.draggable-canvas:hover {
|
||||||
|
border: 2px solid #2980b9;
|
||||||
|
/* Darker border on hover */
|
||||||
|
background-color: rgba(52, 152, 219, 0.2);
|
||||||
|
/* Darken background on hover */
|
||||||
|
}
|
||||||
|
.signature-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list-item {
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list-item:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list-name {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list-details {
|
||||||
|
color: #6c757d;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-list-details small:not(:last-child) {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-toggle {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
BIN
src/main/resources/static/images/signature.png
Normal file
BIN
src/main/resources/static/images/signature.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
2106
src/main/resources/static/js/compare/diff.js
Normal file
2106
src/main/resources/static/js/compare/diff.js
Normal file
File diff suppressed because it is too large
Load Diff
145
src/main/resources/static/js/compare/pdfWorker.js
Normal file
145
src/main/resources/static/js/compare/pdfWorker.js
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
importScripts('./diff.js');
|
||||||
|
|
||||||
|
self.onmessage = async function (e) {
|
||||||
|
const { text1, text2, color1, color2 } = e.data;
|
||||||
|
console.log('Received text for comparison:', { text1, text2 });
|
||||||
|
|
||||||
|
const startTime = performance.now();
|
||||||
|
|
||||||
|
if (text1.trim() === "" || text2.trim() === "") {
|
||||||
|
self.postMessage({ status: 'error', message: 'One or both of the texts are empty.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const words1 = text1.split(' ');
|
||||||
|
const words2 = text2.split(' ');
|
||||||
|
const MAX_WORD_COUNT = 150000;
|
||||||
|
const COMPLEX_WORD_COUNT = 50000;
|
||||||
|
const BATCH_SIZE = 5000; // Define a suitable batch size for processing
|
||||||
|
const OVERLAP_SIZE = 200; // Number of words to overlap - bigger increases accuracy but affects performance
|
||||||
|
|
||||||
|
const isComplex = words1.length > COMPLEX_WORD_COUNT || words2.length > COMPLEX_WORD_COUNT;
|
||||||
|
const isTooLarge = words1.length > MAX_WORD_COUNT || words2.length > MAX_WORD_COUNT;
|
||||||
|
|
||||||
|
let complexMessage = 'One or both of the provided documents are large files, accuracy of comparison may be reduced';
|
||||||
|
let tooLargeMessage = 'One or Both of the provided documents are too large to process';
|
||||||
|
|
||||||
|
// Listen for messages from the main thread
|
||||||
|
self.addEventListener('message', (event) => {
|
||||||
|
if (event.data.type === 'SET_TOO_LARGE_MESSAGE') {
|
||||||
|
tooLargeMessage = event.data.message;
|
||||||
|
}
|
||||||
|
if (event.data.type === 'SET_COMPLEX_MESSAGE') {
|
||||||
|
complexMessage = event.data.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isTooLarge) {
|
||||||
|
self.postMessage({
|
||||||
|
status: 'warning',
|
||||||
|
message: tooLargeMessage,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (isComplex) {
|
||||||
|
self.postMessage({
|
||||||
|
status: 'warning',
|
||||||
|
message: complexMessage,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Perform diff operation depending on document size
|
||||||
|
const differences = isComplex
|
||||||
|
? await staggeredBatchDiff(words1, words2, color1, color2, BATCH_SIZE, OVERLAP_SIZE)
|
||||||
|
: diff(words1, words2, color1, color2);
|
||||||
|
|
||||||
|
console.log(`Diff operation took ${performance.now() - startTime} milliseconds`);
|
||||||
|
self.postMessage({ status: 'success', differences });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Splits text into smaller batches to run through diff checking algorithms. overlaps the batches to help ensure
|
||||||
|
async function staggeredBatchDiff(words1, words2, color1, color2, batchSize, overlapSize) {
|
||||||
|
const differences = [];
|
||||||
|
const totalWords1 = words1.length;
|
||||||
|
const totalWords2 = words2.length;
|
||||||
|
|
||||||
|
let previousEnd1 = 0; // Track where the last batch ended in words1
|
||||||
|
let previousEnd2 = 0; // Track where the last batch ended in words2
|
||||||
|
|
||||||
|
// Function to determine if differences are large, differences that are too large indicate potential error in batching
|
||||||
|
const isLargeDifference = (differences) => {
|
||||||
|
return differences.length > 50;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (previousEnd1 < totalWords1 || previousEnd2 < totalWords2) {
|
||||||
|
// Define the next chunk boundaries
|
||||||
|
const start1 = previousEnd1;
|
||||||
|
const end1 = Math.min(start1 + batchSize, totalWords1);
|
||||||
|
|
||||||
|
const start2 = previousEnd2;
|
||||||
|
const end2 = Math.min(start2 + batchSize, totalWords2);
|
||||||
|
|
||||||
|
//If difference is too high decrease batch size for more granular check
|
||||||
|
const dynamicBatchSize = isLargeDifference(differences) ? batchSize / 2 : batchSize;
|
||||||
|
|
||||||
|
// Adjust the size of the current chunk using dynamic batch size
|
||||||
|
const batchWords1 = words1.slice(start1, end1 + dynamicBatchSize);
|
||||||
|
const batchWords2 = words2.slice(start2, end2 + dynamicBatchSize);
|
||||||
|
|
||||||
|
// Include overlap from the previous chunk
|
||||||
|
const overlapWords1 = previousEnd1 > 0 ? words1.slice(Math.max(0, previousEnd1 - overlapSize), previousEnd1) : [];
|
||||||
|
const overlapWords2 = previousEnd2 > 0 ? words2.slice(Math.max(0, previousEnd2 - overlapSize), previousEnd2) : [];
|
||||||
|
|
||||||
|
// Combine overlaps and current batches for comparison
|
||||||
|
const combinedWords1 = overlapWords1.concat(batchWords1);
|
||||||
|
const combinedWords2 = overlapWords2.concat(batchWords2);
|
||||||
|
|
||||||
|
// Perform the diff on the combined words
|
||||||
|
const batchDifferences = diff(combinedWords1, combinedWords2, color1, color2);
|
||||||
|
differences.push(...batchDifferences);
|
||||||
|
|
||||||
|
// Update the previous end indices based on the results of this batch
|
||||||
|
previousEnd1 = end1;
|
||||||
|
previousEnd2 = end2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return differences;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Standard diff function for small text comparisons
|
||||||
|
function diff(words1, words2, color1, color2) {
|
||||||
|
console.log(`Starting diff between ${words1.length} words and ${words2.length} words`);
|
||||||
|
const matrix = Array.from({ length: words1.length + 1 }, () => Array(words2.length + 1).fill(0));
|
||||||
|
|
||||||
|
for (let i = 1; i <= words1.length; i++) {
|
||||||
|
for (let j = 1; j <= words2.length; j++) {
|
||||||
|
matrix[i][j] = words1[i - 1] === words2[j - 1]
|
||||||
|
? matrix[i - 1][j - 1] + 1
|
||||||
|
: Math.max(matrix[i][j - 1], matrix[i - 1][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return backtrack(matrix, words1, words2, color1, color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backtrack function to find differences
|
||||||
|
function backtrack(matrix, words1, words2, color1, color2) {
|
||||||
|
let i = words1.length, j = words2.length;
|
||||||
|
const differences = [];
|
||||||
|
|
||||||
|
while (i > 0 || j > 0) {
|
||||||
|
if (i > 0 && j > 0 && words1[i - 1] === words2[j - 1]) {
|
||||||
|
differences.unshift(['black', words1[i - 1]]);
|
||||||
|
i--; j--;
|
||||||
|
} else if (j > 0 && (i === 0 || matrix[i][j] === matrix[i][j - 1])) {
|
||||||
|
differences.unshift([color2, words2[j - 1]]);
|
||||||
|
j--;
|
||||||
|
} else {
|
||||||
|
differences.unshift([color1, words1[i - 1]]);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return differences;
|
||||||
|
}
|
||||||
36
src/main/resources/static/js/draggable.js
Normal file
36
src/main/resources/static/js/draggable.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
const draggableElement = document.querySelector('.draggable-canvas');
|
||||||
|
|
||||||
|
// Variables to store the current position of the draggable element
|
||||||
|
let offsetX, offsetY, isDragging = false;
|
||||||
|
|
||||||
|
draggableElement.addEventListener('mousedown', (e) => {
|
||||||
|
// Get the offset when the mouse is clicked inside the element
|
||||||
|
offsetX = e.clientX - draggableElement.getBoundingClientRect().left;
|
||||||
|
offsetY = e.clientY - draggableElement.getBoundingClientRect().top;
|
||||||
|
|
||||||
|
// Set isDragging to true
|
||||||
|
isDragging = true;
|
||||||
|
|
||||||
|
// Add event listeners for mouse movement and release
|
||||||
|
document.addEventListener('mousemove', onMouseMove);
|
||||||
|
document.addEventListener('mouseup', onMouseUp);
|
||||||
|
});
|
||||||
|
|
||||||
|
function onMouseMove(e) {
|
||||||
|
if (isDragging) {
|
||||||
|
// Calculate the new position of the element
|
||||||
|
const left = e.clientX - offsetX;
|
||||||
|
const top = e.clientY - offsetY;
|
||||||
|
|
||||||
|
// Move the element by setting its style
|
||||||
|
draggableElement.style.left = `${left}px`;
|
||||||
|
draggableElement.style.top = `${top}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseUp() {
|
||||||
|
// Stop dragging and remove event listeners
|
||||||
|
isDragging = false;
|
||||||
|
document.removeEventListener('mousemove', onMouseMove);
|
||||||
|
document.removeEventListener('mouseup', onMouseUp);
|
||||||
|
}
|
||||||
29
src/main/resources/static/js/fetch-utils.js
Normal file
29
src/main/resources/static/js/fetch-utils.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
window.fetchWithCsrf = async function(url, options = {}) {
|
||||||
|
function getCsrfToken() {
|
||||||
|
const cookieValue = document.cookie
|
||||||
|
.split('; ')
|
||||||
|
.find(row => row.startsWith('XSRF-TOKEN='))
|
||||||
|
?.split('=')[1];
|
||||||
|
|
||||||
|
if (cookieValue) {
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const csrfElement = document.querySelector('input[name="_csrf"]');
|
||||||
|
return csrfElement ? csrfElement.value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new options object to avoid modifying the passed object
|
||||||
|
const fetchOptions = { ...options };
|
||||||
|
|
||||||
|
// Ensure headers object exists
|
||||||
|
fetchOptions.headers = { ...options.headers };
|
||||||
|
|
||||||
|
// Add CSRF token if available
|
||||||
|
const csrfToken = getCsrfToken();
|
||||||
|
if (csrfToken) {
|
||||||
|
fetchOptions.headers['X-XSRF-TOKEN'] = csrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(url, fetchOptions);
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
const scrollDivHorizontally = (id) => {
|
|
||||||
var scrollDeltaX = 0; // variable to store the accumulated horizontal scroll delta
|
|
||||||
var scrollDeltaY = 0; // variable to store the accumulated vertical scroll delta
|
|
||||||
var isScrolling = false; // variable to track if scroll is already in progress
|
|
||||||
const divToScroll = document.getElementById(id);
|
|
||||||
|
|
||||||
function scrollLoop() {
|
|
||||||
// Scroll the div horizontally and vertically by a fraction of the accumulated scroll delta
|
|
||||||
divToScroll.scrollLeft += scrollDeltaX * 0.1;
|
|
||||||
divToScroll.scrollTop += scrollDeltaY * 0.1;
|
|
||||||
|
|
||||||
// Reduce the accumulated scroll delta by a fraction
|
|
||||||
scrollDeltaX *= 0.9;
|
|
||||||
scrollDeltaY *= 0.9;
|
|
||||||
|
|
||||||
// If scroll delta is still significant, continue the scroll loop
|
|
||||||
if (Math.abs(scrollDeltaX) > 0.1 || Math.abs(scrollDeltaY) > 0.1) {
|
|
||||||
requestAnimationFrame(scrollLoop);
|
|
||||||
} else {
|
|
||||||
isScrolling = false; // Reset scroll in progress flag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
divToScroll.addEventListener("wheel", function (e) {
|
|
||||||
e.preventDefault(); // prevent default mousewheel behavior
|
|
||||||
|
|
||||||
// Accumulate the horizontal and vertical scroll delta
|
|
||||||
scrollDeltaX -= e.deltaX || e.wheelDeltaX || -e.deltaY || -e.wheelDeltaY;
|
|
||||||
scrollDeltaY -= e.deltaY || e.wheelDeltaY || -e.deltaX || -e.wheelDeltaX;
|
|
||||||
|
|
||||||
// If scroll is not already in progress, start the scroll loop
|
|
||||||
if (!isScrolling) {
|
|
||||||
isScrolling = true;
|
|
||||||
requestAnimationFrame(scrollLoop);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default scrollDivHorizontally;
|
|
||||||
@@ -119,7 +119,7 @@ document.getElementById("submitConfigBtn").addEventListener("click", function ()
|
|||||||
formData.append("json", pipelineConfigJson);
|
formData.append("json", pipelineConfigJson);
|
||||||
console.log("formData", formData);
|
console.log("formData", formData);
|
||||||
|
|
||||||
fetch("api/v1/pipeline/handleData", {
|
fetchWithCsrf("api/v1/pipeline/handleData", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
@@ -154,7 +154,7 @@ let apiDocs = {};
|
|||||||
let apiSchemas = {};
|
let apiSchemas = {};
|
||||||
let operationSettings = {};
|
let operationSettings = {};
|
||||||
|
|
||||||
fetch("v1/api-docs")
|
fetchWithCsrf("v1/api-docs")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
apiDocs = data.paths;
|
apiDocs = data.paths;
|
||||||
|
|||||||
@@ -283,25 +283,5 @@
|
|||||||
</script>
|
</script>
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${oAuth2Enabled}" class="modal fade" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="editUserModalLabel" th:text="#{login.ssoSignIn}"></h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
|
||||||
<span class="material-symbols-rounded">close</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="mb-3" th:each="provider : ${providerlist}">
|
|
||||||
<a th:href="@{|/oauth2/authorization/${provider.key}|}" th:text="${provider.value}" class="w-100 btn btn-lg btn-primary">OpenID Connect</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" th:text="#{close}"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<!-- Change Username Form -->
|
<!-- Change Username Form -->
|
||||||
<h4 th:text="#{changeCreds.changePassword}">Change password</h4>
|
<h4 th:text="#{changeCreds.changePassword}">Change password</h4>
|
||||||
<form action="api/v1/user/change-password-on-login" method="post" id="formsavechangecreds">
|
<form th:action="@{'api/v1/user/change-password-on-login'}" method="post" id="formsavechangecreds">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="currentPassword" th:text="#{changeCreds.oldPassword}">Old Password</label>
|
<label for="currentPassword" th:text="#{changeCreds.oldPassword}">Old Password</label>
|
||||||
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{changeCreds.oldPassword}">
|
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{changeCreds.oldPassword}">
|
||||||
|
|||||||
@@ -351,7 +351,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="searchDropdown">
|
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="searchDropdown">
|
||||||
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
||||||
<form class="d-flex p-2 search-form" id="searchForm">
|
<form th:action="@{''}" class="d-flex p-2 search-form" id="searchForm">
|
||||||
<input class="form-control search-input" type="search" placeholder="Search" aria-label="Search" id="navbarSearchInput">
|
<input class="form-control search-input" type="search" placeholder="Search" aria-label="Search" id="navbarSearchInput">
|
||||||
</form>
|
</form>
|
||||||
<!-- Search Results -->
|
<!-- Search Results -->
|
||||||
@@ -360,7 +360,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item" th:if="${!@runningEE}">
|
||||||
<a href="https://stirlingpdf.com/pricing" class="nav-link go-pro-link" target="_blank" rel="noopener noreferrer">
|
<a href="https://stirlingpdf.com/pricing" class="nav-link go-pro-link" target="_blank" rel="noopener noreferrer">
|
||||||
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user