Compare commits

...

56 Commits

Author SHA1 Message Date
github-actions[bot]
384c3ee88f 💾 Update Version (#2139)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-31 13:06:55 +00:00
Anthony Stirling
5f7a0537f9 Update build.gradle 2024-10-31 13:06:12 +00:00
Anthony Stirling
5aa5628465 [bug fix] Update compress-pdf.html (#2138)
Update compress-pdf.html
2024-10-31 10:59:51 +00:00
albanobattistella
0d91bca932 Update messages_it_IT.properties (#2135) 2024-10-30 19:55:54 +00:00
Ludovic Ortega
8e88591499 chore(helm): bump chart version according to semver (#2109)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-10-30 13:49:28 +00:00
github-actions[bot]
3e051d0105 Update 3rd Party Licenses (#2134)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-30 13:00:51 +00:00
dependabot[bot]
4a9b16ff8f Bump org.springframework.security:spring-security-saml2-service-provider from 6.3.3 to 6.3.4 (#2052)
Bump org.springframework.security:spring-security-saml2-service-provider

Bumps [org.springframework.security:spring-security-saml2-service-provider](https://github.com/spring-projects/spring-security) from 6.3.3 to 6.3.4.
- [Release notes](https://github.com/spring-projects/spring-security/releases)
- [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-projects/spring-security/compare/6.3.3...6.3.4)

---
updated-dependencies:
- dependency-name: org.springframework.security:spring-security-saml2-service-provider
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-30 12:58:47 +00:00
github-actions[bot]
a7082ecd85 💾 Update Version (#2132)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-30 12:48:44 +00:00
github-actions[bot]
966e6a4923 📝 Update README: Translation Progress Table (#2133)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-30 12:48:30 +00:00
Anthony Stirling
27d2681a97 Feature/save signs (#2127)
* apply fix

* Fixes empty th:action

* Update build.gradle

* fix

* formatting

* Save signatures

* Fix code scanning alert no. 42: Uncontrolled data used in path expression

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix UserServiceInterface

* Merge branch 'feature/saveSigns' of
git@github.com:Stirling-Tools/Stirling-PDF.git into feature/saveSigns

* 0.31.0 bump and further csrf

* formatting

* preview name

* add

* sign doc

* Update translation files (#2128)

Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>

---------

Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: Dimitrios Kaitantzidis <james_k23@hotmail.gr>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: a <a>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-30 12:46:44 +00:00
github-actions[bot]
ed75fa4e1b 📝 Update README: Translation Progress Table (#2129)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-29 19:05:01 +00:00
Rania Amina
9b9752bd7a Update id_ID Translation and fix some grammars (#2108)
* Update id_ID Translation and fix some grammars

* sync lines to fix build warning

* get back new line at end of file

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-10-29 19:03:00 +00:00
Anthony Stirling
903dc7638c Fix csrf (#2126)
* apply fix

* Fixes empty th:action

* Update build.gradle

* fix

* formatting

---------

Co-authored-by: Dimitrios Kaitantzidis <james_k23@hotmail.gr>
2024-10-29 17:56:29 +00:00
github-actions[bot]
c39b111edc 📝 Update README: Translation Progress Table (#2121)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-29 16:31:25 +00:00
github-actions[bot]
d910929aa6 Update translation files (#2125)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-29 16:30:44 +00:00
reecebrowne
a9ce0e80ee Feature/298 improve compare performance (#2124)
* Implement Diff.js

* Compare feature - add service worker and improve efficiency for large files

* Compare - messages updated to be compatable with language packs

* Compare - Acknowledge Diff.js usage

* Add message warning there is  no text in uploaded pdf to messages file

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-10-29 15:56:45 +00:00
Florian Fish
4922ab700e Add new french translations (#2120)
Add new french translations and improve simple quote
2024-10-29 10:12:49 +00:00
github-actions[bot]
01f3c138a6 Update 3rd Party Licenses (#2119)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-28 23:22:15 +00:00
github-actions[bot]
4e21f76979 📝 Update README: Translation Progress Table (#2103)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-28 23:22:02 +00:00
dependabot[bot]
a9ccd85e75 Bump org.springframework.boot from 3.3.4 to 3.3.5 (#2118)
Bumps [org.springframework.boot](https://github.com/spring-projects/spring-boot) from 3.3.4 to 3.3.5.
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

---
updated-dependencies:
- dependency-name: org.springframework.boot
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-28 23:19:59 +00:00
dependabot[bot]
6f407f1d2f Bump springBootVersion from 3.3.4 to 3.3.5 (#2117)
Bumps `springBootVersion` from 3.3.4 to 3.3.5.

Updates `org.springframework.boot:spring-boot-starter-web` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-jetty` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-security` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-data-jpa` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-oauth2-client` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-test` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

Updates `org.springframework.boot:spring-boot-devtools` from 3.3.4 to 3.3.5
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5)

---
updated-dependencies:
- dependency-name: org.springframework.boot:spring-boot-starter-web
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-jetty
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-security
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-data-jpa
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-oauth2-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-test
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-actuator
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-devtools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-28 23:19:36 +00:00
pixeebot[bot]
af5e2b6895 Modernize and secure temp file creation (#2106)
Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>
2024-10-28 23:19:12 +00:00
Ludy
d2046c64d8 Optimierung der SAML2-Integration und Verbesserung der Zertifikats- und Fehlerbehandlung (#2105)
* certificate processing

* Hides dialog when provider list is empty

* removed: unused
2024-10-27 22:17:36 +00:00
Manuel Mora Gordillo
1b88d89191 Spanish translate (#2102)
* Spanish translate

* Added blank line

---------

Co-authored-by: Manu <manuel@fusiontelecom.co>
2024-10-25 13:20:13 +01:00
github-actions[bot]
03bf98265b 📝 Update README: Translation Progress Table (#2072)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-24 14:21:17 +01:00
Anthony Stirling
89da2a5c01 Auto detect presence of external dependencies (LibreOffice etc) and disable/enable features dynamically (#2082)
* Create ExternalAppDepConfig.java

* Update EndpointConfiguration.java

* Hardening suggestions for Stirling-PDF / ExternalAppDepConfig (#2083)

Switch order of literals to prevent NullPointerException

Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>

---------

Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>
2024-10-24 13:59:17 +01:00
swanemar
a10d06b693 added some missing translations (#2085) 2024-10-24 10:35:32 +00:00
Eric
a7ed99084f visual certificate signing (#2084)
add visual digital signature
2024-10-24 07:08:09 +01:00
github-actions[bot]
88f3594d80 Update 3rd Party Licenses (#2080)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-23 12:28:58 +01:00
Eric
e0b77ca274 extract and apply the image orientation from exif data in imageToPdf (#2073) 2024-10-23 12:17:40 +01:00
albanobattistella
bac81c930d Update messages_it_IT.properties (#2077) 2024-10-23 12:16:49 +01:00
Corbinian Grimm
2f49626a4c Update messages_de_DE.properties (#2070)
* Update messages_de_DE.properties

Completed translations for German language.

* Update messages_de_DE.properties
2024-10-22 21:53:13 +01:00
Anthony Stirling
83ef003505 Update PostHogService.java 2024-10-22 15:36:54 +01:00
Anthony Stirling
949b87005c Fix metricCollection 2024-10-22 15:36:22 +01:00
a
532f7cdbbf Merge branch 'main' of git@github.com:Stirling-Tools/Stirling-PDF.git into main 2024-10-22 12:22:20 +01:00
Anthony Stirling
51c4a60313 Remove pro badge if enabled 2024-10-22 12:22:08 +01:00
reecebrowne
aa00808219 Removed horizontal scroll logic from multi-tool template (#2065)
* Removed horizontal scroll logic from multi-tool template

* Remove unused horizontalScroll.js
2024-10-22 12:02:00 +01:00
github-actions[bot]
5d40175e18 💾 Update Version (#2064)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-22 11:30:59 +01:00
Anthony Stirling
a40fdd5a0b Fixes for analyticsPrompt 2024-10-22 11:10:09 +01:00
github-actions[bot]
6ea7ffc36c 📝 Update README: Translation Progress Table (#2062)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-22 09:54:46 +01:00
Thomas BERNARD
39e0fd8eef French translation improvements (#2061)
* fix a spelling mistake in a french message

n'importe quel fichier au singulier

* Translate "Remove Certificate Sign" to French

* french translation for pdfToPDFA.pdfWithDigitalSignature

* fix french translation for BootToPDF and PDFToBook

* Translate "Remove image" to French

* Translate "Split PDF by Chapters" to French

* fr translation : Popular => Populaire

* french translation for adminUserSettings.* messages

* french translation for session.expired
2024-10-22 08:11:48 +01:00
Anthony Stirling
cae8cd0aa9 Add on hover color to sign (#2059)
* Fixed layering issue with z-index, and added smoother transitions for… (#1996)

Fixed layering issue with z-index, and added smoother transitions for signing

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>

* Delete package-lock.json

---------

Co-authored-by: Surya Karthikeyan Vijayalakshmi <108506548+SuryaKV101@users.noreply.github.com>
2024-10-22 00:44:22 +01:00
Anthony Stirling
04d5ae1912 Default terms and conditions to stirlingpdf.com (#2058) 2024-10-22 00:42:17 +01:00
github-actions[bot]
e01ba93cf8 Update 3rd Party Licenses (#2057)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-22 00:41:44 +01:00
github-actions[bot]
edd0ec9d23 Update 3rd Party Licenses (#2056)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-22 00:22:01 +01:00
dependabot[bot]
899f3d267b Bump org.commonmark:commonmark from 0.23.0 to 0.24.0 (#2054)
Bumps [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) from 0.23.0 to 0.24.0.
- [Release notes](https://github.com/commonmark/commonmark-java/releases)
- [Changelog](https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md)
- [Commits](https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.23.0...commonmark-parent-0.24.0)

---
updated-dependencies:
- dependency-name: org.commonmark:commonmark
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 00:21:14 +01:00
dependabot[bot]
88c0a9e26b Bump org.springframework:spring-webmvc from 6.1.13 to 6.1.14 (#2053)
Bumps [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) from 6.1.13 to 6.1.14.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.13...v6.1.14)

---
updated-dependencies:
- dependency-name: org.springframework:spring-webmvc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 00:19:52 +01:00
dependabot[bot]
dc6cec9daf Bump org.commonmark:commonmark-ext-gfm-tables from 0.23.0 to 0.24.0 (#2055)
Bumps [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) from 0.23.0 to 0.24.0.
- [Release notes](https://github.com/commonmark/commonmark-java/releases)
- [Changelog](https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md)
- [Commits](https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.23.0...commonmark-parent-0.24.0)

---
updated-dependencies:
- dependency-name: org.commonmark:commonmark-ext-gfm-tables
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 00:19:14 +01:00
github-actions[bot]
a64dd2e282 📝 Update README: Translation Progress Table (#2047)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-20 21:02:09 +01:00
github-actions[bot]
c9b7d848b4 Update translation files (#2048)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-20 21:01:50 +01:00
Anthony Stirling
89a9ba6ebc remove unused translation 2024-10-20 21:00:16 +01:00
Patryk Marszelewski
22249ef9bf Update messages_pl_PL.properties (#2042) 2024-10-20 20:34:39 +01:00
github-actions[bot]
619a863b99 Update 3rd Party Licenses (#2044)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-10-20 20:32:57 +01:00
Peter Dave Hello
e098b2999c Update and improve zh_TW Traditional Chinese locale (#2046)
This is a small follow-up to #2030, but it will significantly improve the user experience for Traditional Chinese users.
2024-10-20 20:32:40 +01:00
IT Creativity + Art Team
1149f2a30d Update messages_bg_BG.properties (#2045)
Update messages_bg_BG.properties
2024-10-20 20:32:18 +01:00
Ludy
eff1843061 Major Enhancements to SAML2 and OAuth2 Integration with Simplified Security Configurations (#2040)
* implement Saml2 login/logout

* changed: deprecation code

* relyingPartyRegistrations only enabled samle
2024-10-20 12:30:58 +01:00
123 changed files with 6291 additions and 2530 deletions

View File

@@ -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
View File

@@ -4,6 +4,7 @@ bin/
tmp/ tmp/
*.tmp *.tmp
*.bak *.bak
*.exe
*.swp *.swp
*~.nib *~.nib
local.properties local.properties

View File

@@ -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) | ![93%](https://geps.dev/progress/93) | | Arabic (العربية) (ar_AR) | ![93%](https://geps.dev/progress/93) |
| Basque (Euskara) (eu_ES) | ![57%](https://geps.dev/progress/57) | | Basque (Euskara) (eu_ES) | ![56%](https://geps.dev/progress/56) |
| Bulgarian (Български) (bg_BG) | ![86%](https://geps.dev/progress/86) | | Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) |
| Catalan (Català) (ca_CA) | ![44%](https://geps.dev/progress/44) | | Catalan (Català) (ca_CA) | ![44%](https://geps.dev/progress/44) |
| Croatian (Hrvatski) (hr_HR) | ![87%](https://geps.dev/progress/87) | | Croatian (Hrvatski) (hr_HR) | ![86%](https://geps.dev/progress/86) |
| Czech (Česky) (cs_CZ) | ![82%](https://geps.dev/progress/82) | | Czech (Česky) (cs_CZ) | ![82%](https://geps.dev/progress/82) |
| Danish (Dansk) (da_DK) | ![91%](https://geps.dev/progress/91) | | Danish (Dansk) (da_DK) | ![90%](https://geps.dev/progress/90) |
| Dutch (Nederlands) (nl_NL) | ![88%](https://geps.dev/progress/88) | | Dutch (Nederlands) (nl_NL) | ![87%](https://geps.dev/progress/87) |
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| French (Français) (fr_FR) | ![85%](https://geps.dev/progress/85) | | French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) |
| German (Deutsch) (de_DE) | ![93%](https://geps.dev/progress/93) | | German (Deutsch) (de_DE) | ![97%](https://geps.dev/progress/97) |
| Greek (Ελληνικά) (el_GR) | ![75%](https://geps.dev/progress/75) | | Greek (Ελληνικά) (el_GR) | ![75%](https://geps.dev/progress/75) |
| Hindi (हिंदी) (hi_IN) | ![72%](https://geps.dev/progress/72) | | Hindi (हिंदी) (hi_IN) | ![71%](https://geps.dev/progress/71) |
| Hungarian (Magyar) (hu_HU) | ![69%](https://geps.dev/progress/69) | | Hungarian (Magyar) (hu_HU) | ![69%](https://geps.dev/progress/69) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![70%](https://geps.dev/progress/70) | | Indonesia (Bahasa Indonesia) (id_ID) | ![95%](https://geps.dev/progress/95) |
| Irish (Gaeilge) (ga_IE) | ![90%](https://geps.dev/progress/90) | | Irish (Gaeilge) (ga_IE) | ![89%](https://geps.dev/progress/89) |
| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | | Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
| Japanese (日本語) (ja_JP) | ![87%](https://geps.dev/progress/87) | | Japanese (日本語) (ja_JP) | ![86%](https://geps.dev/progress/86) |
| Korean (한국어) (ko_KR) | ![77%](https://geps.dev/progress/77) | | Korean (한국어) (ko_KR) | ![76%](https://geps.dev/progress/76) |
| Norwegian (Norsk) (no_NB) | ![90%](https://geps.dev/progress/90) | | Norwegian (Norsk) (no_NB) | ![89%](https://geps.dev/progress/89) |
| Polish (Polski) (pl_PL) | ![84%](https://geps.dev/progress/84) | | Polish (Polski) (pl_PL) | ![98%](https://geps.dev/progress/98) |
| Portuguese (Português) (pt_PT) | ![72%](https://geps.dev/progress/72) | | Portuguese (Português) (pt_PT) | ![71%](https://geps.dev/progress/71) |
| Portuguese Brazilian (Português) (pt_BR) | ![99%](https://geps.dev/progress/99) | | Portuguese Brazilian (Português) (pt_BR) | ![98%](https://geps.dev/progress/98) |
| Romanian (Română) (ro_RO) | ![92%](https://geps.dev/progress/92) | | Romanian (Română) (ro_RO) | ![91%](https://geps.dev/progress/91) |
| Russian (Русский) (ru_RU) | ![77%](https://geps.dev/progress/77) | | Russian (Русский) (ru_RU) | ![76%](https://geps.dev/progress/76) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![72%](https://geps.dev/progress/72) | | Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![71%](https://geps.dev/progress/71) |
| Simplified Chinese (简体中文) (zh_CN) | ![93%](https://geps.dev/progress/93) | | Simplified Chinese (简体中文) (zh_CN) | ![92%](https://geps.dev/progress/92) |
| Slovakian (Slovensky) (sk_SK) | ![84%](https://geps.dev/progress/84) | | Slovakian (Slovensky) (sk_SK) | ![83%](https://geps.dev/progress/83) |
| Spanish (Español) (es_ES) | ![93%](https://geps.dev/progress/93) | | Spanish (Español) (es_ES) | ![97%](https://geps.dev/progress/97) |
| Swedish (Svenska) (sv_SE) | ![92%](https://geps.dev/progress/92) | | Swedish (Svenska) (sv_SE) | ![93%](https://geps.dev/progress/93) |
| Thai (ไทย) (th_TH) | ![91%](https://geps.dev/progress/91) | | Thai (ไทย) (th_TH) | ![90%](https://geps.dev/progress/90) |
| Traditional Chinese (繁體中文) (zh_TW) | ![99%](https://geps.dev/progress/99) | | Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) |
| Turkish (Türkçe) (tr_TR) | ![94%](https://geps.dev/progress/94) | | Turkish (Türkçe) (tr_TR) | ![93%](https://geps.dev/progress/93) |
| Ukrainian (Українська) (uk_UA) | ![82%](https://geps.dev/progress/82) | | Ukrainian (Українська) (uk_UA) | ![81%](https://geps.dev/progress/81) |
| Vietnamese (Tiếng Việt) (vi_VN) | ![90%](https://geps.dev/progress/90) | | Vietnamese (Tiếng Việt) (vi_VN) | ![90%](https://geps.dev/progress/90) |
## Contributing (creating issues, translations, fixing bugs, etc.) ## Contributing (creating issues, translations, fixing bugs, etc.)

View File

@@ -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"

View File

@@ -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

View 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

View File

@@ -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")

View File

@@ -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;
} }

View File

@@ -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

View File

@@ -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";
} }

View File

@@ -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();
}
}

View File

@@ -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);
}
}
} }

View File

@@ -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 ]", "");
} }
} }

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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();
}
} }

View File

@@ -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);

View File

@@ -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(

View File

@@ -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 ]", "");
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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 "/";
}
}

View File

@@ -1,7 +0,0 @@
package stirling.software.SPDF.config.security.saml;
public interface Saml2AuthorityAttributeLookup {
String getAuthorityAttribute(String registrationId);
SimpleScimMappings getIdentityMappings(String registrationId);
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -1,10 +0,0 @@
package stirling.software.SPDF.config.security.saml;
import lombok.Data;
@Data
public class SimpleScimMappings {
String givenName;
String familyName;
String email;
}

View File

@@ -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));
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
} }

View File

@@ -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");
} }
} }

View File

@@ -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;
} }

View File

@@ -4,4 +4,6 @@ public interface UserServiceInterface {
String getApiKeyForUser(String username); String getApiKeyForUser(String username);
String getCurrentUsername(); String getCurrentUsername();
long getTotalUsersCount();
} }

View File

@@ -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);

View File

@@ -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 =

View File

@@ -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";
} }

View File

@@ -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);
}
}

View File

@@ -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);
} }
} }
} }

View File

@@ -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'");
} }
} }

View File

@@ -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"
}

View File

@@ -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());
} }

View File

@@ -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");
}
}
}

View File

@@ -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);
}
} }

View File

@@ -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

View File

@@ -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);

View 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);

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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= yes=
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

View File

@@ -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

View File

@@ -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 dattendre ? 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 na 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 dutilisateur 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 dutilisateur existe déjà. usernameExistsMessage=Le nouveau nom d'utilisateur existe déjà.
invalidUsernameMessage=Nom dutilisateur invalide, le nom dutilisateur 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 lutilisateur actuellement connecté. deleteCurrentUserMessage=Impossible de supprimer l'utilisateur actuellement connecté.
deleteUsernameExistsMessage=Le nom dutilisateur nexiste 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 daccueil 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 lapplication : settings.appVersion=Version de l'application :
settings.downloadOption.title=Choisissez loption 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 dutilisateur 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 dadministration 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 dutilisateur account.changeUsername=Modifier le nom d'utilisateur
account.newUsername=Nouveau nom dutilisateur 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 lAPI 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 lutilisateur à changer son nom dutilisateur/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 nimporte 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 dauteur,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 nimporte 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 lOCR pour analyser et détecter le texte des images dun 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 dun 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 dune photo ou dun 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 dun 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 dun 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 dun 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 dun 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 dune 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é dun 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 nimporte 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 nimporte 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 nimporte 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 dun 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 dun 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 dun 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 dun 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 limage dun 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 dutilisateur 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 laffichage 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 limage de fond des sites web. HTMLToPDF.printBackground=Restituer l'image de fond des sites web.
HTMLToPDF.defaultHeader=Activer lentê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 soccuper 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 dune 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) dune 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 nest pas listé ci-dessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant loutil en ligne de commande keytool. Puis choisissez loption 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, sil nest 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 langle absolu minimum requis pour la rotation de limage (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 darriè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 : 8000). ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut : 8000).
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 quil soit moins probable que lOCR 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 quil soit moins probable que lOCR 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, nanalyser 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 lOCR, analyser chaque page et supprimer tous les éléments de texte dorigine 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 lOCR (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 lOCR pour dautres 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 lOCR. 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 dimage 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 cest possible!) compress.header=Compresser un PDF (lorsque c'est possible!)
compress.credit=Ce service utilise Ghostscript pour la compression et loptimisation 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 doptimisation 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, 25MB, 10,8MB, 25KB) compress.selectText.5=Taille PDF attendue (par exemple, 25MB, 10,8MB, 25KB)
@@ -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 dajustement de limage imageToPDF.selectLabel=Options d'ajustement de l'image
imageToPDF.fillPage=Remplir la page imageToPDF.fillPage=Remplir la page
imageToPDF.fitDocumentToImage=Ajuster la page à limage 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 dimage 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 dimpression 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 lutilisateur 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 lassemblage du document addPassword.selectText.6=Empêcher l'assemblage du document
addPassword.selectText.7=Empêcher lextraction de contenu addPassword.selectText.7=Empêcher l'extraction de contenu
addPassword.selectText.8=Empêcher lextraction pour laccessibilité 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 limpression addPassword.selectText.12=Empêcher l'impression
addPassword.selectText.13=Empêcher limpression 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 quil 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 louverture 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 lassemblage du document permissions.selectText.3=Empêcher l'assemblage du document
permissions.selectText.4=Empêcher lextraction de contenu permissions.selectText.4=Empêcher l'extraction de contenu
permissions.selectText.5=Empêcher lextraction pour laccessibilité 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 limpression permissions.selectText.9=Empêcher l'impression
permissions.selectText.10=Empêcher limpression 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 dimpression) 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 dincrustation 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 lincrustation 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 daide / 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, nhésitez pas à nous contacter pour obtenir de laide. 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 sest 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 na 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 dassistance 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
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

View 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=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

View File

@@ -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

View 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=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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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"
}, },

View File

@@ -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;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load Diff

View 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;
}

View 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);
}

View 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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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>

View File

@@ -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}">

View File

@@ -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