Compare commits

...

46 Commits

Author SHA1 Message Date
pixeebot[bot]
b094634799 Hardening suggestions for Stirling-PDF / fix-sig-logo (#2144)
Modernize and secure temp file creation

Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>
2024-10-31 16:17:23 -04:00
sbplat
9e597a4390 fix signature logo not loading and add option to disable it 2024-10-31 16:06:36 -04:00
Anthony Stirling
febc3cf48b Update pull_request_template.md 2024-10-31 17:46:30 +00:00
Philip H.
c5abb47403 navbar.css: prevent overlapping of elements (#2140)
go-pro-link is overlapping the settings button
2024-10-31 17:45:44 +00:00
Anthony Stirling
0e3c9bcc10 Update README.md 2024-10-31 14:52:41 +00:00
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
98 changed files with 4654 additions and 1163 deletions

View File

@@ -8,6 +8,7 @@ Closes #(issue_number)
- [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have performed a self-review of my own code - [ ] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings - [ ] My changes generate no new warnings
- [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only)

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

108
README.md
View File

@@ -166,48 +166,55 @@ 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!
| Language | Progress | | Language | Progress |
| ------------------------------------------- | -------------------------------------- | | ------------------------------------------- | -------------------------------------- |
| Arabic (العربية) (ar_AR) | ![94%](https://geps.dev/progress/94) | | 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) | ![99%](https://geps.dev/progress/99) | | 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) | ![83%](https://geps.dev/progress/83) | | 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) | ![94%](https://geps.dev/progress/94) | | 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) | ![99%](https://geps.dev/progress/99) | | 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) | ![91%](https://geps.dev/progress/91) | | 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.)
@@ -273,14 +280,44 @@ 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
enterpriseEdition:
enabled: false # set to 'true' to enable enterprise edition
key: 00000000-0000-0000-0000-000000000000
CustomMetadata:
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 to autopopulate with users username
creator: Stirling-PDF # Supports text such as 'Company-PDF'
producer: Stirling-PDF # Supports text such as 'Company-PDF'
legal:
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: 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
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
system: system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc) defaultLocale: en-US # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: true # see when a new update is available showUpdate: false # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
tessdataDir: /usr/share/tessdata # Path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored.
enableAnalytics: undefined # Set to 'true' to enable analytics, set to 'false' to disable analytics, for enterprise users this is set to true
ui: ui:
appName: '' # Application's visible name appName: '' # Application's visible name
@@ -293,6 +330,11 @@ endpoints:
metrics: metrics:
enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
# Automatically Generated Settings (Do Not Edit Directly)
AutomaticallyGenerated:
key: example
UUID: example
``` ```
There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones

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
@@ -137,11 +137,11 @@ 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"
@@ -154,6 +154,8 @@ dependencies {
implementation "org.springframework.security:spring-security-saml2-service-provider" implementation "org.springframework.security:spring-security-saml2-service-provider"
implementation 'com.coveo:saml-client:5.0.0' 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"
@@ -179,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

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

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

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

@@ -9,6 +9,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import io.micrometer.common.util.StringUtils; 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;
@@ -40,7 +41,7 @@ public class InitialSetup {
applicationProperties.getAutomaticallyGenerated().setKey(secretKey); applicationProperties.getAutomaticallyGenerated().setKey(secretKey);
} }
} }
@PostConstruct @PostConstruct
public void initLegalUrls() throws IOException { public void initLegalUrls() throws IOException {
// Initialize Terms and Conditions // Initialize Terms and Conditions
@@ -59,7 +60,4 @@ public class InitialSetup {
applicationProperties.getLegal().setPrivacyPolicy(defaultPrivacyUrl); applicationProperties.getLegal().setPrivacyPolicy(defaultPrivacyUrl);
} }
} }
} }

View File

@@ -36,6 +36,8 @@ import org.springframework.security.saml2.provider.service.web.authentication.Sa
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;
@@ -94,6 +96,41 @@ public class SecurityConfiguration {
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);
@@ -113,6 +150,7 @@ public class SecurityConfiguration {
logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessHandler( .logoutSuccessHandler(
new CustomLogoutSuccessHandler(applicationProperties)) new CustomLogoutSuccessHandler(applicationProperties))
.clearAuthentication(true)
.invalidateHttpSession(true) // Invalidate session .invalidateHttpSession(true) // Invalidate session
.deleteCookies("JSESSIONID", "remember-me")); .deleteCookies("JSESSIONID", "remember-me"));
http.rememberMe( http.rememberMe(
@@ -203,7 +241,8 @@ public class SecurityConfiguration {
} }
// Handle SAML // Handle SAML
if (applicationProperties.getSecurity().isSaml2Activ() && applicationProperties.getSystem().getEnableAlphaFunctionality()) { if (applicationProperties.getSecurity().isSaml2Activ()
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
http.authenticationProvider(samlAuthenticationProvider()); http.authenticationProvider(samlAuthenticationProvider());
http.saml2Login( http.saml2Login(
saml2 -> saml2 ->
@@ -222,6 +261,16 @@ public class SecurityConfiguration {
} 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());
} }

View File

@@ -45,7 +45,6 @@ public class UserService implements UserServiceInterface {
@Autowired DatabaseBackupInterface databaseBackupHelper; @Autowired DatabaseBackupInterface databaseBackupHelper;
// 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 {
@@ -360,8 +359,8 @@ public class UserService implements UserServiceInterface {
} }
} }
@Override @Override
public long getTotalUsersCount() { public long getTotalUsersCount() {
return userRepository.count(); return userRepository.count();
} }
} }

View File

@@ -1,48 +1,42 @@
package stirling.software.SPDF.config.security.saml2; package stirling.software.SPDF.config.security.saml2;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.util.FileCopyUtils;
public class CertificateUtils { public class CertificateUtils {
public static X509Certificate readCertificate(Resource certificateResource) throws Exception { public static X509Certificate readCertificate(Resource certificateResource) throws Exception {
String certificateString = try (PemReader pemReader =
new String( new PemReader(
FileCopyUtils.copyToByteArray(certificateResource.getInputStream()), new InputStreamReader(
StandardCharsets.UTF_8); certificateResource.getInputStream(), StandardCharsets.UTF_8))) {
String certContent = PemObject pemObject = pemReader.readPemObject();
certificateString byte[] decodedCert = pemObject.getContent();
.replace("-----BEGIN CERTIFICATE-----", "") CertificateFactory cf = CertificateFactory.getInstance("X.509");
.replace("-----END CERTIFICATE-----", "") return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert));
.replaceAll("\\R", "") }
.replaceAll("\\s+", "");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
byte[] decodedCert = Base64.getDecoder().decode(certContent);
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert));
} }
public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception { public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception {
String privateKeyString = try (PemReader pemReader =
new String( new PemReader(
FileCopyUtils.copyToByteArray(privateKeyResource.getInputStream()), new InputStreamReader(
StandardCharsets.UTF_8); privateKeyResource.getInputStream(), StandardCharsets.UTF_8))) {
String privateKeyContent = PemObject pemObject = pemReader.readPemObject();
privateKeyString byte[] decodedKey = pemObject.getContent();
.replace("-----BEGIN PRIVATE KEY-----", "") return (RSAPrivateKey)
.replace("-----END PRIVATE KEY-----", "") KeyFactory.getInstance("RSA")
.replaceAll("\\R", "") .generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
.replaceAll("\\s+", ""); }
KeyFactory kf = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.getDecoder().decode(privateKeyContent);
return (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
} }
} }

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

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

View File

@@ -1,10 +1,14 @@
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.nio.file.Files;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@@ -14,12 +18,39 @@ 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.commons.io.FileUtils;
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 +66,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 +94,8 @@ public class CertSignController {
} }
class CreateSignature extends CreateSignatureBase { class CreateSignature extends CreateSignatureBase {
File logoFile;
public CreateSignature(KeyStore keystore, char[] pin) public CreateSignature(KeyStore keystore, char[] pin)
throws KeyStoreException, throws KeyStoreException,
UnrecoverableKeyException, UnrecoverableKeyException,
@@ -69,6 +103,101 @@ public class CertSignController {
IOException, IOException,
CertificateException { CertificateException {
super(keystore, pin); super(keystore, pin);
ClassPathResource resource = new ClassPathResource("static/images/signature.png");
try (InputStream is = resource.getInputStream()) {
logoFile = Files.createTempFile("signature", ".png").toFile();
FileUtils.copyInputStreamToFile(is, logoFile);
} catch (IOException e) {
logger.error("Failed to load image signature file");
throw e;
}
}
public InputStream createVisibleSignature(
PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showLogo)
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 (showLogo) {
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(logoFile, 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 +226,8 @@ 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;
Boolean showLogo = request.isShowLogo();
if (certType == null) { if (certType == null) {
throw new IllegalArgumentException("Cert type must be provided"); throw new IllegalArgumentException("Cert type must be provided");
@@ -126,11 +256,19 @@ 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,
showLogo);
return WebResponseUtils.boasToWebResponse( return WebResponseUtils.boasToWebResponse(
baos, baos,
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "") Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
@@ -142,9 +280,12 @@ 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,
Boolean showLogo) {
try (PDDocument doc = pdfDocumentFactory.load(input)) { try (PDDocument doc = pdfDocumentFactory.load(input)) {
PDSignature signature = new PDSignature(); PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
@@ -154,7 +295,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, showLogo));
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

@@ -89,10 +89,9 @@ public class AccountWebController {
} }
SAML2 saml2 = securityProps.getSaml2(); SAML2 saml2 = securityProps.getSaml2();
if (saml2 != null) { if (securityProps.isSaml2Activ()
if (saml2.getEnabled()) { && applicationProperties.getSystem().getEnableAlphaFunctionality()) {
providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2"); 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
@@ -101,7 +100,8 @@ public class AccountWebController {
model.addAttribute("providerlist", providerList); model.addAttribute("providerlist", providerList);
model.addAttribute("loginMethod", securityProps.getLoginMethod()); model.addAttribute("loginMethod", securityProps.getLoginMethod());
model.addAttribute("altLogin", securityProps.isAltLogin()); boolean altLogin = providerList.size() > 0 ? securityProps.isAltLogin() : false;
model.addAttribute("altLogin", altLogin);
model.addAttribute("currentPage", "login"); model.addAttribute("currentPage", "login");
@@ -164,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;
} }

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

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

@@ -50,4 +50,7 @@ public class SignPDFWithCertRequest extends PDFFile {
description = description =
"The page number where the signature should be visible. This is required if showSignature is set to true") "The page number where the signature should be visible. This is required if showSignature is set to true")
private Integer pageNumber; private Integer pageNumber;
@Schema(description = "Whether to visually show a signature logo along with the signature")
private boolean showLogo;
} }

View File

@@ -29,12 +29,12 @@ public class PostHogService {
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final UserServiceInterface userService; private final UserServiceInterface userService;
@Autowired @Autowired
public PostHogService( public PostHogService(
PostHog postHog, PostHog postHog,
@Qualifier("UUID") String uuid, @Qualifier("UUID") String uuid,
ApplicationProperties applicationProperties, @Autowired(required = false) UserServiceInterface userService) { 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;
@@ -43,7 +43,7 @@ public class PostHogService {
} }
private void captureSystemInfo() { private void captureSystemInfo() {
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) { if (!Boolean.parseBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
return; return;
} }
try { try {
@@ -54,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);
@@ -137,10 +137,9 @@ public class PostHogService {
metrics.put("docker_metrics", getDockerMetrics()); metrics.put("docker_metrics", getDockerMetrics());
} }
metrics.put("application_properties", captureApplicationProperties()); metrics.put("application_properties", captureApplicationProperties());
if (userService != null) {
if(userService != null) { metrics.put("total_users_created", userService.getTotalUsersCount());
metrics.put("total_users_created", userService.getTotalUsersCount());
} }
} catch (Exception e) { } catch (Exception e) {

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
@@ -782,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
@@ -804,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
@@ -1220,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=Страница
pages=Страници pages=Страници
loading=Loading...
addToDoc=Add to Document
legal.privacy=Политика за поверителност legal.privacy=Политика за поверителност
legal.terms=Правила и условия legal.terms=Правила и условия
@@ -782,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
@@ -804,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
@@ -1220,5 +1230,3 @@ splitByChapters.desc.2=Ниво на отметка: Изберете нивот
splitByChapters.desc.3=Включване на метаданни: Ако е отметнато, метаданните на оригиналния PDF ще бъдат включени във всеки разделен PDF. splitByChapters.desc.3=Включване на метаданни: Ако е отметнато, метаданните на оригиналния PDF ще бъдат включени във всеки разделен PDF.
splitByChapters.desc.4=Разрешаване на дубликати: Ако е отметнато, позволява множество отметки на една и съща страница за създаване на отделни PDF файлове. splitByChapters.desc.4=Разрешаване на дубликати: Ако е отметнато, позволява множество отметки на една и съща страница за създаване на отделни PDF файлове.
splitByChapters.submit=Разделяне на PDF splitByChapters.submit=Разделяне на PDF

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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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,9 +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
#auto-redact #auto-redact
autoRedact.title=Automatisch zensieren/schwärzen autoRedact.title=Automatisch zensieren/schwärzen
@@ -703,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)
@@ -782,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
@@ -804,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
@@ -1210,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -748,6 +750,7 @@ certSign.showSig=Show Signature
certSign.reason=Reason certSign.reason=Reason
certSign.location=Location certSign.location=Location
certSign.name=Name certSign.name=Name
certSign.showLogo=Show Logo
certSign.submit=Sign PDF certSign.submit=Sign PDF
@@ -782,6 +785,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
@@ -804,6 +810,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
@@ -1220,5 +1231,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
@@ -748,6 +750,7 @@ certSign.showSig=Show Signature
certSign.reason=Reason certSign.reason=Reason
certSign.location=Location certSign.location=Location
certSign.name=Name certSign.name=Name
certSign.showLogo=Show Logo
certSign.submit=Sign PDF certSign.submit=Sign PDF
@@ -782,6 +785,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
@@ -804,6 +810,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
@@ -1220,5 +1231,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,9 +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
#auto-redact #auto-redact
autoRedact.title=Auto Redactar autoRedact.title=Auto Redactar
@@ -782,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
@@ -804,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
@@ -887,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
@@ -1210,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
@@ -782,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
@@ -804,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
@@ -1220,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,10 +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.
#auto-redact #auto-redact
autoRedact.title=Caviarder automatiquement autoRedact.title=Caviarder automatiquement
@@ -617,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
@@ -703,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
@@ -725,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
@@ -737,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
@@ -752,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
@@ -782,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
@@ -804,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
@@ -821,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
@@ -839,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
@@ -872,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)
@@ -960,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)
@@ -973,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 !)
@@ -989,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
@@ -1031,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
@@ -1063,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
@@ -1076,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
@@ -1138,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
@@ -1178,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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,17 +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
#auto-redact #auto-redact
autoRedact.title=Redaksional Otomatis autoRedact.title=Redaksional Otomatis
@@ -617,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
@@ -737,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):
@@ -752,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 (%):
@@ -777,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
@@ -804,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
@@ -830,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
@@ -904,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)
@@ -982,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
@@ -1060,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:
@@ -1074,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.
@@ -1096,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.
@@ -1104,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
@@ -1158,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 #
@@ -782,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
@@ -804,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
@@ -1220,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=利用規約
@@ -782,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に変換
@@ -804,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
@@ -1220,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
@@ -782,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로
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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=informacje
pro=Pro pro=Pro
page=Strona page=Strona
pages=Strony pages=Strony
loading=Loading...
addToDoc=Add to Document
legal.privacy=Polityka Prywatności legal.privacy=Polityka Prywatności
legal.terms=Zasady i Postanowienia legal.terms=Zasady i Postanowienia
@@ -782,6 +784,9 @@ 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
@@ -804,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
@@ -1220,5 +1230,3 @@ splitByChapters.desc.2=Poziom Zakładek: Wybierz poziom zakładek, który ma zos
splitByChapters.desc.3=Dołącz Metadane: Jeśli opcja ta jest zaznaczona, metadane oryginalnego pliku PDF zostaną uwzględnione w każdym rozdzielonych plików PDF. splitByChapters.desc.3=Dołącz Metadane: Jeśli opcja ta jest zaznaczona, metadane oryginalnego pliku PDF zostaną uwzględnione w każdym rozdzielonych plików PDF.
splitByChapters.desc.4=Zezwól na Duplikaty: Jeśli ta opcja jest zaznaczona, pozwala na tworzenie oddzielnych plików PDF przez wiele zakładek na tej samej stronie. splitByChapters.desc.4=Zezwól na Duplikaty: Jeśli ta opcja jest zaznaczona, pozwala na tworzenie oddzielnych plików PDF przez wiele zakładek na tej samej stronie.
splitByChapters.submit=Podziel PDF splitByChapters.submit=Podziel PDF

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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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,9 +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
#auto-redact #auto-redact
autoRedact.title=Auto-redigera autoRedact.title=Auto-redigera
@@ -728,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
@@ -782,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
@@ -804,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
@@ -1181,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)
@@ -1210,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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
@@ -782,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
@@ -804,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
@@ -1220,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=專業版
page=頁面 page=頁面
pages=頁面 pages=頁面
loading=Loading...
addToDoc=Add to Document
legal.privacy=隱私權政策 legal.privacy=隱私權政策
legal.terms=使用條款 legal.terms=使用條款
@@ -782,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
@@ -804,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
@@ -1220,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

@@ -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",
@@ -28,6 +35,13 @@
"moduleLicense": "MIT", "moduleLicense": "MIT",
"moduleLicenseUrl": "https://opensource.org/licenses/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",
@@ -400,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"
}, },
@@ -414,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"
}, },
@@ -681,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"
}, },
@@ -776,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/"
}, },
@@ -1139,266 +1153,266 @@
{ {
"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"
}, },

View File

@@ -329,11 +329,14 @@ span.icon-text::after {
} }
} }
.go-pro-link { .go-pro-link {
position: relative; position: relative;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
transition: all 0.3s ease; transition: all 0.3s ease;
} z-index: 1;
display: inline-block;
width: auto;
}
.go-pro-badge { .go-pro-badge {
display: inline-block; display: inline-block;
@@ -350,4 +353,4 @@ span.icon-text::after {
.go-pro-link:hover .go-pro-badge { .go-pro-link:hover .go-pro-badge {
background-color: #0056b3; background-color: #0056b3;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
} }

View File

@@ -62,3 +62,53 @@ select#font-select option {
background-color: rgba(52, 152, 219, 0.2); background-color: rgba(52, 152, 219, 0.2);
/* Darken background on hover */ /* 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,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="${altLogin}" 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>

View File

@@ -374,17 +374,17 @@
<p th:text="#{analytics.paragraph2}">Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.</p> <p th:text="#{analytics.paragraph2}">Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.</p>
<p th:text="#{analytics.settings}">You can change the settings for analytics in the config/settings.yml file</p> <p th:text="#{analytics.settings}">You can change the settings for analytics in the config/settings.yml file</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer justify-content-between">
<button type="button" class="btn btn-primary" th:text="#{analytics.enable}" onclick="setAnalytics(true)">Enable analytics</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onclick="setAnalytics(false)" th:text="#{analytics.disable}">Disable analytics</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onclick="setAnalytics(false)" th:text="#{analytics.disable}">Disable analytics</button> <button type="button" class="btn btn-primary" th:text="#{analytics.enable}" onclick="setAnalytics(true)">Enable analytics</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script th:src="@{'/js/fetch-utils.js'}"></script>
<script th:inline="javascript"> <script th:inline="javascript">
/*<![CDATA[*/ /*<![CDATA[*/
@@ -398,7 +398,7 @@
}); });
/*]]>*/ /*]]>*/
function setAnalytics(enabled) { function setAnalytics(enabled) {
fetch('api/v1/settings/update-enable-analytics', { fetchWithCsrf('api/v1/settings/update-enable-analytics', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -426,50 +426,60 @@
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const surveyVersion = "2.0"; const surveyVersion = "2.0";
const modal = new bootstrap.Modal(document.getElementById('surveyModal')); const modal = new bootstrap.Modal(document.getElementById('surveyModal'));
const dontShowAgain = document.getElementById('dontShowAgain'); const dontShowAgain = document.getElementById('dontShowAgain');
const takeSurveyButton = document.getElementById('takeSurvey'); const takeSurveyButton = document.getElementById('takeSurvey');
const viewThresholds = [5, 15, 30, 50, 75, 100, 150, 200]; const viewThresholds = [5, 10, 15, 22, 30, 50, 75, 100, 150, 200];
let pageViews = parseInt(localStorage.getItem('pageViews') || '0');
pageViews++; // Check if survey version changed and reset page views if it did
localStorage.setItem('pageViews', pageViews.toString()); const storedVersion = localStorage.getItem('surveyVersion');
if (storedVersion && storedVersion !== surveyVersion) {
localStorage.setItem('pageViews', '0');
}
function shouldShowSurvey() { let pageViews = parseInt(localStorage.getItem('pageViews') || '0');
if (localStorage.getItem('dontShowSurvey') === 'true' || localStorage.getItem('surveyTaken') === 'true') {
return false; pageViews++;
localStorage.setItem('pageViews', pageViews.toString());
function shouldShowSurvey() {
if (localStorage.getItem('dontShowSurvey') === 'true' ||
localStorage.getItem('surveyTaken') === 'true') {
return false;
} }
if (localStorage.getItem('surveyVersion') !== surveyVersion) { // If survey version changed and we hit a threshold, show the survey
return true; if (localStorage.getItem('surveyVersion') !== surveyVersion &&
viewThresholds.includes(pageViews)) {
return true;
} }
return viewThresholds.includes(pageViews); return viewThresholds.includes(pageViews);
} }
if (shouldShowSurvey()) { if (shouldShowSurvey()) {
modal.show(); modal.show();
} }
dontShowAgain.addEventListener('change', function() { dontShowAgain.addEventListener('change', function() {
if (this.checked) { if (this.checked) {
localStorage.setItem('dontShowSurvey', 'true'); localStorage.setItem('dontShowSurvey', 'true');
localStorage.setItem('surveyVersion', surveyVersion); localStorage.setItem('surveyVersion', surveyVersion);
} else { } else {
localStorage.removeItem('dontShowSurvey'); localStorage.removeItem('dontShowSurvey');
localStorage.removeItem('surveyVersion'); localStorage.removeItem('surveyVersion');
} }
}); });
takeSurveyButton.addEventListener('click', function() { takeSurveyButton.addEventListener('click', function() {
localStorage.setItem('surveyTaken', 'true'); localStorage.setItem('surveyTaken', 'true');
localStorage.setItem('surveyVersion', surveyVersion); localStorage.setItem('surveyVersion', surveyVersion);
modal.hide(); modal.hide();
});
}); });
});
</script> </script>

View File

@@ -19,7 +19,7 @@
<span class="material-symbols-rounded tool-header-icon organize">add_to_photos</span> <span class="material-symbols-rounded tool-header-icon organize">add_to_photos</span>
<span class="tool-header-text" th:text="#{merge.header}"></span> <span class="tool-header-text" th:text="#{merge.header}"></span>
</div> </div>
<form action="api/v1/general/merge-pdfs" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/general/merge-pdfs'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{multiPdfDropPrompt}" for="fileInput-input"></label> <label th:text="#{multiPdfDropPrompt}" for="fileInput-input"></label>
<div <div

View File

@@ -20,7 +20,7 @@
</div> </div>
<!-- pdf selector --> <!-- pdf selector -->
<div th:replace="~{fragments/common :: fileSelector(name='pdf-upload', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='pdf-upload', disableMultipleFiles=true, multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script> <script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
<script> <script>
let originalFileName = ''; let originalFileName = '';
@@ -46,7 +46,7 @@
</script> </script>
<div class="tab-group show-on-file-selected"> <div class="tab-group show-on-file-selected">
<div th:replace="~{fragments/common :: fileSelector(name='image-upload', multipleInputsForSingleRequest=true, accept='image/*', inputText=#{imgPrompt})}"></div> <div th:replace="~{fragments/common :: fileSelector(name='image-upload', disableMultipleFiles=true, multipleInputsForSingleRequest=true, accept='image/*', inputText=#{imgPrompt})}"></div>
<script> <script>
const imageUpload = document.querySelector('input[name=image-upload]'); const imageUpload = document.querySelector('input[name=image-upload]');
imageUpload.addEventListener('change', e => { imageUpload.addEventListener('change', e => {

View File

@@ -21,7 +21,7 @@
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-12 bg-card"> <div class="col-md-12 bg-card">
<form> <form th:action="@{''}">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-3"> <div class="col-md-3">

View File

@@ -1,236 +1,256 @@
<!DOCTYPE html> <!DOCTYPE html>
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org"> <html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}"
<head> xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{compare.title}, header=#{compare.header})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{compare.title}, header=#{compare.header})}"></th:block>
<style> <style>
.result-column { .result-column {
border: 1px solid #ccc; border: 1px solid #ccc;
padding: 15px; padding: 15px;
margin-bottom: 15px; margin-bottom: 15px;
overflow-y: auto; overflow-y: auto;
height: calc(100vh - 400px); height: calc(100vh - 400px);
white-space: pre-wrap; white-space: pre-wrap;
} }
.flex-container {
display: flex;
flex-direction: row;
}
.color-selector {
display: flex;
flex-direction: row;
align-items: center;
width: 50%;
max-height: 100px;
margin-bottom: 2rem;
}
#color-box1, #color-box2 {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
background-color: transparent;
}
.spacer1 {
padding-right: calc(var(--bs-gutter-x) * .5);
}
.spacer2 {
padding-left: calc(var(--bs-gutter-x) * .5);
}
</style>
</head>
<body> .flex-container {
<div id="page-container"> display: flex;
<div id="content-wrap"> flex-direction: row;
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block> }
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-9 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">compare</span>
<span class="tool-header-text" th:text="#{compare.header}"></span>
</div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf', remoteCall='false')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput2', multipleInputsForSingleRequest=false, accept='application/pdf', remoteCall='false')}"></div>
<div class="row"> .color-selector {
<div class="flex-container"> display: flex;
<div class="color-selector spacer1"> flex-direction: row;
<label th:text="#{compare.highlightColor.1}"></label> align-items: center;
<label for="color-box1"></label><input type="color" id="color-box1" value="#ff0000"> width: 50%;
</div> max-height: 100px;
<div class="color-selector spacer2"> margin-bottom: 2rem;
<label th:text="#{compare.highlightColor.2}"></label> }
<label for="color-box2"></label><input type="color" id="color-box2" value="#008000">
</div>
</div>
</div>
<button class="btn btn-primary" onclick="comparePDFs()" th:text="#{compare.submit}"></button> #color-box1,
#color-box2 {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
background-color: transparent;
}
<div class="row"> .spacer1 {
<div class="col-md-6"> padding-right: calc(var(--bs-gutter-x) * .5);
<h3 th:text="#{compare.document.1}"></h3> }
<div id="result1" class="result-column"></div>
</div>
<div class="col-md-6">
<h3 th:text="#{compare.document.2}"></h3>
<div id="result2" class="result-column"></div>
</div>
</div>
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
<script>
// get the elements
var result1 = document.getElementById('result1');
var result2 = document.getElementById('result2');
// add event listeners .spacer2 {
result1.addEventListener('scroll', function() { padding-left: calc(var(--bs-gutter-x) * .5);
result2.scrollTop = result1.scrollTop; }
}); </style>
</head>
result2.addEventListener('scroll', function() { <body>
result1.scrollTop = result2.scrollTop; <div id="page-container">
}); <div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
async function comparePDFs() { <br><br>
const file1 = document.getElementById("fileInput-input").files[0]; <div class="container">
const file2 = document.getElementById("fileInput2-input").files[0]; <div class="row justify-content-center">
var color1 = document.getElementById('color-box1').value; <div class="col-md-9 bg-card">
var color2 = document.getElementById('color-box2').value; <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">compare</span>
if (!file1 || !file2) { <span class="tool-header-text" th:text="#{compare.header}"></span>
console.error("Please select two PDF files to compare");
return;
}
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'
const [pdf1, pdf2] = await Promise.all([
pdfjsLib.getDocument(URL.createObjectURL(file1)).promise,
pdfjsLib.getDocument(URL.createObjectURL(file2)).promise
]);
const extractText = async (pdf) => {
const pages = [];
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const content = await page.getTextContent();
const strings = content.items.map(item => item.str);
pages.push(strings.join(" "));
}
return pages.join(" ");
};
const [text1, text2] = await Promise.all([
extractText(pdf1),
extractText(pdf2)
]);
if (text1.trim() === "" || text2.trim() === "") {
alert("One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.");
return;
}
const diff = (text1, text2) => {
const words1 = text1.split(' ');
const words2 = text2.split(' ');
// Create a 2D array to hold our "matrix"
const matrix = Array(words1.length + 1).fill(null).map(() => Array(words2.length + 1).fill(0));
// Perform standard LCS algorithm
for (let i = 1; i <= words1.length; i++) {
for (let j = 1; j <= words2.length; j++) {
if (words1[i - 1] === words2[j - 1]) {
matrix[i][j] = matrix[i - 1][j - 1] + 1;
} else {
matrix[i][j] = Math.max(matrix[i][j - 1], matrix[i - 1][j]);
}
}
}
let i = words1.length;
let j = words2.length;
const differences = [];
// Backtrack through the matrix to create the diff
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 - 1] >= matrix[i - 1][j])) {
differences.unshift([color2, words2[j - 1]]);
j--;
} else if (i > 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
differences.unshift([color1, words1[i - 1]]);
i--;
}
}
console.log(differences);
return differences;
};
const differences = diff(text1, text2);
const displayDifferences = (differences) => {
const resultDiv1 = document.getElementById("result1");
const resultDiv2 = document.getElementById("result2");
resultDiv1.innerHTML = "";
resultDiv2.innerHTML = "";
differences.forEach(([color, word]) => {
const span1 = document.createElement("span");
const span2 = document.createElement("span");
// If it's an addition, show it in color2 in the second document and transparent in the first
if (color === color2) {
span1.style.color = "transparent";
span1.style.userSelect = "none";
span2.style.color = color;
}
// If it's a deletion, show it in color1 in the first document and transparent in the second
else if (color === color1) {
span1.style.color = color;
span2.style.color = "transparent";
span2.style.userSelect = "none";
}
// If it's unchanged, show it in black in both
else {
span1.style.color = color;
span2.style.color = color;
}
span1.textContent = word;
span2.textContent = word;
resultDiv1.appendChild(span1);
resultDiv2.appendChild(span2);
// Add space after each word, or a new line if the word ends with a full stop
const spaceOrNewline1 = document.createElement("span");
const spaceOrNewline2 = document.createElement("span");
if (word.endsWith(".")) {
spaceOrNewline1.innerHTML = "<br>";
spaceOrNewline2.innerHTML = "<br>";
} else {
spaceOrNewline1.textContent = " ";
spaceOrNewline2.textContent = " ";
}
resultDiv1.appendChild(spaceOrNewline1);
resultDiv2.appendChild(spaceOrNewline2);
});
};
console.log('Differences:', differences);
displayDifferences(differences);
}
</script>
</div> </div>
<div
th:replace="~{fragments/common :: fileSelector(name='fileInput', disableMultipleFiles=true, multipleInputsForSingleRequest=false, accept='application/pdf', remoteCall='false')}">
</div>
<div
th:replace="~{fragments/common :: fileSelector(name='fileInput2', disableMultipleFiles=true, multipleInputsForSingleRequest=false, accept='application/pdf', remoteCall='false')}">
</div>
<div class="row">
<div class="flex-container">
<div class="color-selector spacer1">
<label th:text="#{compare.highlightColor.1}"></label>
<label for="color-box1"></label><input type="color" id="color-box1" value="#ff0000">
</div>
<div class="color-selector spacer2">
<label th:text="#{compare.highlightColor.2}"></label>
<label for="color-box2"></label><input type="color" id="color-box2" value="#008000">
</div>
</div>
</div>
<button class="btn btn-primary" onclick="comparePDFs()" th:text="#{compare.submit}"></button>
<div class="row">
<div class="col-md-6">
<h3 th:text="#{compare.document.1}"></h3>
<div id="result1" class="result-column"></div>
</div>
<div class="col-md-6">
<h3 th:text="#{compare.document.2}"></h3>
<div id="result2" class="result-column"></div>
</div>
</div>
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
<script th:inline="javascript">
// get the elements
var result1 = document.getElementById('result1');
var result2 = document.getElementById('result2');
// add event listeners
result1.addEventListener('scroll', function () {
result2.scrollTop = result1.scrollTop;
});
result2.addEventListener('scroll', function () {
result1.scrollTop = result2.scrollTop;
});
async function comparePDFs() {
const file1 = document.getElementById("fileInput-input").files[0];
const file2 = document.getElementById("fileInput2-input").files[0];
var color1 = document.getElementById('color-box1').value;
var color2 = document.getElementById('color-box2').value;
const complexMessage = /*[[#{compare.complex.message}]]*/ 'One or both of the provided documents are large files, accuracy of comparison may be reduced';
const largeFilesMessage = /*[[#{compare.large.file.message}]]*/ 'One or Both of the provided documents are too large to process';
const noTextMessage = /*[[#{compare.no.text.message}]]*/ 'One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison."';
if (!file1 || !file2) {
console.error("Please select two PDF files to compare");
return;
}
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs';
const [pdf1, pdf2] = await Promise.all([
pdfjsLib.getDocument(URL.createObjectURL(file1)).promise,
pdfjsLib.getDocument(URL.createObjectURL(file2)).promise
]);
const extractText = async (pdf) => {
const pages = [];
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const content = await page.getTextContent();
const strings = content.items.map(item => item.str);
pages.push(strings.join(" "));
}
return pages.join(" ");
};
const [text1, text2] = await Promise.all([
extractText(pdf1),
extractText(pdf2)
]);
if (text1.trim() === "" || text2.trim() === "") {
alert(noTextMessage);
return;
}
const resultDiv1 = document.getElementById("result1");
const resultDiv2 = document.getElementById("result2");
const loading = /*[[#{loading}]]*/ 'Loading...';
resultDiv1.innerHTML = loading;
resultDiv2.innerHTML = loading;
// Create a new Worker
const worker = new Worker('/js/compare/pdfWorker.js');
// Post messages to the worker
worker.postMessage({
type: 'SET_COMPLEX_MESSAGE',
message: complexMessage
});
worker.postMessage({
type: 'SET_TOO_LARGE_MESSAGE',
message: largeFilesMessage
});
// Error handling for the worker
worker.onerror = function (error) {
console.error('Worker error:', error);
};
worker.onmessage = function (e) {
const { status, differences, message } = e.data;
if (status === 'error') {
resultDiv1.innerHTML = '';
resultDiv2.innerHTML = '';
alert(message);
return;
}
if (status === 'success' && differences) {
console.log('Differences:', differences);
displayDifferences(differences);
}
if (event.data.status === 'warning') {
console.warn(event.data.message);
alert(event.data.message);
}
};
worker.postMessage({ text1, text2, color1, color2 });
const displayDifferences = (differences) => {
const resultDiv1 = document.getElementById("result1");
const resultDiv2 = document.getElementById("result2");
resultDiv1.innerHTML = "";
resultDiv2.innerHTML = "";
differences.forEach(([color, word]) => {
const span1 = document.createElement("span");
const span2 = document.createElement("span");
if (color === color2) {
span1.style.color = "transparent";
span1.style.userSelect = "none";
span2.style.color = color;
}
// If it's a deletion, show it in in the first document and transparent in the second
else if (color === color1) {
span1.style.color = color;
span2.style.color = "transparent";
span2.style.userSelect = "none";
}
// If it's unchanged, show it in black in both
else {
span1.style.color = color;
span2.style.color = color;
}
span1.textContent = word;
span2.textContent = word;
resultDiv1.appendChild(span1);
resultDiv2.appendChild(span2);
// Add space after each word, or a new line if the word ends with a full stop
const spaceOrNewline1 = document.createElement("span");
const spaceOrNewline2 = document.createElement("span");
if (word.endsWith(".")) {
spaceOrNewline1.innerHTML = "<br>";
spaceOrNewline2.innerHTML = "<br>";
} else {
spaceOrNewline1.textContent = " ";
spaceOrNewline2.textContent = " ";
}
resultDiv1.appendChild(spaceOrNewline1);
resultDiv2.appendChild(spaceOrNewline2);
});
};
}
</script>
</div> </div>
</div> </div>
</div> </div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div> </div>
</body> <th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html> </html>

View File

@@ -52,4 +52,4 @@
</div> </div>
</body> </body>
</html> </html>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon other">thread_unread</span> <span class="material-symbols-rounded tool-header-icon other">thread_unread</span>
<span class="tool-header-text" th:text="#{removeAnnotations.header}"></span> <span class="tool-header-text" th:text="#{removeAnnotations.header}"></span>
</div> </div>
<form id="pdfForm" class="mb-3"> <form id="pdfForm" th:action="@{''}" class="mb-3">
<div class="custom-file"> <div class="custom-file">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf', remoteCall='false')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf', remoteCall='false')}"></div>
</div> </div>

View File

@@ -39,6 +39,7 @@
<!-- Button to download the JSON --> <!-- Button to download the JSON -->
<a href="#" id="downloadJS" class="btn btn-primary mt-3" style="display: none;" th:text="#{showJS.downloadJS}">Download JSON</a> <a href="#" id="downloadJS" class="btn btn-primary mt-3" style="display: none;" th:text="#{showJS.downloadJS}">Download JSON</a>
</div> </div>
<script th:src="@{'/js/fetch-utils.js'}"></script>
<script> <script>
document.querySelector('#pdfInfoForm').addEventListener('submit', function(event){ document.querySelector('#pdfInfoForm').addEventListener('submit', function(event){
event.preventDefault(); event.preventDefault();
@@ -46,7 +47,7 @@
// Fetch the formData // Fetch the formData
const formData = new FormData(event.target); const formData = new FormData(event.target);
fetch('api/v1/misc/show-javascript', { fetchWithCsrf('api/v1/misc/show-javascript', {
method: 'POST', method: 'POST',
body: formData body: formData
}).then(response => response.text()) }).then(response => response.text())

View File

@@ -80,7 +80,6 @@
<script type="module"> <script type="module">
import PdfContainer from './js/multitool/PdfContainer.js'; import PdfContainer from './js/multitool/PdfContainer.js';
import DragDropManager from "./js/multitool/DragDropManager.js"; import DragDropManager from "./js/multitool/DragDropManager.js";
import scrollDivHorizontally from "./js/multitool/horizontalScroll.js";
import ImageHighlighter from "./js/multitool/ImageHighlighter.js"; import ImageHighlighter from "./js/multitool/ImageHighlighter.js";
import PdfActionsManager from './js/multitool/PdfActionsManager.js'; import PdfActionsManager from './js/multitool/PdfActionsManager.js';
import FileDragManager from './js/multitool/fileInput.js'; import FileDragManager from './js/multitool/fileInput.js';
@@ -93,7 +92,6 @@
const fileDragManager = new FileDragManager(); const fileDragManager = new FileDragManager();
// Scroll the wrapper horizontally // Scroll the wrapper horizontally
scrollDivHorizontally('pages-container-wrapper');
// Automatically exposes rotateAll, addFiles and exportPdf to the window for the global buttons. // Automatically exposes rotateAll, addFiles and exportPdf to the window for the global buttons.
const pdfContainer = new PdfContainer( const pdfContainer = new PdfContainer(
@@ -111,4 +109,4 @@
</script> </script>
</body> </body>
</html> </html>

View File

@@ -192,6 +192,7 @@
</div> </div>
</div> </div>
</div> </div>
<script th:src="@{'/js/fetch-utils.js'}"></script>
<script th:src="@{'/js/pipeline.js'}"></script>\ <script th:src="@{'/js/pipeline.js'}"></script>\
</div> </div>
</div> </div>

View File

@@ -20,7 +20,7 @@
<span class="material-symbols-rounded tool-header-icon word">remove_selection</span> <span class="material-symbols-rounded tool-header-icon word">remove_selection</span>
<span class="tool-header-text" th:text="#{removeImage.header}"></span> <span class="tool-header-text" th:text="#{removeImage.header}"></span>
</div> </div>
<form action="api/v1/general/remove-image-pdf" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/general/remove-image-pdf'}" method="post" enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<br> <br>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">lock</span> <span class="material-symbols-rounded tool-header-icon security">lock</span>
<span class="tool-header-text" th:text="#{addPassword.header}"></span> <span class="tool-header-text" th:text="#{addPassword.header}"></span>
</div> </div>
<form action="api/v1/security/add-password" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/add-password'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{addPassword.selectText.1}"></label> <label th:text="#{addPassword.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>

View File

@@ -17,7 +17,7 @@
<span class="tool-header-text" th:text="#{watermark.header}"></span> <span class="tool-header-text" th:text="#{watermark.header}"></span>
</div> </div>
<form method="post" enctype="multipart/form-data" action="api/v1/security/add-watermark"> <form method="post" enctype="multipart/form-data" th:action="@{'api/v1/security/add-watermark'}">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{watermark.selectText.1}"></label> <label th:text="#{watermark.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">ink_eraser</span> <span class="material-symbols-rounded tool-header-icon security">ink_eraser</span>
<span class="tool-header-text" th:text="#{autoRedact.header}"></span> <span class="tool-header-text" th:text="#{autoRedact.header}"></span>
</div> </div>
<form action="api/v1/security/auto-redact" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/auto-redact'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<input type="file" class="form-control" id="fileInput" name="fileInput" required accept="application/pdf"> <input type="file" class="form-control" id="fileInput" name="fileInput" required accept="application/pdf">
</div> </div>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">workspace_premium</span> <span class="material-symbols-rounded tool-header-icon security">workspace_premium</span>
<span class="tool-header-text" th:text="#{certSign.header}"></span> <span class="tool-header-text" th:text="#{certSign.header}"></span>
</div> </div>
<form action="api/v1/security/cert-sign" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/cert-sign'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{certSign.selectPDF}"></label> <label th:text="#{certSign.selectPDF}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
@@ -71,7 +71,11 @@
<label for="name" th:text="#{certSign.name}"></label> <input type="text" class="form-control" id="name" name="name"> <label for="name" th:text="#{certSign.name}"></label> <input type="text" class="form-control" id="name" name="name">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="pageNumber" th:text="#{pageNum}"></label> <input type="number" class="form-control" id="pageNumber" name="pageNumber" min="1" disabled> <label for="pageNumber" th:text="#{pageNum}"></label> <input type="number" class="form-control" id="pageNumber" name="pageNumber" min="1" value="1">
</div>
<div class="form-check mb-3">
<input type="checkbox" id="showLogo" name="showLogo" checked />
<label th:text="#{certSign.showLogo}" for="showLogo"></label>
</div> </div>
</div> </div>
<div class="mb-3 text-left"> <div class="mb-3 text-left">

View File

@@ -17,7 +17,7 @@
<span class="tool-header-text" th:text="#{permissions.header}"></span> <span class="tool-header-text" th:text="#{permissions.header}"></span>
</div> </div>
<p th:text="#{permissions.warning}"></p> <p th:text="#{permissions.warning}"></p>
<form action="api/v1/security/add-password" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/add-password'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{permissions.selectText.1}"></label> <label th:text="#{permissions.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>

View File

@@ -31,12 +31,16 @@
<a href="#" id="downloadJson" class="btn btn-primary mt-3" style="display: none;" th:text="#{getPdfInfo.downloadJson}">Download JSON</a> <a href="#" id="downloadJson" class="btn btn-primary mt-3" style="display: none;" th:text="#{getPdfInfo.downloadJson}">Download JSON</a>
</div> </div>
<script> <script>
import { fetchWithCsrf } from 'js/fetch-utils.js';
document.getElementById("pdfInfoForm").addEventListener("submit", function(event) { document.getElementById("pdfInfoForm").addEventListener("submit", function(event) {
event.preventDefault(); event.preventDefault();
const formData = new FormData(event.target); const formData = new FormData(event.target);
fetch('api/v1/security/get-info-on-pdf', { fetchWithCsrf('api/v1/security/get-info-on-pdf', {
method: 'POST', method: 'POST',
body: formData body: formData
}).then(response => response.json()).then(data => { }).then(response => response.json()).then(data => {

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">remove_moderator</span> <span class="material-symbols-rounded tool-header-icon security">remove_moderator</span>
<span class="tool-header-text" th:text="#{removeCertSign.header}"></span> <span class="tool-header-text" th:text="#{removeCertSign.header}"></span>
</div> </div>
<form action="api/v1/security/remove-cert-sign" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/remove-cert-sign'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{removeCertSign.selectPDF}"></label> <label th:text="#{removeCertSign.selectPDF}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">lock_open_right</span> <span class="material-symbols-rounded tool-header-icon security">lock_open_right</span>
<span class="tool-header-text" th:text="#{removePassword.header}"></span> <span class="tool-header-text" th:text="#{removePassword.header}"></span>
</div> </div>
<form action="api/v1/security/remove-password" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/remove-password'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{removePassword.selectText.1}"></label> <label th:text="#{removePassword.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">water_drop</span> <span class="material-symbols-rounded tool-header-icon security">water_drop</span>
<span class="tool-header-text" th:text="#{remove-watermark.header}"></span> <span class="tool-header-text" th:text="#{remove-watermark.header}"></span>
</div> </div>
<form method="post" enctype="multipart/form-data" action="api/v1/security/remove-watermark"> <form method="post" enctype="multipart/form-data" th:action="@{'api/v1/security/remove-watermark'}">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{remove-watermark.selectText.1}"></label> <label th:text="#{remove-watermark.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>

View File

@@ -16,7 +16,7 @@
<span class="material-symbols-rounded tool-header-icon security">sanitizer</span> <span class="material-symbols-rounded tool-header-icon security">sanitizer</span>
<span class="tool-header-text" th:text="#{sanitizePDF.header}"></span> <span class="tool-header-text" th:text="#{sanitizePDF.header}"></span>
</div> </div>
<form action="api/v1/security/sanitize-pdf" method="post" enctype="multipart/form-data"> <form th:action="@{'api/v1/security/sanitize-pdf'}" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
</div> </div>

View File

@@ -43,6 +43,53 @@
</div> </div>
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script> <script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
<script> <script>
let currentPreviewSrc = null;
function toggleSignatureView() {
const gridView = document.getElementById('gridView');
const listView = document.getElementById('listView');
const gridText = document.querySelector('.grid-view-text');
const listText = document.querySelector('.list-view-text');
if (gridView.style.display !== 'none') {
gridView.style.display = 'none';
listView.style.display = 'block';
gridText.style.display = 'none';
listText.style.display = 'inline';
} else {
gridView.style.display = 'block';
listView.style.display = 'none';
gridText.style.display = 'inline';
listText.style.display = 'none';
}
}
function previewSignature(element) {
const src = element.dataset.src;
currentPreviewSrc = src;
// Extract filename from the data source path
const filename = element.querySelector('.signature-list-name').textContent;
// Update preview modal
const previewImage = document.getElementById('previewImage');
const previewFileName = document.getElementById('previewFileName');
previewImage.src = src;
previewFileName.textContent = filename;
const modal = new bootstrap.Modal(document.getElementById('signaturePreview'));
modal.show();
}
function addSignatureFromPreview() {
if (currentPreviewSrc) {
DraggableUtils.createDraggableCanvasFromUrl(currentPreviewSrc);
bootstrap.Modal.getInstance(document.getElementById('signaturePreview')).hide();
}
}
let originalFileName = ''; let originalFileName = '';
document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => { document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => {
const file = event.target.files[0]; const file = event.target.files[0];
@@ -68,7 +115,7 @@
<div class="tab-group show-on-file-selected"> <div class="tab-group show-on-file-selected">
<div class="tab-container" th:title="#{sign.upload}"> <div class="tab-container" th:title="#{sign.upload}">
<div <div
th:replace="~{fragments/common :: fileSelector(name='image-upload', multipleInputsForSingleRequest=true, accept='image/*', inputText=#{imgPrompt})}"> th:replace="~{fragments/common :: fileSelector(name='image-upload', disableMultipleFiles=true, multipleInputsForSingleRequest=true, accept='image/*', inputText=#{imgPrompt})}">
</div> </div>
<script> <script>
const imageUpload = document.querySelector('input[name=image-upload]'); const imageUpload = document.querySelector('input[name=image-upload]');
@@ -165,6 +212,126 @@
</script> </script>
</div> </div>
<div class="tab-container" th:title="#{sign.saved}">
<div class="saved-signatures-section" th:if="${not #lists.isEmpty(signatures)}">
<!-- View Toggle Button -->
<div class="view-toggle mb-3">
<button class="btn btn-outline-secondary btn-sm" onclick="toggleSignatureView()">
<span class="material-symbols-rounded grid-view-text">view_list</span>
<span class="material-symbols-rounded list-view-text" style="display: none;">grid_view</span>
</button>
</div>
<!-- Preview Modal -->
<div class="modal fade" id="signaturePreview" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><span id="previewFileName"></span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body text-center">
<img id="previewImage" src="" alt="Signature Preview" style="max-width: 100%;">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" th:text="#{close}"></button>
<button type="button" class="btn btn-primary" onclick="addSignatureFromPreview()" th:text="#{addToDoc}">Add to Document</button>
</div>
</div>
</div>
</div>
<!-- Grid View -->
<div id="gridView">
<!-- Personal Signatures -->
<div class="signature-category" th:if="${not #lists.isEmpty(signatures.?[category == 'Personal'])}">
<h5 th:text="#{sign.personalSigs}"></h5>
<div class="signature-grid">
<div th:each="sig : ${signatures}" th:if="${sig.category == 'Personal'}" class="signature-item">
<img th:src="@{'/api/v1/general/sign/' + ${sig.fileName}}"
th:alt="${sig.fileName}"
th:data-filename="${sig.fileName}"
style="max-width: 200px; cursor: pointer;"
onclick="DraggableUtils.createDraggableCanvasFromUrl(this.src)"/>
<div class="signature-name" th:text="${sig.fileName}"></div>
</div>
</div>
</div>
<!-- Shared Signatures -->
<div class="signature-category" th:if="${not #lists.isEmpty(signatures.?[category == 'Shared'])}">
<h5 th:text="#{sign.sharedSigs}"></h5>
<div class="signature-grid">
<div th:each="sig : ${signatures}" th:if="${sig.category == 'Shared'}" class="signature-item">
<img th:src="@{'/api/v1/general/sign/' + ${sig.fileName}}"
th:alt="${sig.fileName}"
th:data-filename="${sig.fileName}"
style="max-width: 200px; cursor: pointer;"
onclick="DraggableUtils.createDraggableCanvasFromUrl(this.src)"/>
<div class="signature-name" th:text="${sig.fileName}"></div>
</div>
</div>
</div>
</div>
<!-- List View (Initially Hidden) -->
<div id="listView" style="display: none;">
<!-- Personal Signatures -->
<div class="signature-category" th:if="${not #lists.isEmpty(signatures.?[category == 'Personal'])}">
<h5 th:text="#{sign.personalSigs}"></h5>
<div class="signature-list">
<div th:each="sig : ${signatures}" th:if="${sig.category == 'Personal'}"
class="signature-list-item"
th:data-src="@{'/api/v1/general/sign/' + ${sig.fileName}}"
onclick="previewSignature(this)">
<div class="signature-list-info">
<span th:text="${sig.fileName}" class="signature-list-name"></span>
</div>
</div>
</div>
</div>
<!-- Shared Signatures -->
<div class="signature-category" th:if="${not #lists.isEmpty(signatures.?[category == 'Shared'])}">
<h5 th:text="#{sign.sharedSigs}"></h5>
<div class="signature-list">
<div th:each="sig : ${signatures}" th:if="${sig.category == 'Shared'}"
class="signature-list-item"
th:data-src="@{'/api/v1/general/sign/' + ${sig.fileName}}"
onclick="previewSignature(this)">
<div class="signature-list-info">
<span th:text="${sig.fileName}" class="signature-list-name"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<div th:if="${#lists.isEmpty(signatures)}" class="text-center p-3">
<p th:text="#{sign.noSavedSigs}">No saved signatures found</p>
</div>
</div>
<div class="tab-container" th:title="#{sign.text}"> <div class="tab-container" th:title="#{sign.text}">
<label class="form-check-label" for="sigText" th:text="#{text}"></label> <label class="form-check-label" for="sigText" th:text="#{text}"></label>
<textarea class="form-control" id="sigText" name="sigText" rows="3"></textarea> <textarea class="form-control" id="sigText" name="sigText" rows="3"></textarea>