diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 6e006423a..9afb72a4d 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,8 @@ "Bash(mkdir:*)", "Bash(./gradlew:*)", "Bash(grep:*)", - "Bash(cat:*)" + "Bash(cat:*)", + "Bash(find:*)" ], "deny": [] } diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 644378d12..5ab9f82c9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -119,7 +119,9 @@ "EditorConfig.EditorConfig", // EditorConfig support for maintaining consistent coding styles "ms-azuretools.vscode-docker", // Docker extension for Visual Studio Code "charliermarsh.ruff", // Ruff extension for Ruff language support - "github.vscode-github-actions" // GitHub Actions extension for Visual Studio Code + "github.vscode-github-actions", // GitHub Actions extension for Visual Studio Code + "stylelint.vscode-stylelint", // Stylelint extension for CSS and SCSS linting + "redhat.vscode-yaml" // YAML extension for Visual Studio Code ] } }, diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index c60f138ad..530345e30 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,5 +1,9 @@ # Formatting 5f771b785130154ed47952635b7acef371ffe0ec +7fa5e130d99227c2202ebddfdd91348176ec0c7b +14d4fbb2a36195eedb034785e5a5ff6a47f268c6 +ee8030c1c4148062cde15c49c67d04ef03930c55 +fcd41924f5f261febfa9d9a92994671f3ebc97d6 # Normalize files 55d4fda01b2f39f5b7d7b4fda5214bd7ff0fd5dd diff --git a/.gitattributes b/.gitattributes index f72c204bd..0a8155152 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,10 @@ * text=auto eol=lf # Ignore all JavaScript files in a directory -stirling-pdf/src/main/resources/static/pdfjs/* linguist-vendored -stirling-pdf/src/main/resources/static/pdfjs/** linguist-vendored -stirling-pdf/src/main/resources/static/pdfjs-legacy/* linguist-vendored -stirling-pdf/src/main/resources/static/pdfjs-legacy/** linguist-vendored -stirling-pdf/src/main/resources/static/css/bootstrap-icons.css linguist-vendored -stirling-pdf/src/main/resources/static/css/bootstrap.min.css linguist-vendored -stirling-pdf/src/main/resources/static/css/fonts/* linguist-vendored +app/core/src/main/resources/static/pdfjs/* linguist-vendored +app/core/src/main/resources/static/pdfjs/** linguist-vendored +app/core/src/main/resources/static/pdfjs-legacy/* linguist-vendored +app/core/src/main/resources/static/pdfjs-legacy/** linguist-vendored +app/core/src/main/resources/static/css/bootstrap-icons.css linguist-vendored +app/core/src/main/resources/static/css/bootstrap.min.css linguist-vendored +app/core/src/main/resources/static/css/fonts/* linguist-vendored diff --git a/.github/labeler-config-srvaroa.yml b/.github/labeler-config-srvaroa.yml index f8e66fab4..bdc48da53 100644 --- a/.github/labeler-config-srvaroa.yml +++ b/.github/labeler-config-srvaroa.yml @@ -2,86 +2,99 @@ version: 1 labels: - label: "Bugfix" - title: '^fix:.*' + title: '^fix(\([^)]*\))?:|^fix:.*' - label: "enhancement" - title: '^feat:.*' + title: '^feat(\([^)]*\))?:|^feat:.*' - label: "build" - title: '^build:.*' + title: '^build(\([^)]*\))?:|^build:.*' - label: "chore" - title: '^chore:.*' + title: '^chore(\([^)]*\))?:|^chore:.*' - label: "ci" - title: '^ci:.*' + title: '^ci(\([^)]*\))?:|^ci:.*' + + - label: "ci" + title: '^.*\(ci\):.*' - label: "perf" - title: '^perf:.*' + title: '^perf(\([^)]*\))?:|^perf:.*' - label: "refactor" - title: '^refactor:.*' + title: '^refactor(\([^)]*\))?:|^refactor:.*' - label: "revert" - title: '^revert:.*' + title: '^revert(\([^)]*\))?:|^revert:.*' - label: "style" - title: '^style:.*' + title: '^style(\([^)]*\))?:|^style:.*' - label: "Documentation" - title: '^docs:.*' + title: '^docs(\([^)]*\))?:|^docs:.*' + + - label: "Documentation" + title: '^.*\(docs\):.*' + + - label: "dependencies" + title: '^deps(\([^)]*\))?:|^deps:.*' + + - label: "dependencies" + title: '^.*\(deps\):.*' - label: 'API' - title: '.*openapi.*' + title: '.*openapi.*|.*swagger.*|.*api.*' - label: 'Translation' files: - - 'stirling-pdf/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}.properties' + - 'app/core/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}.properties' - 'scripts/ignore_translation.toml' - - 'stirling-pdf/src/main/resources/templates/fragments/languages.html' + - 'app/core/src/main/resources/templates/fragments/languages.html' - '.github/scripts/check_language_properties.py' - label: 'Front End' files: - - 'stirling-pdf/src/main/resources/templates/.*' - - 'proprietary/src/main/resources/templates/.*' - - 'stirling-pdf/src/main/resources/static/.*' - - 'proprietary/src/main/resources/static/.*' - - 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/.*' - - 'stirling-pdf/src/main/java/stirling/software/SPDF/UI/.*' - - 'proprietary/src/main/java/stirling/software/proprietary/security/controller/web/.*' + - 'app/core/src/main/resources/templates/.*' + - 'app/proprietary/src/main/resources/templates/.*' + - 'app/core/src/main/resources/static/.*' + - 'app/proprietary/src/main/resources/static/.*' + - 'app/core/src/main/java/stirling/software/SPDF/controller/web/.*' + - 'app/core/src/main/java/stirling/software/SPDF/UI/.*' + - 'app/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/.*' - label: 'Java' files: - - 'common/src/main/java/.*.java' - - 'proprietary/src/main/java/.*.java' - - 'stirling-pdf/src/main/java/.*.java' + - 'app/common/src/main/java/.*.java' + - 'app/proprietary/src/main/java/.*.java' + - 'app/core/src/main/java/.*.java' - label: 'Back End' files: - - 'stirling-pdf/src/main/java/stirling/software/SPDF/config/.*' - - 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/.*' - - 'stirling-pdf/src/main/resources/settings.yml.template' - - 'stirling-pdf/src/main/resources/application.properties' - - 'stirling-pdf/src/main/resources/banner.txt' + - 'app/core/src/main/java/stirling/software/SPDF/config/.*' + - 'app/core/src/main/java/stirling/software/SPDF/controller/.*' + - 'app/core/src/main/resources/settings.yml.template' + - 'app/core/src/main/resources/application.properties' + - 'app/core/src/main/resources/banner.txt' - 'scripts/png_to_webp.py' - 'split_photos.py' - 'application.properties' - label: 'Security' files: - - 'proprietary/src/main/java/stirling/software/proprietary/security/.*' + - 'app/proprietary/src/main/java/stirling/software/proprietary/security/.*' - 'scripts/download-security-jar.sh' - '.github/workflows/dependency-review.yml' - '.github/workflows/scorecards.yml' - label: 'API' files: - - 'stirling-pdf/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java' - - 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java' - - 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/.*' - - 'stirling-pdf/src/main/java/stirling/software/SPDF/model/api/.*' - - 'proprietary/src/main/java/stirling/software/proprietary/security/controller/api/.*' + - 'app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java' + - 'app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java' + - 'app/core/src/main/java/stirling/software/SPDF/controller/api/.*' + - 'app/core/src/main/java/stirling/software/SPDF/model/api/.*' + - 'app/core/src/main/java/stirling/software/SPDF/service/ApiDocService.java' + - 'app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/.*' - 'scripts/png_to_webp.py' - 'split_photos.py' - '.github/workflows/swagger.yml' @@ -115,13 +128,15 @@ labels: - '.editorconfig' - '.pre-commit-config' - '.github/workflows/pre_commit.yml' - - 'HowToAddNewLanguage.md' + - 'devGuide/.*' + - 'devTools/.*' + - 'devTools/.*' - label: 'Test' files: - - 'common/src/test/.*' - - 'proprietary/src/test/.*' - - 'stirling-pdf/src/test/.*' + - 'app/common/src/test/.*' + - 'app/proprietary/src/test/.*' + - 'app/core/src/test/.*' - 'testing/.*' - '.github/workflows/scorecards.yml' - 'exampleYmlFiles/test_cicd.yml' @@ -137,6 +152,6 @@ labels: - 'gradlew.bat' - 'settings.gradle' - 'build.gradle' - - 'common/build.gradle' - - 'proprietary/build.gradle' - - 'stirling-pdf/build.gradle' + - 'app/common/build.gradle' + - 'app/proprietary/build.gradle' + - 'app/core/build.gradle' diff --git a/.github/labeler-config.yml b/.github/labeler-config.yml deleted file mode 100644 index d1a340065..000000000 --- a/.github/labeler-config.yml +++ /dev/null @@ -1,86 +0,0 @@ -Translation: - - changed-files: - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/messages_*_*.properties' - - any-glob-to-any-file: 'scripts/ignore_translation.toml' - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/fragments/languages.html' - -Front End: - - changed-files: - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/**/*' - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/static/**/*' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/**' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/UI/**/*' - -Java: - - changed-files: - - any-glob-to-any-file: 'common/src/main/java/**/*.java' - - any-glob-to-any-file: 'proprietary/src/main/java/**/*.java' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/**/*.java' - -Back End: - - changed-files: - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/config/**/*' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/**/*' - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/settings.yml.template' - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/application.properties' - - any-glob-to-any-file: 'stirling-pdf/src/main/resources/banner.txt' - - any-glob-to-any-file: 'scripts/png_to_webp.py' - - any-glob-to-any-file: 'split_photos.py' - -Security: - - changed-files: - - any-glob-to-any-file: 'proprietary/src/main/java/stirling/software/proprietary/security/**/*' - - any-glob-to-any-file: 'scripts/download-security-jar.sh' - - any-glob-to-any-file: '.github/workflows/dependency-review.yml' - - any-glob-to-any-file: '.github/workflows/scorecards.yml' - -API: - - changed-files: - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/**/*' - - any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/model/api/**/*' - - any-glob-to-any-file: 'scripts/png_to_webp.py' - - any-glob-to-any-file: 'split_photos.py' - - any-glob-to-any-file: '.github/workflows/swagger.yml' - -Documentation: - - changed-files: - - any-glob-to-any-file: '**/*.md' - - any-glob-to-any-file: 'scripts/counter_translation.py' - - any-glob-to-any-file: 'scripts/ignore_translation.toml' - -Docker: - - changed-files: - - any-glob-to-any-file: '.github/workflows/build.yml' - - any-glob-to-any-file: '.github/workflows/push-docker.yml' - - any-glob-to-any-file: 'Dockerfile' - - any-glob-to-any-file: 'Dockerfile.fat' - - any-glob-to-any-file: 'Dockerfile.ultra-lite' - - any-glob-to-any-file: 'exampleYmlFiles/*.yml' - - any-glob-to-any-file: 'scripts/download-security-jar.sh' - - any-glob-to-any-file: 'scripts/init.sh' - - any-glob-to-any-file: 'scripts/init-without-ocr.sh' - - any-glob-to-any-file: 'scripts/installFonts.sh' - - any-glob-to-any-file: 'test.sh' - - any-glob-to-any-file: 'test2.sh' - -Devtools: - - changed-files: - - any-glob-to-any-file: '.devcontainer/**/*' - - any-glob-to-any-file: 'Dockerfile.dev' - -Test: - - changed-files: - - any-glob-to-any-file: 'cucumber/**/*' - - any-glob-to-any-file: 'common/src/test/**/*' - - any-glob-to-any-file: 'proprietary/src/test/**/*' - - any-glob-to-any-file: 'stirling-pdf/src/test/**/*' - - any-glob-to-any-file: 'src/testing/**/*' - - any-glob-to-any-file: '.pre-commit-config' - - any-glob-to-any-file: '.github/workflows/pre_commit.yml' - - any-glob-to-any-file: '.github/workflows/scorecards.yml' - -Github: - - changed-files: - - any-glob-to-any-file: '.github/**/*' diff --git a/.github/labels.yml b/.github/labels.yml index b7f5642e7..9b35ccb1a 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -175,3 +175,6 @@ description: "This PR changes 1000+ lines ignoring generated files." - name: "to research" color: "FBCA04" +- name: "pr-deployed" + color: "00FF00" + description: "Pull request has been deployed to a test environment" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index da5780860..b909f28e8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,5 +1,6 @@ # Description of Changes + --- @@ -15,15 +17,15 @@ Closes #(issue_number) ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) -- [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) -- [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) +- [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) +- [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) -- [ ] 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/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) @@ -31,4 +33,4 @@ Closes #(issue_number) ### Testing (if applicable) -- [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. +- [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. diff --git a/.github/scripts/check_language_properties.py b/.github/scripts/check_language_properties.py index 659ff7027..a77c378a6 100644 --- a/.github/scripts/check_language_properties.py +++ b/.github/scripts/check_language_properties.py @@ -197,7 +197,7 @@ def check_for_differences(reference_file, file_list, branch, actor): if len(file_list) == 1: file_arr = file_list[0].split() base_dir = os.path.abspath( - os.path.join(os.getcwd(), "stirling-pdf", "src", "main", "resources") + os.path.join(os.getcwd(), "app", "core", "src", "main", "resources") ) for file_path in file_arr: @@ -219,13 +219,14 @@ def check_for_differences(reference_file, file_list, branch, actor): # only local windows command not file_normpath.startswith( os.path.join( - "", "stirling-pdf", "src", "main", "resources", "messages_" + "", "app", "core", "src", "main", "resources", "messages_" ) ) and not file_normpath.startswith( os.path.join( os.getcwd(), - "stirling-pdf", + "app", + "core", "src", "main", "resources", @@ -328,7 +329,7 @@ def check_for_differences(reference_file, file_list, branch, actor): report.append("## ❌ Overall Check Status: **_Failed_**") report.append("") report.append( - f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/messages_en_GB.properties)" + f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/core/src/main/resources/messages_en_GB.properties)" ) else: report.append("## ✅ Overall Check Status: **_Success_**") @@ -389,7 +390,8 @@ if __name__ == "__main__": file_list = glob.glob( os.path.join( os.getcwd(), - "stirling-pdf", + "app", + "core", "src", "main", "resources", diff --git a/.github/scripts/requirements_pre_commit.txt b/.github/scripts/requirements_pre_commit.txt index ea034f5d1..4e2d2c2b6 100644 --- a/.github/scripts/requirements_pre_commit.txt +++ b/.github/scripts/requirements_pre_commit.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --generate-hashes --output-file='.github\scripts\requirements_pre_commit.txt' '.github\scripts\requirements_pre_commit.in' +# pip-compile --generate-hashes --output-file='.github\scripts\requirements_pre_commit.txt' --strip-extras '.github\scripts\requirements_pre_commit.in' # cfgv==3.4.0 \ --hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \ @@ -12,25 +12,25 @@ distlib==0.3.9 \ --hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \ --hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403 # via virtualenv -filelock==3.16.1 \ - --hash=sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0 \ - --hash=sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435 +filelock==3.18.0 \ + --hash=sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2 \ + --hash=sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de # via virtualenv -identify==2.6.5 \ - --hash=sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566 \ - --hash=sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc +identify==2.6.12 \ + --hash=sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2 \ + --hash=sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6 # via pre-commit nodeenv==1.9.1 \ --hash=sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f \ --hash=sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9 # via pre-commit -platformdirs==4.3.6 \ - --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ - --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb +platformdirs==4.3.8 \ + --hash=sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc \ + --hash=sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4 # via virtualenv -pre-commit==4.0.1 \ - --hash=sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2 \ - --hash=sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878 +pre-commit==4.2.0 \ + --hash=sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146 \ + --hash=sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd # via -r .github\scripts\requirements_pre_commit.in pyyaml==6.0.2 \ --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ @@ -87,7 +87,7 @@ pyyaml==6.0.2 \ --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 # via pre-commit -virtualenv==20.28.1 \ - --hash=sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb \ - --hash=sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329 +virtualenv==20.31.2 \ + --hash=sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11 \ + --hash=sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af # via pre-commit diff --git a/.github/scripts/requirements_sync_readme.txt b/.github/scripts/requirements_sync_readme.txt index 6b72d4086..e72486ab2 100644 --- a/.github/scripts/requirements_sync_readme.txt +++ b/.github/scripts/requirements_sync_readme.txt @@ -2,9 +2,9 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --generate-hashes --output-file='.github\scripts\requirements_sync_readme.txt' '.github\scripts\requirements_sync_readme.in' +# pip-compile --generate-hashes --output-file='.github\scripts\requirements_sync_readme.txt' --strip-extras '.github\scripts\requirements_sync_readme.in' # -tomlkit==0.13.2 \ - --hash=sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde \ - --hash=sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79 +tomlkit==0.13.3 \ + --hash=sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1 \ + --hash=sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0 # via -r .github\scripts\requirements_sync_readme.in diff --git a/.github/workflows/PR-Auto-Deploy-V2.yml b/.github/workflows/PR-Auto-Deploy-V2.yml new file mode 100644 index 000000000..d8df89585 --- /dev/null +++ b/.github/workflows/PR-Auto-Deploy-V2.yml @@ -0,0 +1,327 @@ +name: Auto PR V2 Deployment + +on: + pull_request: + types: [opened, synchronize, reopened] + + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + check-pr: + runs-on: ubuntu-latest + outputs: + should_deploy: ${{ steps.check-conditions.outputs.should_deploy }} + pr_number: ${{ github.event.number }} + pr_repository: ${{ steps.get-pr-info.outputs.repository }} + pr_ref: ${{ steps.get-pr-info.outputs.ref }} + steps: + - name: Harden Runner + uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + with: + egress-policy: audit + + - name: Check deployment conditions + id: check-conditions + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + PR_BRANCH: ${{ github.event.pull_request.head.ref }} + run: | + echo "PR Title: $PR_TITLE" + echo "PR Author: $PR_AUTHOR" + echo "PR Branch: $PR_BRANCH" + echo "PR Base Branch: ${{ github.event.pull_request.base.ref }}" + + # Define authorized users + authorized_users=( + "Frooodle" + "sf298" + "Ludy87" + "LaserKaspar" + "sbplat" + "reecebrowne" + "DarioGii" + "ConnorYoh" + ) + + # Check if author is in the authorized list + is_authorized=false + for user in "${authorized_users[@]}"; do + if [[ "$PR_AUTHOR" == "$user" ]]; then + is_authorized=true + break + fi + done + + # If PR is targeting feature/react-overhaul and user is authorized, deploy unconditionally + PR_BASE_BRANCH="${{ github.event.pull_request.base.ref }}" + if [[ "$PR_BASE_BRANCH" == "feature/react-overhaul" && "$is_authorized" == "true" ]]; then + echo "✅ Deployment forced: PR targets feature/react-overhaul and author is authorized." + echo "should_deploy=true" >> $GITHUB_OUTPUT + exit 0 + fi + + # Otherwise, continue with original keyword checks + has_v2_keyword=false + if [[ "$PR_TITLE" =~ [Vv]2 ]] || [[ "$PR_TITLE" =~ [Vv]ersion.?2 ]] || [[ "$PR_TITLE" =~ [Vv]ersion.?[Tt]wo ]]; then + has_v2_keyword=true + fi + + has_branch_keyword=false + if [[ "$PR_BRANCH" =~ [Vv]2 ]] || [[ "$PR_BRANCH" =~ [Rr]eact ]]; then + has_branch_keyword=true + fi + + if [[ "$is_authorized" == "true" && ( "$has_v2_keyword" == "true" || "$has_branch_keyword" == "true" ) ]]; then + echo "✅ Deployment conditions met" + echo "should_deploy=true" >> $GITHUB_OUTPUT + else + echo "❌ Deployment conditions not met" + echo " - Authorized user: $is_authorized" + echo " - Has V2 keyword in title: $has_v2_keyword" + echo " - Has V2/React keyword in branch: $has_branch_keyword" + echo "should_deploy=false" >> $GITHUB_OUTPUT + fi + + - name: Get PR repository and ref + id: get-pr-info + if: steps.check-conditions.outputs.should_deploy == 'true' + run: | + # For forks, use the full repository name, for internal PRs use the current repo + if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then + repository="${{ github.event.pull_request.head.repo.full_name }}" + else + repository="${{ github.repository }}" + fi + + echo "repository=$repository" >> $GITHUB_OUTPUT + echo "ref=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT + + deploy-v2-pr: + needs: check-pr + runs-on: ubuntu-latest + if: needs.check-pr.outputs.should_deploy == 'true' + # Concurrency control - only one deployment per PR at a time + concurrency: + group: v2-deploy-pr-${{ needs.check-pr.outputs.pr_number }} + cancel-in-progress: true + permissions: + contents: read + issues: write + pull-requests: write + + steps: + - name: Harden Runner + uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + with: + egress-policy: audit + + - name: Checkout main repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + repository: ${{ github.repository }} + ref: main + + - name: Setup GitHub App Bot + if: github.actor != 'dependabot[bot]' + id: setup-bot + uses: ./.github/actions/setup-bot + continue-on-error: true + with: + app-id: ${{ secrets.GH_APP_ID }} + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + + - name: Add deployment started comment + id: deployment-started + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + github-token: ${{ steps.setup-bot.outputs.token }} + script: | + const { owner, repo } = context.repo; + const prNumber = ${{ needs.check-pr.outputs.pr_number }}; + + // Delete previous V2 deployment comments to avoid clutter + const { data: comments } = await github.rest.issues.listComments({ + owner, + repo, + issue_number: prNumber, + per_page: 100 + }); + + const v2Comments = comments.filter(comment => + comment.body.includes('🚀 **Auto-deploying V2 version**') || + comment.body.includes('## 🚀 V2 Auto-Deployment Complete!') || + comment.body.includes('❌ **V2 Auto-deployment failed**') + ); + + for (const comment of v2Comments) { + console.log(`Deleting old V2 comment: ${comment.id}`); + await github.rest.issues.deleteComment({ + owner, + repo, + comment_id: comment.id + }); + } + + // Create new deployment started comment + const { data: newComment } = await github.rest.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: `🚀 **Auto-deploying V2 version** for PR #${prNumber}...\n\n_This is an automated deployment triggered by V2/version2 keywords in the PR title or V2/React keywords in the branch name._\n\n⚠️ **Note:** If new commits are pushed during deployment, this build will be cancelled and replaced with the latest version.` + }); + + return newComment.id; + + - name: Checkout PR + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + repository: ${{ needs.check-pr.outputs.pr_repository }} + ref: ${{ needs.check-pr.outputs.pr_ref }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up JDK + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + with: + java-version: "17" + distribution: "temurin" + + - name: Build backend + run: | + export DISABLE_ADDITIONAL_FEATURES=true + ./gradlew clean build + env: + STIRLING_PDF_DESKTOP_UI: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Get version number + id: versionNumber + run: | + VERSION=$(grep "^version =" build.gradle | awk -F'"' '{print $2}') + echo "versionNumber=$VERSION" >> $GITHUB_OUTPUT + + - name: Login to Docker Hub + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_API }} + + - name: Build and push V2 monolith image + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + file: ./docker/monolith/Dockerfile + push: true + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }} + build-args: VERSION_TAG=v2-alpha + platforms: linux/amd64 + + - name: Set up SSH + run: | + mkdir -p ~/.ssh/ + echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key + sudo chmod 600 ../private.key + + - name: Deploy V2 to VPS + id: deploy + run: | + # Use same port strategy as regular PRs - just the PR number + V2_PORT=${{ needs.check-pr.outputs.pr_number }} + + # Create docker-compose for V2 monolith + cat > docker-compose.yml << EOF + version: '3.3' + services: + stirling-pdf-v2: + container_name: stirling-pdf-v2-pr-${{ needs.check-pr.outputs.pr_number }} + image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }} + ports: + - "${V2_PORT}:80" # Frontend port (same as regular PRs) + volumes: + - /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/data:/usr/share/tessdata:rw + - /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/config:/configs:rw + - /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/logs:/logs:rw + environment: + DISABLE_ADDITIONAL_FEATURES: "true" + SECURITY_ENABLELOGIN: "false" + SYSTEM_DEFAULTLOCALE: en-GB + UI_APPNAME: "Stirling-PDF V2 PR#${{ needs.check-pr.outputs.pr_number }}" + UI_HOMEDESCRIPTION: "V2 PR#${{ needs.check-pr.outputs.pr_number }} - Frontend/Backend Split Architecture" + UI_APPNAMENAVBAR: "V2 PR#${{ needs.check-pr.outputs.pr_number }}" + SYSTEM_MAXFILESIZE: "100" + METRICS_ENABLED: "true" + SYSTEM_GOOGLEVISIBILITY: "false" + restart: on-failure:5 + EOF + + # Deploy to VPS + scp -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null docker-compose.yml ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }}:/tmp/docker-compose-v2.yml + + ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << ENDSSH + # Create V2 PR-specific directories + mkdir -p /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/{data,config,logs} + + # Move docker-compose file to correct location + mv /tmp/docker-compose-v2.yml /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/docker-compose.yml + + # Stop any existing container and clean up + cd /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }} + docker-compose down --remove-orphans 2>/dev/null || true + + # Start the new container + docker-compose pull + docker-compose up -d + + # Clean up unused Docker resources to save space + docker system prune -af --volumes + ENDSSH + + # Set port for output + echo "v2_port=${V2_PORT}" >> $GITHUB_OUTPUT + + - name: Post V2 deployment URL to PR + if: success() + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + github-token: ${{ steps.setup-bot.outputs.token }} + script: | + const { owner, repo } = context.repo; + const prNumber = ${{ needs.check-pr.outputs.pr_number }}; + const v2Port = ${{ steps.deploy.outputs.v2_port }}; + + // Delete the "deploying..." comment since we're posting the final result + const deploymentStartedId = ${{ steps.deployment-started.outputs.result }}; + if (deploymentStartedId) { + console.log(`Deleting deployment started comment: ${deploymentStartedId}`); + try { + await github.rest.issues.deleteComment({ + owner, + repo, + comment_id: deploymentStartedId + }); + } catch (error) { + console.log(`Could not delete deployment started comment: ${error.message}`); + } + } + + const deploymentUrl = `http://${{ secrets.VPS_HOST }}:${v2Port}`; + + const commentBody = `## 🚀 V2 Auto-Deployment Complete!\n\n` + + `Your V2 PR with the new frontend/backend split architecture has been deployed!\n\n` + + `🔗 **V2 Test URL:** [${deploymentUrl}](${deploymentUrl})\n\n` + + `_This deployment will be automatically cleaned up when the PR is closed._\n\n` + + `🔄 **Auto-deployed** because PR title or branch name contains V2/version2/React keywords.`; + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: commentBody + }); + diff --git a/.github/workflows/PR-Demo-Comment-with-react.yml b/.github/workflows/PR-Demo-Comment-with-react.yml index 874081068..877a78524 100644 --- a/.github/workflows/PR-Demo-Comment-with-react.yml +++ b/.github/workflows/PR-Demo-Comment-with-react.yml @@ -6,20 +6,18 @@ on: permissions: contents: read - issues: write # Required for adding reactions to comments - pull-requests: read # Required for reading PR information + pull-requests: read jobs: check-comment: runs-on: ubuntu-latest permissions: issues: write - pull-requests: read if: | github.event.issue.pull_request && ( - contains(github.event.comment.body, 'prdeploy') || - contains(github.event.comment.body, 'deploypr') + contains(github.event.comment.body, 'prdeploy') || + contains(github.event.comment.body, 'deploypr') ) && ( @@ -30,6 +28,7 @@ jobs: github.event.comment.user.login == 'sbplat' || github.event.comment.user.login == 'reecebrowne' || github.event.comment.user.login == 'DarioGii' || + github.event.comment.user.login == 'EthanHealy01' || github.event.comment.user.login == 'ConnorYoh' ) outputs: @@ -42,14 +41,18 @@ jobs: enable_enterprise: ${{ steps.check-pro-flag.outputs.enable_enterprise }} steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit - # Generate GitHub App token - - name: Generate GitHub App Token - id: generate-token - uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6 + - name: Checkout PR + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup GitHub App Bot + if: github.actor != 'dependabot[bot]' + id: setup-bot + uses: ./.github/actions/setup-bot + continue-on-error: true with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} @@ -122,7 +125,7 @@ jobs: id: add-eyes-reaction uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: - github-token: ${{ steps.generate-token.outputs.token }} + github-token: ${{ steps.setup-bot.outputs.token }} script: | console.log(`Adding eyes reaction to comment ID: ${context.payload.comment.id}`); try { @@ -144,18 +147,23 @@ jobs: needs: check-comment runs-on: ubuntu-latest permissions: - contents: read issues: write + pull-requests: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit - - name: Generate GitHub App Token - id: generate-token - uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6 + - name: Checkout PR + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup GitHub App Bot + if: github.actor != 'dependabot[bot]' + id: setup-bot + uses: ./.github/actions/setup-bot + continue-on-error: true with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} @@ -165,7 +173,7 @@ jobs: with: repository: ${{ needs.check-comment.outputs.pr_repository }} ref: ${{ needs.check-comment.outputs.pr_ref }} - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.setup-bot.outputs.token }} - name: Set up JDK uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 @@ -187,12 +195,6 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - name: Get version number - id: versionNumber - run: | - VERSION=$(grep "^version =" build.gradle | awk -F'"' '{print $2}') - echo "versionNumber=$VERSION" >> $GITHUB_OUTPUT - - name: Login to Docker Hub uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: @@ -296,7 +298,7 @@ jobs: if: success() uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: - github-token: ${{ steps.generate-token.outputs.token }} + github-token: ${{ steps.setup-bot.outputs.token }} script: | console.log(`Adding rocket reaction to comment ID: ${{ needs.check-comment.outputs.comment_id }}`); try { @@ -312,11 +314,26 @@ jobs: console.error(error); } + // add label to PR + const prNumber = ${{ needs.check-comment.outputs.pr_number }}; + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + labels: ['pr-deployed'] + }); + console.log(`Added 'pr-deployed' label to PR #${prNumber}`); + } catch (error) { + console.error(`Failed to add label to PR: ${error.message}`); + console.error(error); + } + - name: Add failure reaction to comment if: failure() uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: - github-token: ${{ steps.generate-token.outputs.token }} + github-token: ${{ steps.setup-bot.outputs.token }} script: | console.log(`Adding -1 reaction to comment ID: ${{ needs.check-comment.outputs.comment_id }}`); try { @@ -336,7 +353,7 @@ jobs: if: success() uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: - github-token: ${{ steps.generate-token.outputs.token }} + github-token: ${{ steps.setup-bot.outputs.token }} script: | const { GITHUB_REPOSITORY } = process.env; const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/'); @@ -356,3 +373,11 @@ jobs: issue_number: prNumber, body: commentBody }); + + - name: Cleanup temporary files + if: always() + run: | + echo "Cleaning up temporary files..." + rm -f ../private.key docker-compose.yml + echo "Cleanup complete." + continue-on-error: true diff --git a/.github/workflows/PR-Demo-cleanup.yml b/.github/workflows/PR-Demo-cleanup.yml index ae17ee7c8..855e804b2 100644 --- a/.github/workflows/PR-Demo-cleanup.yml +++ b/.github/workflows/PR-Demo-cleanup.yml @@ -1,7 +1,7 @@ name: PR Deployment cleanup on: - pull_request: + pull_request_target: types: [opened, synchronize, reopened, closed] permissions: @@ -13,25 +13,99 @@ env: jobs: cleanup: + if: github.event.action == 'closed' runs-on: ubuntu-latest permissions: - contents: write pull-requests: write - if: github.event.action == 'closed' + issues: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit + - name: Checkout PR + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup GitHub App Bot + if: github.actor != 'dependabot[bot]' + id: setup-bot + uses: ./.github/actions/setup-bot + continue-on-error: true + with: + app-id: ${{ secrets.GH_APP_ID }} + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + + - name: Remove 'pr-deployed' label if present + id: remove-label-comment + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + github-token: ${{ steps.setup-bot.outputs.token }} + script: | + const prNumber = ${{ github.event.pull_request.number }}; + const owner = context.repo.owner; + const repo = context.repo.repo; + + // Get all labels on the PR + const { data: labels } = await github.rest.issues.listLabelsOnIssue({ + owner, + repo, + issue_number: prNumber + }); + + const hasLabel = labels.some(label => label.name === 'pr-deployed'); + + if (hasLabel) { + console.log("Label 'pr-deployed' found. Removing..."); + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: prNumber, + name: 'pr-deployed' + }); + } else { + console.log("Label 'pr-deployed' not found. Nothing to do."); + } + + // Find existing bot comments about the deployment + const { data: comments } = await github.rest.issues.listComments({ + owner, + repo, + issue_number: prNumber + }); + const deploymentComments = comments.filter(c => + c.body?.includes("## 🚀 PR Test Deployment") && + c.user?.type === "Bot" + ); + + if (deploymentComments.length > 0) { + for (const comment of deploymentComments) { + await github.rest.issues.deleteComment({ + owner, + repo, + comment_id: comment.id + }); + console.log(`Deleted deployment comment (ID: ${comment.id})`); + } + } else { + console.log("No matching deployment comments found."); + } + + // Set flag if either label or comment was present + const hasDeploymentComment = deploymentComments.length > 0; + core.setOutput('present', (hasLabel || hasDeploymentComment) ? 'true' : 'false'); + + - name: Set up SSH + if: steps.remove-label-comment.outputs.present == 'true' run: | mkdir -p ~/.ssh/ echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key sudo chmod 600 ../private.key - name: Cleanup PR deployment + if: steps.remove-label-comment.outputs.present == 'true' id: cleanup run: | ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH' @@ -57,3 +131,11 @@ jobs: echo "NO_CLEANUP_NEEDED" fi ENDSSH + + - name: Cleanup temporary files + if: always() + run: | + echo "Cleaning up temporary files..." + rm -f ../private.key + echo "Cleanup complete." + continue-on-error: true diff --git a/.github/workflows/ai_pr_title_review.yml b/.github/workflows/ai_pr_title_review.yml index 0447a9b62..b9fd7c277 100644 --- a/.github/workflows/ai_pr_title_review.yml +++ b/.github/workflows/ai_pr_title_review.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/auto-labeler.yml b/.github/workflows/auto-labeler.yml deleted file mode 100644 index 5828a2556..000000000 --- a/.github/workflows/auto-labeler.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: "Pull Request Labeler" -on: - pull_request_target: - types: [opened, synchronize] - -permissions: - contents: read - -jobs: - labeler: - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Apply Labels - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - configuration-path: .github/labeler-config.yml - sync-labels: true diff --git a/.github/workflows/auto-labelerV2.yml b/.github/workflows/auto-labelerV2.yml index dec73ddac..bf290de76 100644 --- a/.github/workflows/auto-labelerV2.yml +++ b/.github/workflows/auto-labelerV2.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a4666956..aa98d2a1e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -48,12 +48,12 @@ jobs: if: always() run: | declare -a dirs=( - "stirling-pdf/build/reports/tests/" - "stirling-pdf/build/test-results/" - "common/build/reports/tests/" - "common/build/test-results/" - "proprietary/build/reports/tests/" - "proprietary/build/test-results/" + "app/core/build/reports/tests/" + "app/core/build/test-results/" + "app/common/build/reports/tests/" + "app/common/build/test-results/" + "app/proprietary/build/reports/tests/" + "app/proprietary/build/test-results/" ) missing_reports=() for dir in "${dirs[@]}"; do @@ -74,24 +74,51 @@ jobs: with: name: test-reports-jdk-${{ matrix.jdk-version }}-spring-security-${{ matrix.spring-security }} path: | - stirling-pdf/build/reports/tests/ - stirling-pdf/build/test-results/ - stirling-pdf/build/reports/problems/ - common/build/reports/tests/ - common/build/test-results/ - common/build/reports/problems/ - proprietary/build/reports/tests/ - proprietary/build/test-results/ - proprietary/build/reports/problems/ + app/core/build/reports/tests/ + app/core/build/test-results/ + app/core/build/reports/problems/ + app/common/build/reports/tests/ + app/common/build/test-results/ + app/common/build/reports/problems/ + app/proprietary/build/reports/tests/ + app/proprietary/build/test-results/ + app/proprietary/build/reports/problems/ build/reports/problems/ retention-days: 3 if-no-files-found: warn + check-generateOpenApiDocs: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up JDK 17 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + with: + java-version: "17" + distribution: "temurin" + + - uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 + + - name: Generate OpenAPI documentation + run: ./gradlew :stirling-pdf:generateOpenApiDocs + + - name: Upload OpenAPI Documentation + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: openapi-docs + path: ./SwaggerDoc.json + check-licence: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -135,7 +162,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/check_properties.yml b/.github/workflows/check_properties.yml index 7c2c075b3..da000201a 100644 --- a/.github/workflows/check_properties.yml +++ b/.github/workflows/check_properties.yml @@ -4,7 +4,7 @@ on: pull_request_target: types: [opened, synchronize, reopened] paths: - - "stirling-pdf/src/main/resources/messages_*.properties" + - "app/core/src/main/resources/messages_*.properties" permissions: contents: read # Allow read access to repository content @@ -18,7 +18,7 @@ jobs: pull-requests: write # Allow writing to pull requests steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -67,7 +67,7 @@ jobs: exit 1 fi # Get changed files and filter for properties files, handle case where no matches are found - gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^stirling-pdf/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt || echo "No matching properties files found in PR" + gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^app/core/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt || echo "No matching properties files found in PR" # Check if any files were found if [ ! -s changed_files.txt ]; then echo "No properties files changed in this PR" @@ -117,7 +117,7 @@ jobs: const changedFiles = files .filter(file => file.status !== "removed" && - /^stirling-pdf\/src\/main\/resources\/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$/.test(file.filename) + /^app\/core\/src\/main\/resources\/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$/.test(file.filename) ) .map(file => file.filename); @@ -157,12 +157,12 @@ jobs: // Determine reference file let referenceFilePath; - if (changedFiles.includes("stirling-pdf/src/main/resources/messages_en_GB.properties")) { + if (changedFiles.includes("app/core/src/main/resources/messages_en_GB.properties")) { console.log("Using PR branch reference file."); const { data: fileContent } = await github.rest.repos.getContent({ owner: prRepoOwner, repo: prRepoName, - path: "stirling-pdf/src/main/resources/messages_en_GB.properties", + path: "app/core/src/main/resources/messages_en_GB.properties", ref: branch, }); @@ -174,7 +174,7 @@ jobs: const { data: fileContent } = await github.rest.repos.getContent({ owner: repoOwner, repo: repoName, - path: "stirling-pdf/src/main/resources/messages_en_GB.properties", + path: "app/core/src/main/resources/messages_en_GB.properties", ref: "main", }); diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 4f44295f7..154b6bdae 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/licenses-update.yml b/.github/workflows/licenses-update.yml index 227948288..ba66627ad 100644 --- a/.github/workflows/licenses-update.yml +++ b/.github/workflows/licenses-update.yml @@ -19,7 +19,7 @@ jobs: repository-projects: write # Required for enabling automerge steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -57,11 +57,11 @@ jobs: - name: Move and rename license file run: | - mv build/reports/dependency-license/index.json stirling-pdf/src/main/resources/static/3rdPartyLicenses.json + mv build/reports/dependency-license/index.json app/core/src/main/resources/static/3rdPartyLicenses.json - name: Commit changes run: | - git add stirling-pdf/src/main/resources/static/3rdPartyLicenses.json + git add app/core/src/main/resources/static/3rdPartyLicenses.json git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV - name: Create Pull Request diff --git a/.github/workflows/manage-label.yml b/.github/workflows/manage-label.yml index 3f123afbd..15349a66d 100644 --- a/.github/workflows/manage-label.yml +++ b/.github/workflows/manage-label.yml @@ -15,7 +15,7 @@ jobs: issues: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index e2f33fae0..3cac33e1f 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -21,27 +21,31 @@ jobs: versionMac: ${{ steps.versionNumberMac.outputs.versionNumberMac }} steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - # Get version number + - name: Set up JDK + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + with: + distribution: 'temurin' + java-version: '21' + + # ✅ Get version from Gradle - name: Get version number id: versionNumber run: | - VERSION=$(grep "^version =" build.gradle | awk -F'"' '{print $2}') + VERSION=$(./gradlew printVersion --quiet | tail -1) echo "versionNumber=$VERSION" >> $GITHUB_OUTPUT + # ✅ Get Mac-specific version from Gradle - name: Get version number mac id: versionNumberMac run: | - VERSION=$(grep "^version =" build.gradle | awk -F'"' '{print $2}') - CURRENT_YEAR=$(date +'%Y') - IFS='.' read -r -a VERSION_PARTS <<< "$VERSION" - MAC_VERSION="$CURRENT_YEAR.${VERSION_PARTS[1]:-0}.${VERSION_PARTS[2]:-0}" - echo "versionNumberMac=$MAC_VERSION" >> $GITHUB_OUTPUT + VERSION_MAC=$(./gradlew printMacVersion --quiet | tail -1) + echo "versionNumberMac=$VERSION_MAC" >> $GITHUB_OUTPUT build-portable: needs: read_versions @@ -56,7 +60,7 @@ jobs: file_suffix: "" steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -82,7 +86,7 @@ jobs: run: | mkdir ./binaries mv ./build/launch4j/Stirling-PDF.exe ./binaries/win-Stirling-PDF-portable-Server${{ matrix.file_suffix }}.exe - mv ./build/libs/Stirling-PDF-${{ needs.read_versions.outputs.version }}.jar ./binaries/Stirling-PDF${{ matrix.file_suffix }}.jar + mv ./app/core/build/libs/stirling-pdf-${{ needs.read_versions.outputs.version }}.jar ./binaries/Stirling-PDF${{ matrix.file_suffix }}.jar - name: Upload build artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -106,7 +110,7 @@ jobs: file_suffix: "" steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -144,7 +148,7 @@ jobs: contents: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -234,7 +238,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -248,7 +252,7 @@ jobs: - name: Install Cosign if: matrix.os == 'windows-latest' - uses: sigstore/cosign-installer@fb28c2b6339dcd94da6e4cbcbc5e888961f6f8c3 # v3.9.0 + uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1 - name: Generate key pair if: matrix.os == 'windows-latest' @@ -297,7 +301,7 @@ jobs: contents: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml index 1190c49cd..ebe81c5a8 100644 --- a/.github/workflows/pre_commit.yml +++ b/.github/workflows/pre_commit.yml @@ -16,7 +16,7 @@ jobs: pull-requests: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 39f022586..432925f1a 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -18,7 +18,7 @@ jobs: id-token: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -42,7 +42,7 @@ jobs: - name: Install cosign if: github.ref == 'refs/heads/master' - uses: sigstore/cosign-installer@fb28c2b6339dcd94da6e4cbcbc5e888961f6f8c3 # v3.9.0 + uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1 with: cosign-release: "v2.4.1" @@ -77,6 +77,7 @@ jobs: - name: Generate tags id: meta uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + if: github.ref != 'refs/heads/main' with: images: | ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf @@ -86,11 +87,11 @@ jobs: tags: | type=raw,value=${{ steps.versionNumber.outputs.versionNumber }},enable=${{ github.ref == 'refs/heads/master' }} type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }} - type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push main Dockerfile id: build-push-regular uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + if: github.ref != 'refs/heads/main' with: builder: ${{ steps.buildx.outputs.name }} context: . @@ -153,7 +154,6 @@ jobs: - name: Generate tags fat id: meta3 uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 - if: github.ref != 'refs/heads/main' with: images: | ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf @@ -163,11 +163,11 @@ jobs: tags: | type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-fat,enable=${{ github.ref == 'refs/heads/master' }} type=raw,value=latest-fat,enable=${{ github.ref == 'refs/heads/master' }} + type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push main Dockerfile fat id: build-push-fat uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 - if: github.ref != 'refs/heads/main' with: builder: ${{ steps.buildx.outputs.name }} context: . diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 76c711734..701bb678e 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -23,7 +23,7 @@ jobs: version: ${{ steps.versionNumber.outputs.versionNumber }} steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -83,7 +83,7 @@ jobs: file_suffix: "" steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -95,7 +95,7 @@ jobs: run: ls -R - name: Install Cosign - uses: sigstore/cosign-installer@fb28c2b6339dcd94da6e4cbcbc5e888961f6f8c3 # v3.9.0 + uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1 - name: Generate key pair run: cosign generate-key-pair @@ -161,7 +161,7 @@ jobs: file_suffix: "" steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index a79dc0ec2..948a5a37b 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -74,6 +74,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 with: sarif_file: results.sarif diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index 187e823ae..f708a5b8d 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 17d81412a..237040f0a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,7 +16,7 @@ jobs: pull-requests: write steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml index 6b9307887..463736b65 100644 --- a/.github/workflows/swagger.yml +++ b/.github/workflows/swagger.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -29,7 +29,7 @@ jobs: - uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 - name: Generate Swagger documentation - run: ./gradlew generateOpenApiDocs + run: ./gradlew :stirling-pdf:generateOpenApiDocs - name: Upload Swagger Documentation to SwaggerHub run: ./gradlew swaggerhubUpload diff --git a/.github/workflows/sync_files.yml b/.github/workflows/sync_files.yml index f89f36b2a..620209dbb 100644 --- a/.github/workflows/sync_files.yml +++ b/.github/workflows/sync_files.yml @@ -8,8 +8,8 @@ on: paths: - "build.gradle" - "README.md" - - "stirling-pdf/src/main/resources/messages_*.properties" - - "stirling-pdf/src/main/resources/static/3rdPartyLicenses.json" + - "app/core/src/main/resources/messages_*.properties" + - "app/core/src/main/resources/static/3rdPartyLicenses.json" - "scripts/ignore_translation.toml" permissions: @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -41,11 +41,11 @@ jobs: - name: Sync translation property files run: | - python .github/scripts/check_language_properties.py --reference-file "stirling-pdf/src/main/resources/messages_en_GB.properties" --branch main + python .github/scripts/check_language_properties.py --reference-file "app/core/src/main/resources/messages_en_GB.properties" --branch main - name: Commit translation files run: | - git add stirling-pdf/src/main/resources/messages_*.properties + git add app/core/src/main/resources/messages_*.properties git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "No changes detected" - name: Install dependencies @@ -57,8 +57,8 @@ jobs: - name: Run git add run: | - git add README.md - git diff --staged --quiet || git commit -m ":memo: Sync README.md" || echo "No changes detected" + git add README.md scripts/ignore_translation.toml + git diff --staged --quiet || git commit -m ":memo: Sync README.md & scripts/ignore_translation.toml" || echo "No changes detected" - name: Create Pull Request if: always() @@ -101,4 +101,4 @@ jobs: sign-commits: true add-paths: | README.md - stirling-pdf/src/main/resources/messages_*.properties + app/core/src/main/resources/messages_*.properties diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index d0244619d..2f818fbd0 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -105,7 +105,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit @@ -134,7 +134,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit diff --git a/.gitignore b/.gitignore index 52e57d719..8a5168e49 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ clientWebUI/ !cucumber/exampleFiles/ !cucumber/exampleFiles/example_html.zip exampleYmlFiles/stirling/ +stirling/ /testing/file_snapshots SwaggerDoc.json @@ -125,9 +126,12 @@ SwaggerDoc.json *.rar *.db /build -/stirling-pdf/build -/common/build -/proprietary/build +/app/core/build +/app/common/build +/app/proprietary/build +common/build +proprietary/build +stirling-pdf/build # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5418deaea..094e9b2fa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - --skip="./.*,*.csv,*.json,*.ambr" - --quiet-level=2 files: \.(html|css|js|py|md)$ - exclude: (.vscode|.devcontainer|stirling-pdf/src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js) + exclude: (.vscode|.devcontainer|app/core/src/main/resources|app/proprietary/src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js) - repo: https://github.com/gitleaks/gitleaks rev: v8.27.2 hooks: @@ -34,3 +34,13 @@ repos: - id: trailing-whitespace files: ^.*(\.js|\.java|\.py|\.yml)$ exclude: ^(.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js|\.github/workflows/.*$) + # - repo: https://github.com/thibaudcolas/pre-commit-stylelint + # rev: v16.21.1 + # hooks: + # - id: stylelint + # additional_dependencies: + # - stylelint@16.21.1 + # - stylelint-config-standard@38.0.0 + # - "@stylistic/stylelint-plugin@3.1.3" + # files: \.(css)$ + # args: [--fix] \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 128af83ba..6ab09796f 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -17,5 +17,7 @@ "GitHub.vscode-pull-request-github", // GitHub Pull Requests extension for Visual Studio Code "charliermarsh.ruff", // Ruff code formatter for Python to follow the Ruff Style Guide "yzhang.markdown-all-in-one", // Markdown All-in-One extension for enhanced Markdown editing + "stylelint.vscode-stylelint", // Stylelint extension for CSS and SCSS linting + "redhat.vscode-yaml", // YAML extension for Visual Studio Code ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 3f272e18a..abc54d43e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,12 +3,18 @@ "editor.guides.bracketPairs": "active", "editor.guides.bracketPairsHorizontal": "active", "cSpell.enabled": false, + "[feature]": { + "editor.defaultFormatter": "alexkrechik.cucumberautocomplete" + }, "[java]": { "editor.defaultFormatter": "josevseb.google-java-format-for-vs-code" }, "[jsonc]": { "editor.defaultFormatter": "vscode.json-language-features" }, + "[css]": { + "editor.defaultFormatter": "stylelint.vscode-stylelint" + }, "[json]": { "editor.defaultFormatter": "vscode.json-language-features" }, @@ -27,6 +33,9 @@ "[gradle]": { "editor.defaultFormatter": "vscjava.vscode-gradle" }, + "[yaml]": { + "editor.defaultFormatter": "redhat.vscode-yaml" + }, "java.compile.nullAnalysis.mode": "automatic", "java.configuration.updateBuildConfiguration": "interactive", "java.format.enabled": true, @@ -70,13 +79,17 @@ ".venv*/", ".vscode/", "bin/", - "common/bin/", - "proprietary/bin/", + "app/core/bin/", + "app/common/bin/", + "app/proprietary/bin/", "build/", - "common/build/", - "proprietary/build/", + "app/core/build/", + "app/common/build/", + "app/proprietary/build/", "configs/", + "app/core/configs/", "customFiles/", + "app/core/customFiles/", "docs/", "exampleYmlFiles", "gradle/", @@ -88,8 +101,9 @@ ".git-blame-ignore-revs", ".gitattributes", ".gitignore", - "common/.gitignore", - "proprietary/.gitignore", + "app/core/.gitignore", + "app/common/.gitignore", + "app/proprietary/.gitignore", ".pre-commit-config.yaml", ], // Enables signature help in Java. @@ -119,9 +133,10 @@ "html.format.indentHandlebars": true, "html.format.preserveNewLines": true, "html.format.maxPreserveNewLines": 2, + "stylelint.configFile": "devTools/.stylelintrc.json", "java.project.sourcePaths": [ - "stirling-pdf/src/main/java", - "common/src/main/java", - "proprietary/src/main/java" + "app/core/src/main/java", + "app/common/src/main/java", + "app/proprietary/src/main/java" ] } diff --git a/CLAUDE.md b/CLAUDE.md index 05bfb5254..8bdd7c235 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,23 +25,54 @@ Set `DOCKER_ENABLE_SECURITY=true` environment variable to enable security featur - **Proxy Configuration**: Vite proxies `/api/*` calls to backend (localhost:8080) - **Build Process**: DO NOT run build scripts manually - builds are handled by CI/CD pipelines - **Package Installation**: DO NOT run npm install commands - package management handled separately +- **Deployment Options**: + - **Desktop App**: `npm run tauri-build` (native desktop application) + - **Web Server**: `npm run build` then serve dist/ folder + - **Development**: `npm run tauri-dev` for desktop dev mode -#### Tailwind CSS Setup (if not already installed) -```bash -cd frontend -npm install -D tailwindcss postcss autoprefixer -npx tailwindcss init -p -``` +#### Multi-Tool Workflow Architecture +Frontend designed for **stateful document processing**: +- Users upload PDFs once, then chain tools (split → merge → compress → view) +- File state and processing results persist across tool switches +- No file reloading between tools - performance critical for large PDFs (up to 100GB+) + +#### FileContext - Central State Management +**Location**: `src/contexts/FileContext.tsx` +- **Active files**: Currently loaded PDFs and their variants +- **Tool navigation**: Current mode (viewer/pageEditor/fileEditor/toolName) +- **Memory management**: PDF document cleanup, blob URL lifecycle, Web Worker management +- **IndexedDB persistence**: File storage with thumbnail caching +- **Preview system**: Tools can preview results (e.g., Split → Viewer → back to Split) without context pollution + +**Critical**: All file operations go through FileContext. Don't bypass with direct file handling. + +#### Processing Services +- **enhancedPDFProcessingService**: Background PDF parsing and manipulation +- **thumbnailGenerationService**: Web Worker-based with main-thread fallback +- **fileStorage**: IndexedDB with LRU cache management + +#### Memory Management Strategy +**Why manual cleanup exists**: Large PDFs (up to 100GB+) through multiple tools accumulate: +- PDF.js documents that need explicit .destroy() calls +- Blob URLs from tool outputs that need revocation +- Web Workers that need termination +Without cleanup: browser crashes with memory leaks. + +#### Tool Development +- **Pattern**: Follow `src/tools/Split.tsx` as reference implementation +- **File Access**: Tools receive `selectedFiles` prop (computed from activeFiles based on user selection) +- **File Selection**: Users select files in FileEditor (tool mode) → stored as IDs → computed to File objects for tools +- **Integration**: All files are part of FileContext ecosystem - automatic memory management and operation tracking +- **Parameters**: Tool parameter handling patterns still being standardized +- **Preview Integration**: Tools can implement preview functionality (see Split tool's thumbnail preview) ## Architecture Overview ### Project Structure - **Backend**: Spring Boot application with Thymeleaf templating -- **Frontend**: React-based SPA in `/frontend` directory (replacing legacy Thymeleaf templates) - - **Current Status**: Active development to replace Thymeleaf UI with modern React SPA +- **Frontend**: React-based SPA in `/frontend` directory (Thymeleaf templates fully replaced) - **File Storage**: IndexedDB for client-side file persistence and thumbnails - **Internationalization**: JSON-based translations (converted from backend .properties) - - **URL Parameters**: Deep linking support for tool states and configurations - **PDF Processing**: PDFBox for core PDF operations, LibreOffice for conversions, PDF.js for client-side rendering - **Security**: Spring Security with optional authentication (controlled by `DOCKER_ENABLE_SECURITY`) - **Configuration**: YAML-based configuration with environment variable overrides @@ -59,9 +90,8 @@ npx tailwindcss init -p - **Pipeline System**: Automated PDF processing workflows via `PipelineController` - **Security Layer**: Authentication, authorization, and user management (when enabled) -### Template System (Legacy + Modern) -- **Legacy Thymeleaf Templates**: Located in `src/main/resources/templates/` (being phased out) -- **Modern React Components**: Located in `frontend/src/components/` and `frontend/src/tools/` +### Component Architecture +- **React Components**: Located in `frontend/src/components/` and `frontend/src/tools/` - **Static Assets**: CSS, JS, and resources in `src/main/resources/static/` (legacy) + `frontend/public/` (modern) - **Internationalization**: - Backend: `messages_*.properties` files @@ -91,13 +121,14 @@ npx tailwindcss init -p - Frontend: Update JSON files in `frontend/public/locales/` or use conversion script 5. **Documentation**: API docs auto-generated and available at `/swagger-ui/index.html` -## Frontend Migration Notes +## Frontend Architecture Status -- **Current Branch**: `feature/react-overhaul` - Active React SPA development -- **Migration Status**: Core tools (Split, Merge, Compress) converted to React with URL parameter support -- **File Management**: Implemented IndexedDB storage with thumbnail generation using PDF.js -- **Tools Architecture**: Each tool receives `params` and `updateParams` for URL state synchronization -- **Remaining Work**: Convert remaining Thymeleaf templates to React components +- **Core Status**: React SPA architecture complete with multi-tool workflow support +- **State Management**: FileContext handles all file operations and tool navigation +- **File Processing**: Production-ready with memory management for large PDF workflows (up to 100GB+) +- **Tool Integration**: Standardized tool interface - see `src/tools/Split.tsx` as reference +- **Preview System**: Tool results can be previewed without polluting file context (Split tool example) +- **Performance**: Web Worker thumbnails, IndexedDB persistence, background processing ## Important Notes @@ -108,6 +139,11 @@ npx tailwindcss init -p - **Backend**: Designed to be stateless - files are processed in memory/temp locations only - **Frontend**: Uses IndexedDB for client-side file storage and caching (with thumbnails) - **Security**: When `DOCKER_ENABLE_SECURITY=false`, security-related classes are excluded from compilation +- **FileContext**: All file operations MUST go through FileContext - never bypass with direct File handling +- **Memory Management**: Manual cleanup required for PDF.js documents and blob URLs - don't remove cleanup code +- **Tool Development**: New tools should follow Split tool pattern (`src/tools/Split.tsx`) +- **Performance Target**: Must handle PDFs up to 100GB+ without browser crashes +- **Preview System**: Tools can preview results without polluting main file context (see Split tool implementation) ## Communication Style - Be direct and to the point diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9fad6ecbd..d9828c409 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,7 +25,7 @@ Please make sure your Pull Request adheres to the following guidelines: ## Translations -If you would like to add or modify a translation, please see [How to add new languages to Stirling-PDF](HowToAddNewLanguage.md). Also, please create a Pull Request so others can use it! +If you would like to add or modify a translation, please see [How to add new languages to Stirling-PDF](devGuide/HowToAddNewLanguage.md). Also, please create a Pull Request so others can use it! ## Docs @@ -37,7 +37,18 @@ First, make sure you've read the section [Pull Requests](#pull-requests). If, at any point in time, you have a question, please feel free to ask in the same issue thread or in our [Discord](https://discord.gg/FJUSXUSYec). -Developers should review our [Developer Guide](DeveloperGuide.md) +## Developer Documentation + +For technical guides, setup instructions, and development resources, please see our [Developer Documentation](devGuide/) which includes: + +- [Developer Guide](devGuide/DeveloperGuide.md) - Main setup and architecture guide +- [Exception Handling Guide](devGuide/EXCEPTION_HANDLING_GUIDE.md) - Error handling patterns and i18n +- [Translation Guide](devGuide/HowToAddNewLanguage.md) - Adding new languages +- And more in the [devGuide folder](devGuide/) + +For configuration and usage guides, see: +- [Database Guide](DATABASE.md) - Database setup and configuration +- [OCR Guide](HowToUseOCR.md) - OCR setup and configuration ## License diff --git a/Dockerfile.dev b/Dockerfile.dev deleted file mode 100644 index 15de277b9..000000000 --- a/Dockerfile.dev +++ /dev/null @@ -1,60 +0,0 @@ -# dockerfile.dev - -# Basisimage: Gradle mit JDK 17 (Debian-basiert) -FROM gradle:8.14-jdk17 - -# Als Root-Benutzer arbeiten, um benötigte Pakete zu installieren -USER root - -# Set GRADLE_HOME und füge Gradle zum PATH hinzu -ENV GRADLE_HOME=/opt/gradle -ENV PATH="$GRADLE_HOME/bin:$PATH" - -# Update und Installation zusätzlicher Pakete (Debian/Ubuntu-basiert) -RUN apt-get update && apt-get install -y \ - sudo \ - libreoffice \ - poppler-utils \ - qpdf \ -# settings.yml | tessdataDir: /usr/share/tesseract-ocr/5/tessdata - tesseract-ocr \ - tesseract-ocr-eng \ - fonts-terminus fonts-dejavu fonts-font-awesome fonts-noto fonts-noto-core fonts-noto-cjk fonts-noto-extra fonts-liberation fonts-linuxlibertine \ - python3-uno \ - python3-venv \ -# ss -tln - iproute2 \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -# Setze die Environment Variable für setuptools -ENV SETUPTOOLS_USE_DISTUTILS=local \ - STIRLING_TEMPFILES_DIRECTORY=/tmp/stirling-pdf \ - TMPDIR=/tmp/stirling-pdf \ - TEMP=/tmp/stirling-pdf \ - TMP=/tmp/stirling-pdf - -# Installation der benötigten Python-Pakete -RUN python3 -m venv --system-site-packages /opt/venv \ - && . /opt/venv/bin/activate \ - && pip install --upgrade pip setuptools \ - && pip install --no-cache-dir WeasyPrint pdf2image pillow unoserver opencv-python-headless pre-commit - -# Füge den venv-Pfad zur globalen PATH-Variable hinzu, damit die Tools verfügbar sind -ENV PATH="/opt/venv/bin:$PATH" - -COPY . /workspace - -RUN mkdir -p /tmp/stirling-pdf \ - && adduser --disabled-password --gecos '' devuser \ - && chown -R devuser:devuser /home/devuser /workspace /tmp/stirling-pdf -RUN echo "devuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/devuser \ - && chmod 0440 /etc/sudoers.d/devuser - -# Setze das Arbeitsverzeichnis (wird später per Bind-Mount überschrieben) -WORKDIR /workspace - -RUN chmod +x /workspace/.devcontainer/git-init.sh -RUN sudo chmod +x /workspace/.devcontainer/init-setup.sh - -# Wechsel zum Nicht‑Root Benutzer -USER devuser diff --git a/LICENSE b/LICENSE index 877663171..cc732d7ea 100644 --- a/LICENSE +++ b/LICENSE @@ -4,8 +4,8 @@ Copyright (c) 2025 Stirling PDF Inc. Portions of this software are licensed as follows: -* All content that resides under the "proprietary/" directory of this repository, -if that directory exists, is licensed under the license defined in "proprietary/LICENSE". +* All content that resides under the "app/proprietary/" directory of this repository, +if that directory exists, is licensed under the license defined in "app/proprietary/LICENSE". * Content outside of the above mentioned directories or restrictions above is available under the MIT License as defined below. diff --git a/README.md b/README.md index 1c67d5d9e..02712a1ad 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ All documentation available at [https://docs.stirlingpdf.com/](https://docs.stir - API for integration with external scripts - Optional Login and Authentication support (see [here](https://docs.stirlingpdf.com/Advanced%20Configuration/System%20and%20Security) for documentation) - Database Backup and Import (see [here](https://docs.stirlingpdf.com/Advanced%20Configuration/DATABASE) for documentation) -- Enterprise features like SSO see [here](https://docs.stirlingpdf.com/Enterprise%20Edition) +- Enterprise features like SSO (see [here](https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration) for documentation) ## PDF Features @@ -116,47 +116,47 @@ Stirling-PDF currently supports 40 languages! | Language | Progress | | -------------------------------------------- | -------------------------------------- | -| Arabic (العربية) (ar_AR) | ![65%](https://geps.dev/progress/65) | -| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![65%](https://geps.dev/progress/65) | -| Basque (Euskara) (eu_ES) | ![38%](https://geps.dev/progress/38) | -| Bulgarian (Български) (bg_BG) | ![72%](https://geps.dev/progress/72) | -| Catalan (Català) (ca_CA) | ![71%](https://geps.dev/progress/71) | -| Croatian (Hrvatski) (hr_HR) | ![64%](https://geps.dev/progress/64) | -| Czech (Česky) (cs_CZ) | ![74%](https://geps.dev/progress/74) | -| Danish (Dansk) (da_DK) | ![65%](https://geps.dev/progress/65) | -| Dutch (Nederlands) (nl_NL) | ![63%](https://geps.dev/progress/63) | +| Arabic (العربية) (ar_AR) | ![63%](https://geps.dev/progress/63) | +| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![63%](https://geps.dev/progress/63) | +| Basque (Euskara) (eu_ES) | ![37%](https://geps.dev/progress/37) | +| Bulgarian (Български) (bg_BG) | ![70%](https://geps.dev/progress/70) | +| Catalan (Català) (ca_CA) | ![69%](https://geps.dev/progress/69) | +| Croatian (Hrvatski) (hr_HR) | ![62%](https://geps.dev/progress/62) | +| Czech (Česky) (cs_CZ) | ![71%](https://geps.dev/progress/71) | +| Danish (Dansk) (da_DK) | ![63%](https://geps.dev/progress/63) | +| Dutch (Nederlands) (nl_NL) | ![61%](https://geps.dev/progress/61) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) | -| French (Français) (fr_FR) | ![73%](https://geps.dev/progress/73) | -| German (Deutsch) (de_DE) | ![92%](https://geps.dev/progress/92) | -| Greek (Ελληνικά) (el_GR) | ![71%](https://geps.dev/progress/71) | -| Hindi (हिंदी) (hi_IN) | ![71%](https://geps.dev/progress/71) | +| French (Français) (fr_FR) | ![91%](https://geps.dev/progress/91) | +| German (Deutsch) (de_DE) | ![100%](https://geps.dev/progress/100) | +| Greek (Ελληνικά) (el_GR) | ![69%](https://geps.dev/progress/69) | +| Hindi (हिंदी) (hi_IN) | ![68%](https://geps.dev/progress/68) | | Hungarian (Magyar) (hu_HU) | ![99%](https://geps.dev/progress/99) | -| Indonesian (Bahasa Indonesia) (id_ID) | ![65%](https://geps.dev/progress/65) | -| Irish (Gaeilge) (ga_IE) | ![72%](https://geps.dev/progress/72) | +| Indonesian (Bahasa Indonesia) (id_ID) | ![63%](https://geps.dev/progress/63) | +| Irish (Gaeilge) (ga_IE) | ![70%](https://geps.dev/progress/70) | | Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | -| Japanese (日本語) (ja_JP) | ![72%](https://geps.dev/progress/72) | -| Korean (한국어) (ko_KR) | ![71%](https://geps.dev/progress/71) | -| Norwegian (Norsk) (no_NB) | ![70%](https://geps.dev/progress/70) | -| Persian (فارسی) (fa_IR) | ![68%](https://geps.dev/progress/68) | -| Polish (Polski) (pl_PL) | ![76%](https://geps.dev/progress/76) | -| Portuguese (Português) (pt_PT) | ![72%](https://geps.dev/progress/72) | -| Portuguese Brazilian (Português) (pt_BR) | ![80%](https://geps.dev/progress/80) | -| Romanian (Română) (ro_RO) | ![61%](https://geps.dev/progress/61) | -| Russian (Русский) (ru_RU) | ![72%](https://geps.dev/progress/72) | -| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![46%](https://geps.dev/progress/46) | -| Simplified Chinese (简体中文) (zh_CN) | ![93%](https://geps.dev/progress/93) | -| Slovakian (Slovensky) (sk_SK) | ![54%](https://geps.dev/progress/54) | -| Slovenian (Slovenščina) (sl_SI) | ![75%](https://geps.dev/progress/75) | -| Spanish (Español) (es_ES) | ![78%](https://geps.dev/progress/78) | -| Swedish (Svenska) (sv_SE) | ![69%](https://geps.dev/progress/69) | -| Thai (ไทย) (th_TH) | ![62%](https://geps.dev/progress/62) | -| Tibetan (བོད་ཡིག་) (bo_CN) | ![68%](https://geps.dev/progress/68) | -| Traditional Chinese (繁體中文) (zh_TW) | ![80%](https://geps.dev/progress/80) | -| Turkish (Türkçe) (tr_TR) | ![85%](https://geps.dev/progress/85) | -| Ukrainian (Українська) (uk_UA) | ![75%](https://geps.dev/progress/75) | -| Vietnamese (Tiếng Việt) (vi_VN) | ![60%](https://geps.dev/progress/60) | -| Malayalam (മലയാളം) (ml_IN) | ![77%](https://geps.dev/progress/77) | +| Japanese (日本語) (ja_JP) | ![95%](https://geps.dev/progress/95) | +| Korean (한국어) (ko_KR) | ![69%](https://geps.dev/progress/69) | +| Norwegian (Norsk) (no_NB) | ![67%](https://geps.dev/progress/67) | +| Persian (فارسی) (fa_IR) | ![66%](https://geps.dev/progress/66) | +| Polish (Polski) (pl_PL) | ![73%](https://geps.dev/progress/73) | +| Portuguese (Português) (pt_PT) | ![70%](https://geps.dev/progress/70) | +| Portuguese Brazilian (Português) (pt_BR) | ![77%](https://geps.dev/progress/77) | +| Romanian (Română) (ro_RO) | ![59%](https://geps.dev/progress/59) | +| Russian (Русский) (ru_RU) | ![70%](https://geps.dev/progress/70) | +| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![97%](https://geps.dev/progress/97) | +| Simplified Chinese (简体中文) (zh_CN) | ![95%](https://geps.dev/progress/95) | +| Slovakian (Slovensky) (sk_SK) | ![53%](https://geps.dev/progress/53) | +| Slovenian (Slovenščina) (sl_SI) | ![73%](https://geps.dev/progress/73) | +| Spanish (Español) (es_ES) | ![75%](https://geps.dev/progress/75) | +| Swedish (Svenska) (sv_SE) | ![67%](https://geps.dev/progress/67) | +| Thai (ไทย) (th_TH) | ![60%](https://geps.dev/progress/60) | +| Tibetan (བོད་ཡིག་) (bo_CN) | ![66%](https://geps.dev/progress/66) | +| Traditional Chinese (繁體中文) (zh_TW) | ![77%](https://geps.dev/progress/77) | +| Turkish (Türkçe) (tr_TR) | ![82%](https://geps.dev/progress/82) | +| Ukrainian (Українська) (uk_UA) | ![72%](https://geps.dev/progress/72) | +| Vietnamese (Tiếng Việt) (vi_VN) | ![58%](https://geps.dev/progress/58) | +| Malayalam (മലയാളം) (ml_IN) | ![75%](https://geps.dev/progress/75) | ## Stirling PDF Enterprise @@ -168,7 +168,7 @@ Check out our [Enterprise docs](https://docs.stirlingpdf.com/Pro) Join our community: - [Contribution Guidelines](CONTRIBUTING.md) -- [Translation Guide (How to add custom languages)](HowToAddNewLanguage.md) +- [Translation Guide (How to add custom languages)](devGuide/HowToAddNewLanguage.md) +- [Developer Guide](devGuide/DeveloperGuide.md) - [Issue Tracker](https://github.com/Stirling-Tools/Stirling-PDF/issues) - [Discord Community](https://discord.gg/HYmhKj45pU) -- [Developer Guide](DeveloperGuide.md) diff --git a/allowed-licenses.json b/app/allowed-licenses.json similarity index 100% rename from allowed-licenses.json rename to app/allowed-licenses.json diff --git a/common/.gitignore b/app/common/.gitignore similarity index 99% rename from common/.gitignore rename to app/common/.gitignore index 17f0d4976..bd6361c88 100644 --- a/common/.gitignore +++ b/app/common/.gitignore @@ -124,7 +124,7 @@ SwaggerDoc.json *.rar *.db /build -/common/build/ +/app/common/build/ # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/common/build.gradle b/app/common/build.gradle similarity index 96% rename from common/build.gradle rename to app/common/build.gradle index 6dfd222bf..2ab8c3b97 100644 --- a/common/build.gradle +++ b/app/common/build.gradle @@ -21,7 +21,7 @@ dependencies { api 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' api 'com.fathzer:javaluator:3.0.6' api 'com.posthog.java:posthog:1.2.0' - api 'org.apache.commons:commons-lang3:3.17.0' + api 'org.apache.commons:commons-lang3:3.18.0' api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' api "org.apache.pdfbox:pdfbox:$pdfboxVersion" diff --git a/common/src/main/java/org/apache/pdfbox/examples/util/DeletingRandomAccessFile.java b/app/common/src/main/java/org/apache/pdfbox/examples/util/DeletingRandomAccessFile.java similarity index 100% rename from common/src/main/java/org/apache/pdfbox/examples/util/DeletingRandomAccessFile.java rename to app/common/src/main/java/org/apache/pdfbox/examples/util/DeletingRandomAccessFile.java diff --git a/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java b/app/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java similarity index 100% rename from common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java rename to app/common/src/main/java/stirling/software/common/annotations/AutoJobPostMapping.java diff --git a/common/src/main/java/stirling/software/common/aop/AutoJobAspect.java b/app/common/src/main/java/stirling/software/common/aop/AutoJobAspect.java similarity index 75% rename from common/src/main/java/stirling/software/common/aop/AutoJobAspect.java rename to app/common/src/main/java/stirling/software/common/aop/AutoJobAspect.java index 51c1882b6..2ee10ebcd 100644 --- a/common/src/main/java/stirling/software/common/aop/AutoJobAspect.java +++ b/app/common/src/main/java/stirling/software/common/aop/AutoJobAspect.java @@ -43,6 +43,11 @@ public class AutoJobAspect { // This aspect will run before any audit aspects due to @Order(0) // Extract parameters from the request and annotation boolean async = Boolean.parseBoolean(request.getParameter("async")); + log.debug( + "AutoJobAspect: Processing {} {} with async={}", + request.getMethod(), + request.getRequestURI(), + async); long timeout = autoJobPostMapping.timeout(); int retryCount = autoJobPostMapping.retryCount(); boolean trackProgress = autoJobPostMapping.trackProgress(); @@ -54,19 +59,8 @@ public class AutoJobAspect { retryCount, trackProgress); - // Copy and process arguments - // In a test environment, we might need to update the original objects for verification - boolean isTestEnvironment = false; - try { - isTestEnvironment = Class.forName("org.junit.jupiter.api.Test") != null; - } catch (ClassNotFoundException e) { - // Not in a test environment - } - - Object[] args = - isTestEnvironment - ? processArgsInPlace(joinPoint.getArgs(), async) - : copyAndProcessArgs(joinPoint.getArgs(), async); + // Process arguments in-place to avoid type mismatch issues + Object[] args = processArgsInPlace(joinPoint.getArgs(), async); // Extract queueable and resourceWeight parameters and validate boolean queueable = autoJobPostMapping.queueable(); @@ -230,78 +224,8 @@ public class AutoJobAspect { } /** - * Creates deep copies of arguments when needed to avoid mutating the original objects - * Particularly important for PDFFile objects that might be reused by Spring - * - * @param originalArgs The original arguments - * @param async Whether this is an async operation - * @return A new array with safely processed arguments - */ - private Object[] copyAndProcessArgs(Object[] originalArgs, boolean async) { - if (originalArgs == null || originalArgs.length == 0) { - return originalArgs; - } - - Object[] processedArgs = new Object[originalArgs.length]; - - // Copy all arguments - for (int i = 0; i < originalArgs.length; i++) { - Object arg = originalArgs[i]; - - if (arg instanceof PDFFile pdfFile) { - // Create a copy of PDFFile to avoid mutating the original - // Using direct property access instead of reflection for better performance - PDFFile pdfFileCopy = new PDFFile(); - pdfFileCopy.setFileId(pdfFile.getFileId()); - pdfFileCopy.setFileInput(pdfFile.getFileInput()); - - // Case 1: fileId is provided but no fileInput - if (pdfFileCopy.getFileInput() == null && pdfFileCopy.getFileId() != null) { - try { - log.debug("Using fileId {} to get file content", pdfFileCopy.getFileId()); - MultipartFile file = fileStorage.retrieveFile(pdfFileCopy.getFileId()); - pdfFileCopy.setFileInput(file); - } catch (Exception e) { - throw new RuntimeException( - "Failed to resolve file by ID: " + pdfFileCopy.getFileId(), e); - } - } - // Case 2: For async requests, we need to make a copy of the MultipartFile - else if (async && pdfFileCopy.getFileInput() != null) { - try { - log.debug("Making persistent copy of uploaded file for async processing"); - MultipartFile originalFile = pdfFileCopy.getFileInput(); - String fileId = fileStorage.storeFile(originalFile); - - // Store the fileId for later reference - pdfFileCopy.setFileId(fileId); - - // Replace the original MultipartFile with our persistent copy - MultipartFile persistentFile = fileStorage.retrieveFile(fileId); - pdfFileCopy.setFileInput(persistentFile); - - log.debug("Created persistent file copy with fileId: {}", fileId); - } catch (IOException e) { - throw new RuntimeException( - "Failed to create persistent copy of uploaded file", e); - } - } - - processedArgs[i] = pdfFileCopy; - } else { - // For non-PDFFile objects, just pass the original reference - // If other classes need copy-on-write, add them here - processedArgs[i] = arg; - } - } - - return processedArgs; - } - - /** - * Processes arguments in-place for testing purposes This is similar to our original - * implementation before introducing copy-on-write It's only used in test environments to - * maintain test compatibility + * Processes arguments in-place to handle file resolution and async file persistence. This + * approach avoids type mismatch issues by modifying the original objects directly. * * @param originalArgs The original arguments * @param async Whether this is an async operation diff --git a/common/src/main/java/stirling/software/common/config/TempFileConfiguration.java b/app/common/src/main/java/stirling/software/common/config/TempFileConfiguration.java similarity index 100% rename from common/src/main/java/stirling/software/common/config/TempFileConfiguration.java rename to app/common/src/main/java/stirling/software/common/config/TempFileConfiguration.java diff --git a/common/src/main/java/stirling/software/common/config/TempFileShutdownHook.java b/app/common/src/main/java/stirling/software/common/config/TempFileShutdownHook.java similarity index 97% rename from common/src/main/java/stirling/software/common/config/TempFileShutdownHook.java rename to app/common/src/main/java/stirling/software/common/config/TempFileShutdownHook.java index 6fd3bdeff..00719deaa 100644 --- a/common/src/main/java/stirling/software/common/config/TempFileShutdownHook.java +++ b/app/common/src/main/java/stirling/software/common/config/TempFileShutdownHook.java @@ -6,7 +6,6 @@ import java.nio.file.Path; import java.util.Set; import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; @@ -24,7 +23,6 @@ public class TempFileShutdownHook implements DisposableBean { private final TempFileRegistry registry; - @Autowired public TempFileShutdownHook(TempFileRegistry registry) { this.registry = registry; diff --git a/common/src/main/java/stirling/software/common/configuration/AppConfig.java b/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java similarity index 92% rename from common/src/main/java/stirling/software/common/configuration/AppConfig.java rename to app/common/src/main/java/stirling/software/common/configuration/AppConfig.java index 02614584b..f611f42ca 100644 --- a/common/src/main/java/stirling/software/common/configuration/AppConfig.java +++ b/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java @@ -10,7 +10,6 @@ import java.util.Properties; import java.util.function.Predicate; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,6 +20,7 @@ import org.springframework.core.env.Environment; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.util.ClassUtils; import org.thymeleaf.spring6.SpringTemplateEngine; import lombok.Getter; @@ -148,23 +148,10 @@ public class AppConfig { } @Bean(name = "activeSecurity") - public boolean activeSecurity() { - String disableAdditionalFeatures = env.getProperty("DISABLE_ADDITIONAL_FEATURES"); - - if (disableAdditionalFeatures != null) { - // DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false - // DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true - return !Boolean.parseBoolean(disableAdditionalFeatures); - } - - return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true); - } - - @Bean(name = "missingActiveSecurity") - @ConditionalOnMissingClass( - "stirling.software.proprietary.security.configuration.SecurityConfiguration") public boolean missingActiveSecurity() { - return true; + return ClassUtils.isPresent( + "stirling.software.proprietary.security.configuration.SecurityConfiguration", + this.getClass().getClassLoader()); } @Bean(name = "directoryFilter") diff --git a/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java b/app/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java rename to app/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java diff --git a/common/src/main/java/stirling/software/common/configuration/FileFallbackTemplateResolver.java b/app/common/src/main/java/stirling/software/common/configuration/FileFallbackTemplateResolver.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/FileFallbackTemplateResolver.java rename to app/common/src/main/java/stirling/software/common/configuration/FileFallbackTemplateResolver.java diff --git a/common/src/main/java/stirling/software/common/configuration/InstallationPathConfig.java b/app/common/src/main/java/stirling/software/common/configuration/InstallationPathConfig.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/InstallationPathConfig.java rename to app/common/src/main/java/stirling/software/common/configuration/InstallationPathConfig.java diff --git a/common/src/main/java/stirling/software/common/configuration/PostHogConfig.java b/app/common/src/main/java/stirling/software/common/configuration/PostHogConfig.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/PostHogConfig.java rename to app/common/src/main/java/stirling/software/common/configuration/PostHogConfig.java diff --git a/common/src/main/java/stirling/software/common/configuration/PostHogLoggerImpl.java b/app/common/src/main/java/stirling/software/common/configuration/PostHogLoggerImpl.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/PostHogLoggerImpl.java rename to app/common/src/main/java/stirling/software/common/configuration/PostHogLoggerImpl.java diff --git a/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java b/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java rename to app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java diff --git a/common/src/main/java/stirling/software/common/configuration/YamlPropertySourceFactory.java b/app/common/src/main/java/stirling/software/common/configuration/YamlPropertySourceFactory.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/YamlPropertySourceFactory.java rename to app/common/src/main/java/stirling/software/common/configuration/YamlPropertySourceFactory.java diff --git a/common/src/main/java/stirling/software/common/configuration/interfaces/ShowAdminInterface.java b/app/common/src/main/java/stirling/software/common/configuration/interfaces/ShowAdminInterface.java similarity index 100% rename from common/src/main/java/stirling/software/common/configuration/interfaces/ShowAdminInterface.java rename to app/common/src/main/java/stirling/software/common/configuration/interfaces/ShowAdminInterface.java diff --git a/common/src/main/java/stirling/software/common/model/ApplicationProperties.java b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java similarity index 96% rename from common/src/main/java/stirling/software/common/model/ApplicationProperties.java rename to app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java index 0017fa34a..e4edf2baa 100644 --- a/common/src/main/java/stirling/software/common/model/ApplicationProperties.java +++ b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java @@ -545,6 +545,8 @@ public class ApplicationProperties { private int calibreSessionLimit; private int qpdfSessionLimit; private int tesseractSessionLimit; + private int ghostscriptSessionLimit; + private int ocrMyPdfSessionLimit; public int getQpdfSessionLimit() { return qpdfSessionLimit > 0 ? qpdfSessionLimit : 2; @@ -577,6 +579,14 @@ public class ApplicationProperties { public int getCalibreSessionLimit() { return calibreSessionLimit > 0 ? calibreSessionLimit : 1; } + + public int getGhostscriptSessionLimit() { + return ghostscriptSessionLimit > 0 ? ghostscriptSessionLimit : 8; + } + + public int getOcrMyPdfSessionLimit() { + return ocrMyPdfSessionLimit > 0 ? ocrMyPdfSessionLimit : 2; + } } @Data @@ -589,6 +599,8 @@ public class ApplicationProperties { private long calibreTimeoutMinutes; private long tesseractTimeoutMinutes; private long qpdfTimeoutMinutes; + private long ghostscriptTimeoutMinutes; + private long ocrMyPdfTimeoutMinutes; public long getTesseractTimeoutMinutes() { return tesseractTimeoutMinutes > 0 ? tesseractTimeoutMinutes : 30; @@ -621,6 +633,14 @@ public class ApplicationProperties { public long getCalibreTimeoutMinutes() { return calibreTimeoutMinutes > 0 ? calibreTimeoutMinutes : 30; } + + public long getGhostscriptTimeoutMinutes() { + return ghostscriptTimeoutMinutes > 0 ? ghostscriptTimeoutMinutes : 30; + } + + public long getOcrMyPdfTimeoutMinutes() { + return ocrMyPdfTimeoutMinutes > 0 ? ocrMyPdfTimeoutMinutes : 30; + } } } } diff --git a/common/src/main/java/stirling/software/common/model/FileInfo.java b/app/common/src/main/java/stirling/software/common/model/FileInfo.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/FileInfo.java rename to app/common/src/main/java/stirling/software/common/model/FileInfo.java diff --git a/common/src/main/java/stirling/software/common/model/InputStreamTemplateResource.java b/app/common/src/main/java/stirling/software/common/model/InputStreamTemplateResource.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/InputStreamTemplateResource.java rename to app/common/src/main/java/stirling/software/common/model/InputStreamTemplateResource.java diff --git a/common/src/main/java/stirling/software/common/model/PdfMetadata.java b/app/common/src/main/java/stirling/software/common/model/PdfMetadata.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/PdfMetadata.java rename to app/common/src/main/java/stirling/software/common/model/PdfMetadata.java diff --git a/common/src/main/java/stirling/software/common/model/api/GeneralFile.java b/app/common/src/main/java/stirling/software/common/model/api/GeneralFile.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/GeneralFile.java rename to app/common/src/main/java/stirling/software/common/model/api/GeneralFile.java diff --git a/common/src/main/java/stirling/software/common/model/api/PDFFile.java b/app/common/src/main/java/stirling/software/common/model/api/PDFFile.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/PDFFile.java rename to app/common/src/main/java/stirling/software/common/model/api/PDFFile.java diff --git a/common/src/main/java/stirling/software/common/model/api/converters/EmlToPdfRequest.java b/app/common/src/main/java/stirling/software/common/model/api/converters/EmlToPdfRequest.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/converters/EmlToPdfRequest.java rename to app/common/src/main/java/stirling/software/common/model/api/converters/EmlToPdfRequest.java diff --git a/common/src/main/java/stirling/software/common/model/api/converters/HTMLToPdfRequest.java b/app/common/src/main/java/stirling/software/common/model/api/converters/HTMLToPdfRequest.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/converters/HTMLToPdfRequest.java rename to app/common/src/main/java/stirling/software/common/model/api/converters/HTMLToPdfRequest.java diff --git a/common/src/main/java/stirling/software/common/model/api/misc/HighContrastColorCombination.java b/app/common/src/main/java/stirling/software/common/model/api/misc/HighContrastColorCombination.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/misc/HighContrastColorCombination.java rename to app/common/src/main/java/stirling/software/common/model/api/misc/HighContrastColorCombination.java diff --git a/common/src/main/java/stirling/software/common/model/api/misc/ReplaceAndInvert.java b/app/common/src/main/java/stirling/software/common/model/api/misc/ReplaceAndInvert.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/misc/ReplaceAndInvert.java rename to app/common/src/main/java/stirling/software/common/model/api/misc/ReplaceAndInvert.java diff --git a/common/src/main/java/stirling/software/common/model/api/security/RedactionArea.java b/app/common/src/main/java/stirling/software/common/model/api/security/RedactionArea.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/api/security/RedactionArea.java rename to app/common/src/main/java/stirling/software/common/model/api/security/RedactionArea.java diff --git a/common/src/main/java/stirling/software/common/model/enumeration/Role.java b/app/common/src/main/java/stirling/software/common/model/enumeration/Role.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/enumeration/Role.java rename to app/common/src/main/java/stirling/software/common/model/enumeration/Role.java diff --git a/common/src/main/java/stirling/software/common/model/enumeration/UsernameAttribute.java b/app/common/src/main/java/stirling/software/common/model/enumeration/UsernameAttribute.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/enumeration/UsernameAttribute.java rename to app/common/src/main/java/stirling/software/common/model/enumeration/UsernameAttribute.java diff --git a/common/src/main/java/stirling/software/common/model/exception/UnsupportedClaimException.java b/app/common/src/main/java/stirling/software/common/model/exception/UnsupportedClaimException.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/exception/UnsupportedClaimException.java rename to app/common/src/main/java/stirling/software/common/model/exception/UnsupportedClaimException.java diff --git a/common/src/main/java/stirling/software/common/model/exception/UnsupportedProviderException.java b/app/common/src/main/java/stirling/software/common/model/exception/UnsupportedProviderException.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/exception/UnsupportedProviderException.java rename to app/common/src/main/java/stirling/software/common/model/exception/UnsupportedProviderException.java diff --git a/common/src/main/java/stirling/software/common/model/job/JobProgress.java b/app/common/src/main/java/stirling/software/common/model/job/JobProgress.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/job/JobProgress.java rename to app/common/src/main/java/stirling/software/common/model/job/JobProgress.java diff --git a/common/src/main/java/stirling/software/common/model/job/JobResponse.java b/app/common/src/main/java/stirling/software/common/model/job/JobResponse.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/job/JobResponse.java rename to app/common/src/main/java/stirling/software/common/model/job/JobResponse.java diff --git a/common/src/main/java/stirling/software/common/model/job/JobResult.java b/app/common/src/main/java/stirling/software/common/model/job/JobResult.java similarity index 58% rename from common/src/main/java/stirling/software/common/model/job/JobResult.java rename to app/common/src/main/java/stirling/software/common/model/job/JobResult.java index a621f2db2..52c0826e2 100644 --- a/common/src/main/java/stirling/software/common/model/job/JobResult.java +++ b/app/common/src/main/java/stirling/software/common/model/job/JobResult.java @@ -1,10 +1,13 @@ package stirling.software.common.model.job; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import com.fasterxml.jackson.annotation.JsonIgnore; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -26,14 +29,8 @@ public class JobResult { /** Error message if the job failed */ private String error; - /** The file ID of the result file, if applicable */ - private String fileId; - - /** Original file name, if applicable */ - private String originalFileName; - - /** MIME type of the result, if applicable */ - private String contentType; + /** List of result files for jobs that produce files */ + @JsonIgnore private List resultFiles; /** Time when the job was created */ private LocalDateTime createdAt; @@ -64,21 +61,6 @@ public class JobResult { .build(); } - /** - * Mark this job as complete with a file result - * - * @param fileId The file ID of the result - * @param originalFileName The original file name - * @param contentType The content type of the file - */ - public void completeWithFile(String fileId, String originalFileName, String contentType) { - this.complete = true; - this.fileId = fileId; - this.originalFileName = originalFileName; - this.contentType = contentType; - this.completedAt = LocalDateTime.now(); - } - /** * Mark this job as complete with a general result * @@ -101,6 +83,67 @@ public class JobResult { this.completedAt = LocalDateTime.now(); } + /** + * Mark this job as complete with multiple file results + * + * @param resultFiles The list of result files + */ + public void completeWithFiles(List resultFiles) { + this.complete = true; + this.resultFiles = new ArrayList<>(resultFiles); + this.completedAt = LocalDateTime.now(); + } + + /** + * Mark this job as complete with a single file result (convenience method) + * + * @param fileId The file ID of the result + * @param fileName The file name + * @param contentType The content type of the file + * @param fileSize The size of the file in bytes + */ + public void completeWithSingleFile( + String fileId, String fileName, String contentType, long fileSize) { + ResultFile resultFile = + ResultFile.builder() + .fileId(fileId) + .fileName(fileName) + .contentType(contentType) + .fileSize(fileSize) + .build(); + completeWithFiles(List.of(resultFile)); + } + + /** + * Check if this job has file results + * + * @return true if this job has file results, false otherwise + */ + public boolean hasFiles() { + return resultFiles != null && !resultFiles.isEmpty(); + } + + /** + * Check if this job has multiple file results + * + * @return true if this job has multiple file results, false otherwise + */ + public boolean hasMultipleFiles() { + return resultFiles != null && resultFiles.size() > 1; + } + + /** + * Get all result files + * + * @return List of result files + */ + public List getAllResultFiles() { + if (resultFiles != null && !resultFiles.isEmpty()) { + return Collections.unmodifiableList(resultFiles); + } + return Collections.emptyList(); + } + /** * Add a note to this job * diff --git a/common/src/main/java/stirling/software/common/model/job/JobStats.java b/app/common/src/main/java/stirling/software/common/model/job/JobStats.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/job/JobStats.java rename to app/common/src/main/java/stirling/software/common/model/job/JobStats.java diff --git a/app/common/src/main/java/stirling/software/common/model/job/ResultFile.java b/app/common/src/main/java/stirling/software/common/model/job/ResultFile.java new file mode 100644 index 000000000..da51b1d6c --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/model/job/ResultFile.java @@ -0,0 +1,26 @@ +package stirling.software.common.model.job; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** Represents a single file result from a job execution */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ResultFile { + + /** The file ID for accessing the file */ + private String fileId; + + /** The original file name */ + private String fileName; + + /** MIME type of the file */ + private String contentType; + + /** Size of the file in bytes */ + private long fileSize; +} diff --git a/common/src/main/java/stirling/software/common/model/oauth2/GitHubProvider.java b/app/common/src/main/java/stirling/software/common/model/oauth2/GitHubProvider.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/oauth2/GitHubProvider.java rename to app/common/src/main/java/stirling/software/common/model/oauth2/GitHubProvider.java diff --git a/common/src/main/java/stirling/software/common/model/oauth2/GoogleProvider.java b/app/common/src/main/java/stirling/software/common/model/oauth2/GoogleProvider.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/oauth2/GoogleProvider.java rename to app/common/src/main/java/stirling/software/common/model/oauth2/GoogleProvider.java diff --git a/common/src/main/java/stirling/software/common/model/oauth2/KeycloakProvider.java b/app/common/src/main/java/stirling/software/common/model/oauth2/KeycloakProvider.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/oauth2/KeycloakProvider.java rename to app/common/src/main/java/stirling/software/common/model/oauth2/KeycloakProvider.java diff --git a/common/src/main/java/stirling/software/common/model/oauth2/Provider.java b/app/common/src/main/java/stirling/software/common/model/oauth2/Provider.java similarity index 100% rename from common/src/main/java/stirling/software/common/model/oauth2/Provider.java rename to app/common/src/main/java/stirling/software/common/model/oauth2/Provider.java diff --git a/common/src/main/java/stirling/software/common/service/CustomPDFDocumentFactory.java b/app/common/src/main/java/stirling/software/common/service/CustomPDFDocumentFactory.java similarity index 90% rename from common/src/main/java/stirling/software/common/service/CustomPDFDocumentFactory.java rename to app/common/src/main/java/stirling/software/common/service/CustomPDFDocumentFactory.java index 51f52c34d..d106a2729 100644 --- a/common/src/main/java/stirling/software/common/service/CustomPDFDocumentFactory.java +++ b/app/common/src/main/java/stirling/software/common/service/CustomPDFDocumentFactory.java @@ -24,6 +24,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.common.model.api.PDFFile; import stirling.software.common.util.ApplicationContextProvider; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.TempFileRegistry; @@ -82,7 +83,7 @@ public class CustomPDFDocumentFactory { */ public PDDocument load(File file, boolean readOnly) throws IOException { if (file == null) { - throw new IllegalArgumentException("File cannot be null"); + throw ExceptionUtils.createNullArgumentException("File"); } long fileSize = file.length(); @@ -109,7 +110,7 @@ public class CustomPDFDocumentFactory { */ public PDDocument load(Path path, boolean readOnly) throws IOException { if (path == null) { - throw new IllegalArgumentException("File cannot be null"); + throw ExceptionUtils.createNullArgumentException("File"); } long fileSize = Files.size(path); @@ -130,7 +131,7 @@ public class CustomPDFDocumentFactory { /** Load a PDF from byte array with automatic optimization and read-only option. */ public PDDocument load(byte[] input, boolean readOnly) throws IOException { if (input == null) { - throw new IllegalArgumentException("Input bytes cannot be null"); + throw ExceptionUtils.createNullArgumentException("Input bytes"); } long dataSize = input.length; @@ -151,7 +152,7 @@ public class CustomPDFDocumentFactory { /** Load a PDF from InputStream with automatic optimization and read-only option. */ public PDDocument load(InputStream input, boolean readOnly) throws IOException { if (input == null) { - throw new IllegalArgumentException("InputStream cannot be null"); + throw ExceptionUtils.createNullArgumentException("InputStream"); } // Since we don't know the size upfront, buffer to a temp file @@ -174,7 +175,7 @@ public class CustomPDFDocumentFactory { public PDDocument load(InputStream input, String password, boolean readOnly) throws IOException { if (input == null) { - throw new IllegalArgumentException("InputStream cannot be null"); + throw ExceptionUtils.createNullArgumentException("InputStream"); } // Since we don't know the size upfront, buffer to a temp file @@ -292,9 +293,32 @@ public class CustomPDFDocumentFactory { } else { throw new IllegalArgumentException("Unsupported source type: " + source.getClass()); } + + configureResourceCacheIfNeeded(document, contentSize); + return document; } + /** + * Configure resource cache based on content size and memory constraints. Disables resource + * cache for large files or when memory is low to prevent OOM errors. + */ + private void configureResourceCacheIfNeeded(PDDocument document, long contentSize) { + if (contentSize > LARGE_FILE_THRESHOLD) { + document.setResourceCache(null); + } else { + // Check current memory status for smaller files + long maxMemory = Runtime.getRuntime().maxMemory(); + long usedMemory = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + double freeMemoryPercent = (double) (maxMemory - usedMemory) / maxMemory * 100; + + if (freeMemoryPercent < MIN_FREE_MEMORY_PERCENTAGE) { + document.setResourceCache(null); + } + } + } + /** Load a PDF with password protection using adaptive loading strategies */ private PDDocument loadAdaptivelyWithPassword(Object source, long contentSize, String password) throws IOException { @@ -313,6 +337,9 @@ public class CustomPDFDocumentFactory { } else { throw new IllegalArgumentException("Unsupported source type: " + source.getClass()); } + + configureResourceCacheIfNeeded(document, contentSize); + return document; } @@ -354,7 +381,12 @@ public class CustomPDFDocumentFactory { private PDDocument loadFromFile(File file, long size, StreamCacheCreateFunction cache) throws IOException { - return Loader.loadPDF(new DeletingRandomAccessFile(file), "", null, null, cache); + try { + return Loader.loadPDF(new DeletingRandomAccessFile(file), "", null, null, cache); + } catch (IOException e) { + ExceptionUtils.logException("PDF loading from file", e); + throw ExceptionUtils.handlePdfException(e); + } } private PDDocument loadFromBytes(byte[] bytes, long size, StreamCacheCreateFunction cache) @@ -366,7 +398,13 @@ public class CustomPDFDocumentFactory { Files.write(tempFile, bytes); return loadFromFile(tempFile.toFile(), size, cache); } - return Loader.loadPDF(bytes, "", null, null, cache); + + try { + return Loader.loadPDF(bytes, "", null, null, cache); + } catch (IOException e) { + ExceptionUtils.logException("PDF loading from bytes", e); + throw ExceptionUtils.handlePdfException(e); + } } public PDDocument createNewDocument(MemoryUsageSetting settings) throws IOException { @@ -399,7 +437,7 @@ public class CustomPDFDocumentFactory { try { document.setAllSecurityToBeRemoved(true); } catch (Exception e) { - log.error("Decryption failed", e); + ExceptionUtils.logException("PDF decryption", e); throw new IOException("PDF decryption failed", e); } } diff --git a/common/src/main/java/stirling/software/common/service/FileOrUploadService.java b/app/common/src/main/java/stirling/software/common/service/FileOrUploadService.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/FileOrUploadService.java rename to app/common/src/main/java/stirling/software/common/service/FileOrUploadService.java diff --git a/common/src/main/java/stirling/software/common/service/FileStorage.java b/app/common/src/main/java/stirling/software/common/service/FileStorage.java similarity index 77% rename from common/src/main/java/stirling/software/common/service/FileStorage.java rename to app/common/src/main/java/stirling/software/common/service/FileStorage.java index e200ded8a..320b97865 100644 --- a/common/src/main/java/stirling/software/common/service/FileStorage.java +++ b/app/common/src/main/java/stirling/software/common/service/FileStorage.java @@ -131,14 +131,46 @@ public class FileStorage { return Files.exists(filePath); } + /** + * Get the size of a file by its ID without loading the content into memory + * + * @param fileId The ID of the file + * @return The size of the file in bytes + * @throws IOException If the file doesn't exist or can't be read + */ + public long getFileSize(String fileId) throws IOException { + Path filePath = getFilePath(fileId); + + if (!Files.exists(filePath)) { + throw new IOException("File not found with ID: " + fileId); + } + + return Files.size(filePath); + } + /** * Get the path for a file ID * * @param fileId The ID of the file * @return The path to the file + * @throws IllegalArgumentException if fileId contains path traversal characters or resolves + * outside base directory */ private Path getFilePath(String fileId) { - return Path.of(tempDirPath).resolve(fileId); + // Validate fileId to prevent path traversal + if (fileId.contains("..") || fileId.contains("/") || fileId.contains("\\")) { + throw new IllegalArgumentException("Invalid file ID"); + } + + Path basePath = Path.of(tempDirPath).normalize().toAbsolutePath(); + Path resolvedPath = basePath.resolve(fileId).normalize(); + + // Ensure resolved path is within the base directory + if (!resolvedPath.startsWith(basePath)) { + throw new IllegalArgumentException("File ID resolves to an invalid path"); + } + + return resolvedPath; } /** diff --git a/common/src/main/java/stirling/software/common/service/JobExecutorService.java b/app/common/src/main/java/stirling/software/common/service/JobExecutorService.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/JobExecutorService.java rename to app/common/src/main/java/stirling/software/common/service/JobExecutorService.java diff --git a/common/src/main/java/stirling/software/common/service/JobQueue.java b/app/common/src/main/java/stirling/software/common/service/JobQueue.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/JobQueue.java rename to app/common/src/main/java/stirling/software/common/service/JobQueue.java diff --git a/common/src/main/java/stirling/software/common/service/PdfMetadataService.java b/app/common/src/main/java/stirling/software/common/service/PdfMetadataService.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/PdfMetadataService.java rename to app/common/src/main/java/stirling/software/common/service/PdfMetadataService.java diff --git a/common/src/main/java/stirling/software/common/service/PostHogService.java b/app/common/src/main/java/stirling/software/common/service/PostHogService.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/PostHogService.java rename to app/common/src/main/java/stirling/software/common/service/PostHogService.java diff --git a/common/src/main/java/stirling/software/common/service/ResourceMonitor.java b/app/common/src/main/java/stirling/software/common/service/ResourceMonitor.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/ResourceMonitor.java rename to app/common/src/main/java/stirling/software/common/service/ResourceMonitor.java diff --git a/common/src/main/java/stirling/software/common/service/TaskManager.java b/app/common/src/main/java/stirling/software/common/service/TaskManager.java similarity index 54% rename from common/src/main/java/stirling/software/common/service/TaskManager.java rename to app/common/src/main/java/stirling/software/common/service/TaskManager.java index c2b3ba8a8..902b2bfd1 100644 --- a/common/src/main/java/stirling/software/common/service/TaskManager.java +++ b/app/common/src/main/java/stirling/software/common/service/TaskManager.java @@ -1,15 +1,26 @@ package stirling.software.common.service; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import io.github.pixee.security.ZipSecurity; import jakarta.annotation.PreDestroy; @@ -17,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.common.model.job.JobResult; import stirling.software.common.model.job.JobStats; +import stirling.software.common.model.job.ResultFile; /** Manages async tasks and their results */ @Service @@ -80,8 +92,53 @@ public class TaskManager { public void setFileResult( String jobId, String fileId, String originalFileName, String contentType) { JobResult jobResult = getOrCreateJobResult(jobId); - jobResult.completeWithFile(fileId, originalFileName, contentType); - log.debug("Set file result for job ID: {} with file ID: {}", jobId, fileId); + + // Check if this is a ZIP file that should be extracted + if (isZipFile(contentType, originalFileName)) { + try { + List extractedFiles = + extractZipToIndividualFiles(fileId, originalFileName); + if (!extractedFiles.isEmpty()) { + jobResult.completeWithFiles(extractedFiles); + log.debug( + "Set multiple file results for job ID: {} with {} files extracted from ZIP", + jobId, + extractedFiles.size()); + return; + } + } catch (Exception e) { + log.warn( + "Failed to extract ZIP file for job {}: {}. Falling back to single file result.", + jobId, + e.getMessage()); + } + } + + // Handle as single file using new ResultFile approach + try { + long fileSize = fileStorage.getFileSize(fileId); + jobResult.completeWithSingleFile(fileId, originalFileName, contentType, fileSize); + log.debug("Set single file result for job ID: {} with file ID: {}", jobId, fileId); + } catch (Exception e) { + log.warn( + "Failed to get file size for job {}: {}. Using size 0.", jobId, e.getMessage()); + jobResult.completeWithSingleFile(fileId, originalFileName, contentType, 0); + } + } + + /** + * Set the result of a task as multiple files + * + * @param jobId The job ID + * @param resultFiles The list of result files + */ + public void setMultipleFileResults(String jobId, List resultFiles) { + JobResult jobResult = getOrCreateJobResult(jobId); + jobResult.completeWithFiles(resultFiles); + log.debug( + "Set multiple file results for job ID: {} with {} files", + jobId, + resultFiles.size()); } /** @@ -104,7 +161,7 @@ public class TaskManager { public void setComplete(String jobId) { JobResult jobResult = getOrCreateJobResult(jobId); if (jobResult.getResult() == null - && jobResult.getFileId() == null + && !jobResult.hasFiles() && jobResult.getError() == null) { // If no result or error has been set, mark it as complete with an empty result jobResult.completeWithResult("Task completed successfully"); @@ -186,7 +243,7 @@ public class TaskManager { failedJobs++; } else { successfulJobs++; - if (result.getFileId() != null) { + if (result.hasFiles()) { fileResultJobs++; } } @@ -250,17 +307,8 @@ public class TaskManager { && result.getCompletedAt() != null && result.getCompletedAt().isBefore(expiryThreshold)) { - // If the job has a file result, delete the file - if (result.getFileId() != null) { - try { - fileStorage.deleteFile(result.getFileId()); - } catch (Exception e) { - log.warn( - "Failed to delete file for job {}: {}", - entry.getKey(), - e.getMessage()); - } - } + // Clean up file results + cleanupJobFiles(result, entry.getKey()); // Remove the job result jobResults.remove(entry.getKey()); @@ -290,4 +338,129 @@ public class TaskManager { cleanupExecutor.shutdownNow(); } } + + /** Check if a file is a ZIP file based on content type and filename */ + private boolean isZipFile(String contentType, String fileName) { + if (contentType != null + && (contentType.equals("application/zip") + || contentType.equals("application/x-zip-compressed"))) { + return true; + } + + if (fileName != null && fileName.toLowerCase().endsWith(".zip")) { + return true; + } + + return false; + } + + /** Extract a ZIP file into individual files and store them */ + private List extractZipToIndividualFiles( + String zipFileId, String originalZipFileName) throws IOException { + List extractedFiles = new ArrayList<>(); + + MultipartFile zipFile = fileStorage.retrieveFile(zipFileId); + + try (ZipInputStream zipIn = + ZipSecurity.createHardenedInputStream( + new ByteArrayInputStream(zipFile.getBytes()))) { + ZipEntry entry; + while ((entry = zipIn.getNextEntry()) != null) { + if (!entry.isDirectory()) { + // Use buffered reading for memory safety + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = zipIn.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + byte[] fileContent = out.toByteArray(); + + String contentType = determineContentType(entry.getName()); + String individualFileId = fileStorage.storeBytes(fileContent, entry.getName()); + + ResultFile resultFile = + ResultFile.builder() + .fileId(individualFileId) + .fileName(entry.getName()) + .contentType(contentType) + .fileSize(fileContent.length) + .build(); + + extractedFiles.add(resultFile); + log.debug( + "Extracted file: {} (size: {} bytes)", + entry.getName(), + fileContent.length); + } + zipIn.closeEntry(); + } + } + + // Clean up the original ZIP file after extraction + try { + fileStorage.deleteFile(zipFileId); + log.debug("Cleaned up original ZIP file: {}", zipFileId); + } catch (Exception e) { + log.warn("Failed to clean up original ZIP file {}: {}", zipFileId, e.getMessage()); + } + + return extractedFiles; + } + + /** Determine content type based on file extension */ + private String determineContentType(String fileName) { + if (fileName == null) { + return MediaType.APPLICATION_OCTET_STREAM_VALUE; + } + + String lowerName = fileName.toLowerCase(); + if (lowerName.endsWith(".pdf")) { + return MediaType.APPLICATION_PDF_VALUE; + } else if (lowerName.endsWith(".txt")) { + return MediaType.TEXT_PLAIN_VALUE; + } else if (lowerName.endsWith(".json")) { + return MediaType.APPLICATION_JSON_VALUE; + } else if (lowerName.endsWith(".xml")) { + return MediaType.APPLICATION_XML_VALUE; + } else if (lowerName.endsWith(".jpg") || lowerName.endsWith(".jpeg")) { + return MediaType.IMAGE_JPEG_VALUE; + } else if (lowerName.endsWith(".png")) { + return MediaType.IMAGE_PNG_VALUE; + } else { + return MediaType.APPLICATION_OCTET_STREAM_VALUE; + } + } + + /** Clean up files associated with a job result */ + private void cleanupJobFiles(JobResult result, String jobId) { + // Clean up all result files + if (result.hasFiles()) { + for (ResultFile resultFile : result.getAllResultFiles()) { + try { + fileStorage.deleteFile(resultFile.getFileId()); + } catch (Exception e) { + log.warn( + "Failed to delete file {} for job {}: {}", + resultFile.getFileId(), + jobId, + e.getMessage()); + } + } + } + } + + /** Find the ResultFile metadata for a given file ID by searching through all job results */ + public ResultFile findResultFileByFileId(String fileId) { + for (JobResult jobResult : jobResults.values()) { + if (jobResult.hasFiles()) { + for (ResultFile resultFile : jobResult.getAllResultFiles()) { + if (fileId.equals(resultFile.getFileId())) { + return resultFile; + } + } + } + } + return null; + } } diff --git a/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java b/app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java similarity index 97% rename from common/src/main/java/stirling/software/common/service/TempFileCleanupService.java rename to app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java index 4eba52f29..df85a016b 100644 --- a/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java +++ b/app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java @@ -154,11 +154,15 @@ public class TempFileCleanupService { boolean containerMode = isContainerMode(); int unregisteredDeletedCount = cleanupUnregisteredFiles(containerMode, true, maxAgeMillis); - log.info( - "Scheduled cleanup complete. Deleted {} registered files, {} unregistered files, {} directories", - registeredDeletedCount, - unregisteredDeletedCount, - directoriesDeletedCount); + if (registeredDeletedCount > 0 + || unregisteredDeletedCount > 0 + || directoriesDeletedCount > 0) { + log.info( + "Scheduled cleanup complete. Deleted {} registered files, {} unregistered files, {} directories", + registeredDeletedCount, + unregisteredDeletedCount, + directoriesDeletedCount); + } } /** @@ -166,7 +170,6 @@ public class TempFileCleanupService { * important in Docker environments where temp files persist between container restarts. */ private void runStartupCleanup() { - log.info("Running startup temporary file cleanup"); boolean containerMode = isContainerMode(); log.info( @@ -178,7 +181,6 @@ public class TempFileCleanupService { long maxAgeMillis = containerMode ? 0 : 24 * 60 * 60 * 1000; // 0 or 24 hours int totalDeletedCount = cleanupUnregisteredFiles(containerMode, false, maxAgeMillis); - log.info( "Startup cleanup complete. Deleted {} temporary files/directories", totalDeletedCount); @@ -225,7 +227,7 @@ public class TempFileCleanupService { tempDir -> { try { String phase = isScheduled ? "scheduled" : "startup"; - log.info( + log.debug( "Scanning directory for {} cleanup: {}", phase, tempDir); diff --git a/common/src/main/java/stirling/software/common/service/UserServiceInterface.java b/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java similarity index 100% rename from common/src/main/java/stirling/software/common/service/UserServiceInterface.java rename to app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java diff --git a/common/src/main/java/stirling/software/common/util/ApplicationContextProvider.java b/app/common/src/main/java/stirling/software/common/util/ApplicationContextProvider.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ApplicationContextProvider.java rename to app/common/src/main/java/stirling/software/common/util/ApplicationContextProvider.java diff --git a/common/src/main/java/stirling/software/common/util/AttachmentUtils.java b/app/common/src/main/java/stirling/software/common/util/AttachmentUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/AttachmentUtils.java rename to app/common/src/main/java/stirling/software/common/util/AttachmentUtils.java diff --git a/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java b/app/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/CheckProgramInstall.java rename to app/common/src/main/java/stirling/software/common/util/CheckProgramInstall.java diff --git a/common/src/main/java/stirling/software/common/util/CustomHtmlSanitizer.java b/app/common/src/main/java/stirling/software/common/util/CustomHtmlSanitizer.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/CustomHtmlSanitizer.java rename to app/common/src/main/java/stirling/software/common/util/CustomHtmlSanitizer.java diff --git a/common/src/main/java/stirling/software/common/util/EmlToPdf.java b/app/common/src/main/java/stirling/software/common/util/EmlToPdf.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/EmlToPdf.java rename to app/common/src/main/java/stirling/software/common/util/EmlToPdf.java diff --git a/common/src/main/java/stirling/software/common/util/ErrorUtils.java b/app/common/src/main/java/stirling/software/common/util/ErrorUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ErrorUtils.java rename to app/common/src/main/java/stirling/software/common/util/ErrorUtils.java diff --git a/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java b/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java new file mode 100644 index 000000000..74f65e713 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/util/ExceptionUtils.java @@ -0,0 +1,327 @@ +package stirling.software.common.util; + +import java.io.IOException; +import java.text.MessageFormat; + +import lombok.extern.slf4j.Slf4j; + +/** + * Utility class for handling exceptions with internationalized error messages. Provides consistent + * error handling and user-friendly messages across the application. + */ +@Slf4j +public class ExceptionUtils { + + /** + * Create an IOException with internationalized message for PDF corruption. + * + * @param cause the original exception + * @return IOException with user-friendly message + */ + public static IOException createPdfCorruptedException(Exception cause) { + return createPdfCorruptedException(null, cause); + } + + /** + * Create an IOException with internationalized message for PDF corruption with context. + * + * @param context additional context (e.g., "during merge", "during image extraction") + * @param cause the original exception + * @return IOException with user-friendly message + */ + public static IOException createPdfCorruptedException(String context, Exception cause) { + String message; + if (context != null && !context.isEmpty()) { + message = + String.format( + "Error %s: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation.", + context); + } else { + message = + "PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation."; + } + return new IOException(message, cause); + } + + /** + * Create an IOException with internationalized message for multiple corrupted PDFs. + * + * @param cause the original exception + * @return IOException with user-friendly message + */ + public static IOException createMultiplePdfCorruptedException(Exception cause) { + String message = + "One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them."; + return new IOException(message, cause); + } + + /** + * Create an IOException with internationalized message for PDF encryption issues. + * + * @param cause the original exception + * @return IOException with user-friendly message + */ + public static IOException createPdfEncryptionException(Exception cause) { + String message = + "The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy."; + return new IOException(message, cause); + } + + /** + * Create an IOException with internationalized message for PDF password issues. + * + * @param cause the original exception + * @return IOException with user-friendly message + */ + public static IOException createPdfPasswordException(Exception cause) { + String message = + "The PDF Document is passworded and either the password was not provided or was incorrect"; + return new IOException(message, cause); + } + + /** + * Create an IOException with internationalized message for file processing errors. + * + * @param operation the operation being performed (e.g., "merge", "split", "convert") + * @param cause the original exception + * @return IOException with user-friendly message + */ + public static IOException createFileProcessingException(String operation, Exception cause) { + String message = + String.format( + "An error occurred while processing the file during %s operation: %s", + operation, cause.getMessage()); + return new IOException(message, cause); + } + + /** + * Create a generic IOException with internationalized message. + * + * @param messageKey the i18n message key + * @param defaultMessage the default message if i18n is not available + * @param cause the original exception + * @param args optional arguments for the message + * @return IOException with user-friendly message + */ + public static IOException createIOException( + String messageKey, String defaultMessage, Exception cause, Object... args) { + String message = MessageFormat.format(defaultMessage, args); + return new IOException(message, cause); + } + + /** + * Create a generic RuntimeException with internationalized message. + * + * @param messageKey the i18n message key + * @param defaultMessage the default message if i18n is not available + * @param cause the original exception + * @param args optional arguments for the message + * @return RuntimeException with user-friendly message + */ + public static RuntimeException createRuntimeException( + String messageKey, String defaultMessage, Exception cause, Object... args) { + String message = MessageFormat.format(defaultMessage, args); + return new RuntimeException(message, cause); + } + + /** + * Create an IllegalArgumentException with internationalized message. + * + * @param messageKey the i18n message key + * @param defaultMessage the default message if i18n is not available + * @param args optional arguments for the message + * @return IllegalArgumentException with user-friendly message + */ + public static IllegalArgumentException createIllegalArgumentException( + String messageKey, String defaultMessage, Object... args) { + String message = MessageFormat.format(defaultMessage, args); + return new IllegalArgumentException(message); + } + + /** Create file validation exceptions. */ + public static IllegalArgumentException createHtmlFileRequiredException() { + return createIllegalArgumentException( + "error.fileFormatRequired", "File must be in {0} format", "HTML or ZIP"); + } + + public static IllegalArgumentException createPdfFileRequiredException() { + return createIllegalArgumentException( + "error.fileFormatRequired", "File must be in {0} format", "PDF"); + } + + public static IllegalArgumentException createInvalidPageSizeException(String size) { + return createIllegalArgumentException( + "error.invalidFormat", "Invalid {0} format: {1}", "page size", size); + } + + /** Create OCR-related exceptions. */ + public static IOException createOcrLanguageRequiredException() { + return createIOException( + "error.optionsNotSpecified", "{0} options are not specified", null, "OCR language"); + } + + public static IOException createOcrInvalidLanguagesException() { + return createIOException( + "error.invalidFormat", + "Invalid {0} format: {1}", + null, + "OCR languages", + "none of the selected languages are valid"); + } + + public static IOException createOcrToolsUnavailableException() { + return createIOException( + "error.toolNotInstalled", "{0} is not installed", null, "OCR tools"); + } + + /** Create system requirement exceptions. */ + public static IOException createPythonRequiredForWebpException() { + return createIOException( + "error.toolRequired", "{0} is required for {1}", null, "Python", "WebP conversion"); + } + + /** Create file operation exceptions. */ + public static IOException createFileNotFoundException(String fileId) { + return createIOException("error.fileNotFound", "File not found with ID: {0}", null, fileId); + } + + public static RuntimeException createPdfaConversionFailedException() { + return createRuntimeException( + "error.conversionFailed", "{0} conversion failed", null, "PDF/A"); + } + + public static IllegalArgumentException createInvalidComparatorException() { + return createIllegalArgumentException( + "error.invalidFormat", + "Invalid {0} format: {1}", + "comparator", + "only 'greater', 'equal', and 'less' are supported"); + } + + /** Create compression-related exceptions. */ + public static RuntimeException createMd5AlgorithmException(Exception cause) { + return createRuntimeException( + "error.algorithmNotAvailable", "{0} algorithm not available", cause, "MD5"); + } + + public static IllegalArgumentException createCompressionOptionsException() { + return createIllegalArgumentException( + "error.optionsNotSpecified", + "{0} options are not specified", + "compression (expected output size and optimize level)"); + } + + public static IOException createGhostscriptCompressionException() { + return createIOException( + "error.commandFailed", "{0} command failed", null, "Ghostscript compression"); + } + + public static IOException createGhostscriptCompressionException(Exception cause) { + return createIOException( + "error.commandFailed", "{0} command failed", cause, "Ghostscript compression"); + } + + public static IOException createQpdfCompressionException(Exception cause) { + return createIOException("error.commandFailed", "{0} command failed", cause, "QPDF"); + } + + /** + * Check if an exception indicates a corrupted PDF and wrap it with appropriate message. + * + * @param e the exception to check + * @return the original exception if not PDF corruption, or a new IOException with user-friendly + * message + */ + public static IOException handlePdfException(IOException e) { + return handlePdfException(e, null); + } + + /** + * Check if an exception indicates a corrupted PDF and wrap it with appropriate message. + * + * @param e the exception to check + * @param context additional context for the error + * @return the original exception if not PDF corruption, or a new IOException with user-friendly + * message + */ + public static IOException handlePdfException(IOException e, String context) { + if (PdfErrorUtils.isCorruptedPdfError(e)) { + return createPdfCorruptedException(context, e); + } + + if (isEncryptionError(e)) { + return createPdfEncryptionException(e); + } + + if (isPasswordError(e)) { + return createPdfPasswordException(e); + } + + return e; // Return original exception if no specific handling needed + } + + /** + * Check if an exception indicates a PDF encryption/decryption error. + * + * @param e the exception to check + * @return true if it's an encryption error, false otherwise + */ + public static boolean isEncryptionError(IOException e) { + String message = e.getMessage(); + if (message == null) return false; + + return message.contains("BadPaddingException") + || message.contains("Given final block not properly padded") + || message.contains("AES initialization vector not fully read") + || message.contains("Failed to decrypt"); + } + + /** + * Check if an exception indicates a PDF password error. + * + * @param e the exception to check + * @return true if it's a password error, false otherwise + */ + public static boolean isPasswordError(IOException e) { + String message = e.getMessage(); + if (message == null) return false; + + return message.contains("password is incorrect") + || message.contains("Password is not provided") + || message.contains("PDF contains an encryption dictionary"); + } + + /** + * Log an exception with appropriate level based on its type. + * + * @param operation the operation being performed + * @param e the exception that occurred + */ + public static void logException(String operation, Exception e) { + if (PdfErrorUtils.isCorruptedPdfError(e)) { + log.warn("PDF corruption detected during {}: {}", operation, e.getMessage()); + } else if (e instanceof IOException + && (isEncryptionError((IOException) e) || isPasswordError((IOException) e))) { + log.info("PDF security issue during {}: {}", operation, e.getMessage()); + } else { + log.error("Unexpected error during {}", operation, e); + } + } + + /** Create common validation exceptions. */ + public static IllegalArgumentException createInvalidArgumentException(String argumentName) { + return createIllegalArgumentException( + "error.invalidArgument", "Invalid argument: {0}", argumentName); + } + + public static IllegalArgumentException createInvalidArgumentException( + String argumentName, String value) { + return createIllegalArgumentException( + "error.invalidFormat", "Invalid {0} format: {1}", argumentName, value); + } + + public static IllegalArgumentException createNullArgumentException(String argumentName) { + return createIllegalArgumentException( + "error.argumentRequired", "{0} must not be null", argumentName); + } +} diff --git a/common/src/main/java/stirling/software/common/util/ExecutorFactory.java b/app/common/src/main/java/stirling/software/common/util/ExecutorFactory.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ExecutorFactory.java rename to app/common/src/main/java/stirling/software/common/util/ExecutorFactory.java diff --git a/common/src/main/java/stirling/software/common/util/FileMonitor.java b/app/common/src/main/java/stirling/software/common/util/FileMonitor.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/FileMonitor.java rename to app/common/src/main/java/stirling/software/common/util/FileMonitor.java diff --git a/common/src/main/java/stirling/software/common/util/FileToPdf.java b/app/common/src/main/java/stirling/software/common/util/FileToPdf.java similarity index 95% rename from common/src/main/java/stirling/software/common/util/FileToPdf.java rename to app/common/src/main/java/stirling/software/common/util/FileToPdf.java index 7b3765084..c735e5287 100644 --- a/common/src/main/java/stirling/software/common/util/FileToPdf.java +++ b/app/common/src/main/java/stirling/software/common/util/FileToPdf.java @@ -32,21 +32,23 @@ public class FileToPdf { try (TempFile tempOutputFile = new TempFile(tempFileManager, ".pdf")) { try (TempFile tempInputFile = - new TempFile(tempFileManager, fileName.endsWith(".html") ? ".html" : ".zip")) { + new TempFile( + tempFileManager, + fileName.toLowerCase().endsWith(".html") ? ".html" : ".zip")) { - if (fileName.endsWith(".html")) { + if (fileName.toLowerCase().endsWith(".html")) { String sanitizedHtml = sanitizeHtmlContent( new String(fileBytes, StandardCharsets.UTF_8), disableSanitize); Files.write( tempInputFile.getPath(), sanitizedHtml.getBytes(StandardCharsets.UTF_8)); - } else if (fileName.endsWith(".zip")) { + } else if (fileName.toLowerCase().endsWith(".zip")) { Files.write(tempInputFile.getPath(), fileBytes); sanitizeHtmlFilesInZip( tempInputFile.getPath(), disableSanitize, tempFileManager); } else { - throw new IllegalArgumentException("Unsupported file format: " + fileName); + throw ExceptionUtils.createHtmlFileRequiredException(); } List command = new ArrayList<>(); diff --git a/common/src/main/java/stirling/software/common/util/GeneralUtils.java b/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/GeneralUtils.java rename to app/common/src/main/java/stirling/software/common/util/GeneralUtils.java diff --git a/common/src/main/java/stirling/software/common/util/ImageProcessingUtils.java b/app/common/src/main/java/stirling/software/common/util/ImageProcessingUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ImageProcessingUtils.java rename to app/common/src/main/java/stirling/software/common/util/ImageProcessingUtils.java diff --git a/common/src/main/java/stirling/software/common/util/PDFToFile.java b/app/common/src/main/java/stirling/software/common/util/PDFToFile.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/PDFToFile.java rename to app/common/src/main/java/stirling/software/common/util/PDFToFile.java diff --git a/app/common/src/main/java/stirling/software/common/util/PdfErrorUtils.java b/app/common/src/main/java/stirling/software/common/util/PdfErrorUtils.java new file mode 100644 index 000000000..aeda114c9 --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/util/PdfErrorUtils.java @@ -0,0 +1,55 @@ +package stirling.software.common.util; + +import java.io.IOException; + +/** Utility class for detecting and handling PDF-related errors. */ +public class PdfErrorUtils { + + /** + * Checks if an IOException indicates a corrupted PDF file. + * + * @param e the IOException to check + * @return true if the error indicates PDF corruption, false otherwise + */ + public static boolean isCorruptedPdfError(IOException e) { + return isCorruptedPdfError(e.getMessage()); + } + + /** + * Checks if any Exception indicates a corrupted PDF file. + * + * @param e the Exception to check + * @return true if the error indicates PDF corruption, false otherwise + */ + public static boolean isCorruptedPdfError(Exception e) { + return isCorruptedPdfError(e.getMessage()); + } + + /** + * Checks if an error message indicates a corrupted PDF file. + * + * @param message the error message to check + * @return true if the message indicates PDF corruption, false otherwise + */ + private static boolean isCorruptedPdfError(String message) { + if (message == null) return false; + + // Check for common corruption indicators + return message.contains("Missing root object specification") + || message.contains("Header doesn't contain versioninfo") + || message.contains("Expected trailer") + || message.contains("Invalid PDF") + || message.contains("Corrupted") + || message.contains("damaged") + || message.contains("Unknown dir object") + || message.contains("Can't dereference COSObject") + || message.contains("parseCOSString string should start with") + || message.contains("ICCBased colorspace array must have a stream") + || message.contains("1-based index not found") + || message.contains("Invalid dictionary, found:") + || message.contains("AES initialization vector not fully read") + || message.contains("BadPaddingException") + || message.contains("Given final block not properly padded") + || message.contains("End-of-File, expected line"); + } +} diff --git a/common/src/main/java/stirling/software/common/util/PdfUtils.java b/app/common/src/main/java/stirling/software/common/util/PdfUtils.java similarity index 79% rename from common/src/main/java/stirling/software/common/util/PdfUtils.java rename to app/common/src/main/java/stirling/software/common/util/PdfUtils.java index 3986110e5..ec269e47d 100644 --- a/common/src/main/java/stirling/software/common/util/PdfUtils.java +++ b/app/common/src/main/java/stirling/software/common/util/PdfUtils.java @@ -42,26 +42,34 @@ public class PdfUtils { public static PDRectangle textToPageSize(String size) { switch (size.toUpperCase()) { - case "A0": + case "A0" -> { return PDRectangle.A0; - case "A1": + } + case "A1" -> { return PDRectangle.A1; - case "A2": + } + case "A2" -> { return PDRectangle.A2; - case "A3": + } + case "A3" -> { return PDRectangle.A3; - case "A4": + } + case "A4" -> { return PDRectangle.A4; - case "A5": + } + case "A5" -> { return PDRectangle.A5; - case "A6": + } + case "A6" -> { return PDRectangle.A6; - case "LETTER": + } + case "LETTER" -> { return PDRectangle.LETTER; - case "LEGAL": + } + case "LEGAL" -> { return PDRectangle.LEGAL; - default: - throw new IllegalArgumentException("Invalid standard page size: " + size); + } + default -> throw ExceptionUtils.createInvalidPageSizeException(size); } } @@ -135,6 +143,17 @@ public class PdfUtils { int DPI, String filename) throws IOException, Exception { + + // Validate and limit DPI to prevent excessive memory usage + final int MAX_SAFE_DPI = 500; // Maximum safe DPI to prevent memory issues + if (DPI > MAX_SAFE_DPI) { + throw ExceptionUtils.createIllegalArgumentException( + "error.dpiExceedsLimit", + "DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value.", + DPI, + MAX_SAFE_DPI); + } + try (PDDocument document = pdfDocumentFactory.load(inputStream)) { PDFRenderer pdfRenderer = new PDFRenderer(document); pdfRenderer.setSubsamplingAllowed(true); @@ -158,7 +177,21 @@ public class PdfUtils { writer.prepareWriteSequence(null); for (int i = 0; i < pageCount; ++i) { - BufferedImage image = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + BufferedImage image; + try { + image = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + } catch (IllegalArgumentException e) { + if (e.getMessage() != null + && e.getMessage() + .contains("Maximum size of image exceeded")) { + throw ExceptionUtils.createIllegalArgumentException( + "error.pageTooBigForDpi", + "PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less).", + i + 1, + DPI); + } + throw e; + } writer.writeToSequence(new IIOImage(image, null, null), param); } @@ -190,7 +223,20 @@ public class PdfUtils { PdfImageDimensionValue dimension = pageSizes.get(settings); if (dimension == null) { // Render the image to get the dimensions - pdfSizeImage = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + try { + pdfSizeImage = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + } catch (IllegalArgumentException e) { + if (e.getMessage() != null + && e.getMessage() + .contains("Maximum size of image exceeded")) { + throw ExceptionUtils.createIllegalArgumentException( + "error.pageTooBigExceedsArray", + "PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less).", + i + 1, + DPI); + } + throw e; + } pdfSizeImageIndex = i; dimension = new PdfImageDimensionValue( @@ -218,7 +264,20 @@ public class PdfUtils { if (firstImageAlreadyRendered && i == 0) { pageImage = pdfSizeImage; } else { - pageImage = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + try { + pageImage = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + } catch (IllegalArgumentException e) { + if (e.getMessage() != null + && e.getMessage() + .contains("Maximum size of image exceeded")) { + throw ExceptionUtils.createIllegalArgumentException( + "error.pageTooBigForDpi", + "PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less).", + i + 1, + DPI); + } + throw e; + } } // Calculate the x-coordinate to center the image @@ -238,7 +297,20 @@ public class PdfUtils { // Zip the images and return as byte array try (ZipOutputStream zos = new ZipOutputStream(baos)) { for (int i = 0; i < pageCount; ++i) { - BufferedImage image = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + BufferedImage image; + try { + image = pdfRenderer.renderImageWithDPI(i, DPI, colorType); + } catch (IllegalArgumentException e) { + if (e.getMessage() != null + && e.getMessage().contains("Maximum size of image exceeded")) { + throw ExceptionUtils.createIllegalArgumentException( + "error.pageTooBigForDpi", + "PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less).", + i + 1, + DPI); + } + throw e; + } try (ByteArrayOutputStream baosImage = new ByteArrayOutputStream()) { ImageIO.write(image, imageType, baosImage); @@ -276,7 +348,19 @@ public class PdfUtils { PDFRenderer pdfRenderer = new PDFRenderer(document); pdfRenderer.setSubsamplingAllowed(true); for (int page = 0; page < document.getNumberOfPages(); ++page) { - BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); + BufferedImage bim; + try { + bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); + } catch (IllegalArgumentException e) { + if (e.getMessage() != null + && e.getMessage().contains("Maximum size of image exceeded")) { + throw ExceptionUtils.createIllegalArgumentException( + "error.pageTooBigFor300Dpi", + "PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion.", + page + 1); + } + throw e; + } PDPage originalPage = document.getPage(page); float width = originalPage.getMediaBox().getWidth(); @@ -349,7 +433,7 @@ public class PdfUtils { } ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); doc.save(byteArrayOutputStream); - log.info("PDF successfully saved to byte array"); + log.debug("PDF successfully saved to byte array"); return byteArrayOutputStream.toByteArray(); } } @@ -495,8 +579,7 @@ public class PdfUtils { case "less": return actualPageCount < pageCount; default: - throw new IllegalArgumentException( - "Invalid comparator. Only 'greater', 'equal', and 'less' are supported."); + throw ExceptionUtils.createInvalidArgumentException("comparator", comparator); } } diff --git a/common/src/main/java/stirling/software/common/util/ProcessExecutor.java b/app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java similarity index 91% rename from common/src/main/java/stirling/software/common/util/ProcessExecutor.java rename to app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java index 09c5ff675..ee7297153 100644 --- a/common/src/main/java/stirling/software/common/util/ProcessExecutor.java +++ b/app/common/src/main/java/stirling/software/common/util/ProcessExecutor.java @@ -84,6 +84,16 @@ public class ProcessExecutor { .getProcessExecutor() .getSessionLimit() .getCalibreSessionLimit(); + case GHOSTSCRIPT -> + applicationProperties + .getProcessExecutor() + .getSessionLimit() + .getGhostscriptSessionLimit(); + case OCR_MY_PDF -> + applicationProperties + .getProcessExecutor() + .getSessionLimit() + .getOcrMyPdfSessionLimit(); }; long timeoutMinutes = @@ -128,6 +138,16 @@ public class ProcessExecutor { .getProcessExecutor() .getTimeoutMinutes() .getCalibreTimeoutMinutes(); + case GHOSTSCRIPT -> + applicationProperties + .getProcessExecutor() + .getTimeoutMinutes() + .getGhostscriptTimeoutMinutes(); + case OCR_MY_PDF -> + applicationProperties + .getProcessExecutor() + .getTimeoutMinutes() + .getOcrMyPdfTimeoutMinutes(); }; return new ProcessExecutor(semaphoreLimit, liveUpdates, timeoutMinutes); }); @@ -278,7 +298,9 @@ public class ProcessExecutor { INSTALL_APP, CALIBRE, TESSERACT, - QPDF + QPDF, + GHOSTSCRIPT, + OCR_MY_PDF } public class ProcessExecutorResult { diff --git a/common/src/main/java/stirling/software/common/util/PropertyConfigs.java b/app/common/src/main/java/stirling/software/common/util/PropertyConfigs.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/PropertyConfigs.java rename to app/common/src/main/java/stirling/software/common/util/PropertyConfigs.java diff --git a/common/src/main/java/stirling/software/common/util/ProviderUtils.java b/app/common/src/main/java/stirling/software/common/util/ProviderUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ProviderUtils.java rename to app/common/src/main/java/stirling/software/common/util/ProviderUtils.java diff --git a/common/src/main/java/stirling/software/common/util/RequestUriUtils.java b/app/common/src/main/java/stirling/software/common/util/RequestUriUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/RequestUriUtils.java rename to app/common/src/main/java/stirling/software/common/util/RequestUriUtils.java diff --git a/common/src/main/java/stirling/software/common/util/SpringContextHolder.java b/app/common/src/main/java/stirling/software/common/util/SpringContextHolder.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/SpringContextHolder.java rename to app/common/src/main/java/stirling/software/common/util/SpringContextHolder.java diff --git a/common/src/main/java/stirling/software/common/util/TempDirectory.java b/app/common/src/main/java/stirling/software/common/util/TempDirectory.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/TempDirectory.java rename to app/common/src/main/java/stirling/software/common/util/TempDirectory.java diff --git a/common/src/main/java/stirling/software/common/util/TempFile.java b/app/common/src/main/java/stirling/software/common/util/TempFile.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/TempFile.java rename to app/common/src/main/java/stirling/software/common/util/TempFile.java diff --git a/common/src/main/java/stirling/software/common/util/TempFileManager.java b/app/common/src/main/java/stirling/software/common/util/TempFileManager.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/TempFileManager.java rename to app/common/src/main/java/stirling/software/common/util/TempFileManager.java diff --git a/common/src/main/java/stirling/software/common/util/TempFileRegistry.java b/app/common/src/main/java/stirling/software/common/util/TempFileRegistry.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/TempFileRegistry.java rename to app/common/src/main/java/stirling/software/common/util/TempFileRegistry.java diff --git a/common/src/main/java/stirling/software/common/util/TempFileUtil.java b/app/common/src/main/java/stirling/software/common/util/TempFileUtil.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/TempFileUtil.java rename to app/common/src/main/java/stirling/software/common/util/TempFileUtil.java diff --git a/common/src/main/java/stirling/software/common/util/UIScaling.java b/app/common/src/main/java/stirling/software/common/util/UIScaling.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/UIScaling.java rename to app/common/src/main/java/stirling/software/common/util/UIScaling.java diff --git a/common/src/main/java/stirling/software/common/util/UrlUtils.java b/app/common/src/main/java/stirling/software/common/util/UrlUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/UrlUtils.java rename to app/common/src/main/java/stirling/software/common/util/UrlUtils.java diff --git a/common/src/main/java/stirling/software/common/util/ValidationUtil.java b/app/common/src/main/java/stirling/software/common/util/ValidationUtil.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ValidationUtil.java rename to app/common/src/main/java/stirling/software/common/util/ValidationUtil.java diff --git a/common/src/main/java/stirling/software/common/util/ValidationUtils.java b/app/common/src/main/java/stirling/software/common/util/ValidationUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/ValidationUtils.java rename to app/common/src/main/java/stirling/software/common/util/ValidationUtils.java diff --git a/common/src/main/java/stirling/software/common/util/WebResponseUtils.java b/app/common/src/main/java/stirling/software/common/util/WebResponseUtils.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/WebResponseUtils.java rename to app/common/src/main/java/stirling/software/common/util/WebResponseUtils.java diff --git a/common/src/main/java/stirling/software/common/util/YamlHelper.java b/app/common/src/main/java/stirling/software/common/util/YamlHelper.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/YamlHelper.java rename to app/common/src/main/java/stirling/software/common/util/YamlHelper.java diff --git a/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java b/app/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java similarity index 94% rename from common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java rename to app/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java index dc1781236..6703a159a 100644 --- a/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java +++ b/app/common/src/main/java/stirling/software/common/util/misc/CustomColorReplaceStrategy.java @@ -108,6 +108,12 @@ public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy { } catch (IllegalArgumentException ie) { log.info("text not supported by font "); font = checkSupportedFontForCharacter(unicodeText); + } catch (UnsupportedOperationException ue) { + log.info( + "font does not support encoding operation: {} for text: '{}'", + font.getClass().getSimpleName(), + unicodeText); + font = checkSupportedFontForCharacter(unicodeText); } finally { // if any other font is not supported, then replace default character * if (font == null) { diff --git a/common/src/main/java/stirling/software/common/util/misc/HighContrastColorReplaceDecider.java b/app/common/src/main/java/stirling/software/common/util/misc/HighContrastColorReplaceDecider.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/misc/HighContrastColorReplaceDecider.java rename to app/common/src/main/java/stirling/software/common/util/misc/HighContrastColorReplaceDecider.java diff --git a/common/src/main/java/stirling/software/common/util/misc/InvertFullColorStrategy.java b/app/common/src/main/java/stirling/software/common/util/misc/InvertFullColorStrategy.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/misc/InvertFullColorStrategy.java rename to app/common/src/main/java/stirling/software/common/util/misc/InvertFullColorStrategy.java diff --git a/common/src/main/java/stirling/software/common/util/misc/PdfTextStripperCustom.java b/app/common/src/main/java/stirling/software/common/util/misc/PdfTextStripperCustom.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/misc/PdfTextStripperCustom.java rename to app/common/src/main/java/stirling/software/common/util/misc/PdfTextStripperCustom.java diff --git a/common/src/main/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategy.java b/app/common/src/main/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategy.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategy.java rename to app/common/src/main/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategy.java diff --git a/common/src/main/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditor.java b/app/common/src/main/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditor.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditor.java rename to app/common/src/main/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditor.java diff --git a/common/src/main/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditor.java b/app/common/src/main/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditor.java similarity index 100% rename from common/src/main/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditor.java rename to app/common/src/main/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditor.java diff --git a/common/src/test/java/stirling/software/common/annotations/AutoJobPostMappingIntegrationTest.java b/app/common/src/test/java/stirling/software/common/annotations/AutoJobPostMappingIntegrationTest.java similarity index 98% rename from common/src/test/java/stirling/software/common/annotations/AutoJobPostMappingIntegrationTest.java rename to app/common/src/test/java/stirling/software/common/annotations/AutoJobPostMappingIntegrationTest.java index e25ceddf9..6d72855fb 100644 --- a/common/src/test/java/stirling/software/common/annotations/AutoJobPostMappingIntegrationTest.java +++ b/app/common/src/test/java/stirling/software/common/annotations/AutoJobPostMappingIntegrationTest.java @@ -126,7 +126,7 @@ class AutoJobPostMappingIntegrationTest { verify(jobExecutorService).runJobGeneric( asyncCaptor.capture(), - workCaptor.capture(), + workCaptor.capture(), timeoutCaptor.capture(), queueableCaptor.capture(), resourceWeightCaptor.capture()); @@ -197,7 +197,7 @@ class AutoJobPostMappingIntegrationTest { autoJobAspect.wrapWithJobExecution(joinPoint, autoJobPostMapping); // Then - assertEquals("stored-file-id", pdfFile.getFileId(), + assertEquals("stored-file-id", pdfFile.getFileId(), "FileId should be set to the stored file id"); assertNotNull(pdfFile.getFileInput(), "FileInput should be replaced with persistent file"); diff --git a/common/src/test/java/stirling/software/common/service/CustomPDFDocumentFactoryTest.java b/app/common/src/test/java/stirling/software/common/service/CustomPDFDocumentFactoryTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/service/CustomPDFDocumentFactoryTest.java rename to app/common/src/test/java/stirling/software/common/service/CustomPDFDocumentFactoryTest.java diff --git a/common/src/test/java/stirling/software/common/service/FileStorageTest.java b/app/common/src/test/java/stirling/software/common/service/FileStorageTest.java similarity index 99% rename from common/src/test/java/stirling/software/common/service/FileStorageTest.java rename to app/common/src/test/java/stirling/software/common/service/FileStorageTest.java index f1ca1ffdf..81ab5857e 100644 --- a/common/src/test/java/stirling/software/common/service/FileStorageTest.java +++ b/app/common/src/test/java/stirling/software/common/service/FileStorageTest.java @@ -187,4 +187,4 @@ class FileStorageTest { // Assert assertFalse(result); } -} \ No newline at end of file +} diff --git a/common/src/test/java/stirling/software/common/service/JobExecutorServiceTest.java b/app/common/src/test/java/stirling/software/common/service/JobExecutorServiceTest.java similarity index 99% rename from common/src/test/java/stirling/software/common/service/JobExecutorServiceTest.java rename to app/common/src/test/java/stirling/software/common/service/JobExecutorServiceTest.java index a4d293b1b..370db503b 100644 --- a/common/src/test/java/stirling/software/common/service/JobExecutorServiceTest.java +++ b/app/common/src/test/java/stirling/software/common/service/JobExecutorServiceTest.java @@ -64,8 +64,8 @@ class JobExecutorServiceTest { void setUp() { // Initialize the service manually with all its dependencies jobExecutorService = new JobExecutorService( - taskManager, - fileStorage, + taskManager, + fileStorage, request, resourceMonitor, jobQueue, @@ -199,4 +199,4 @@ class JobExecutorServiceTest { assertTrue(e.getCause() instanceof TimeoutException); } } -} \ No newline at end of file +} diff --git a/common/src/test/java/stirling/software/common/service/JobQueueTest.java b/app/common/src/test/java/stirling/software/common/service/JobQueueTest.java similarity index 99% rename from common/src/test/java/stirling/software/common/service/JobQueueTest.java rename to app/common/src/test/java/stirling/software/common/service/JobQueueTest.java index 813f5e172..64c836faf 100644 --- a/common/src/test/java/stirling/software/common/service/JobQueueTest.java +++ b/app/common/src/test/java/stirling/software/common/service/JobQueueTest.java @@ -36,7 +36,7 @@ class JobQueueTest { // Mark stubbing as lenient to avoid UnnecessaryStubbingException lenient().when(resourceMonitor.calculateDynamicQueueCapacity(anyInt(), anyInt())).thenReturn(10); lenient().when(resourceMonitor.getCurrentStatus()).thenReturn(statusRef); - + // Initialize JobQueue with mocked ResourceMonitor jobQueue = new JobQueue(resourceMonitor); } @@ -99,4 +99,4 @@ class JobQueueTest { assertTrue(jobQueue.isJobQueued(jobId)); assertFalse(jobQueue.isJobQueued("nonexistent")); } -} \ No newline at end of file +} diff --git a/common/src/test/java/stirling/software/common/service/ResourceMonitorTest.java b/app/common/src/test/java/stirling/software/common/service/ResourceMonitorTest.java similarity index 99% rename from common/src/test/java/stirling/software/common/service/ResourceMonitorTest.java rename to app/common/src/test/java/stirling/software/common/service/ResourceMonitorTest.java index a707b87e6..9667f4999 100644 --- a/common/src/test/java/stirling/software/common/service/ResourceMonitorTest.java +++ b/app/common/src/test/java/stirling/software/common/service/ResourceMonitorTest.java @@ -117,7 +117,7 @@ class ResourceMonitorTest { // Then assertEquals(shouldQueue, result, - String.format("For weight %d and status %s, shouldQueue should be %s", + String.format("For weight %d and status %s, shouldQueue should be %s", weight, status, shouldQueue)); } @@ -134,4 +134,4 @@ class ResourceMonitorTest { assertTrue(staleMetrics.isStale(5000), "Metrics from 6 seconds ago should be stale with 5s threshold"); assertFalse(freshMetrics.isStale(5000), "Fresh metrics should not be stale"); } -} \ No newline at end of file +} diff --git a/common/src/test/java/stirling/software/common/service/SpyPDFDocumentFactory.java b/app/common/src/test/java/stirling/software/common/service/SpyPDFDocumentFactory.java similarity index 100% rename from common/src/test/java/stirling/software/common/service/SpyPDFDocumentFactory.java rename to app/common/src/test/java/stirling/software/common/service/SpyPDFDocumentFactory.java diff --git a/common/src/test/java/stirling/software/common/service/TaskManagerTest.java b/app/common/src/test/java/stirling/software/common/service/TaskManagerTest.java similarity index 86% rename from common/src/test/java/stirling/software/common/service/TaskManagerTest.java rename to app/common/src/test/java/stirling/software/common/service/TaskManagerTest.java index 85f62aed4..5fd2dcc87 100644 --- a/common/src/test/java/stirling/software/common/service/TaskManagerTest.java +++ b/app/common/src/test/java/stirling/software/common/service/TaskManagerTest.java @@ -18,6 +18,7 @@ import org.springframework.test.util.ReflectionTestUtils; import stirling.software.common.model.job.JobResult; import stirling.software.common.model.job.JobStats; +import stirling.software.common.model.job.ResultFile; class TaskManagerTest { @@ -73,13 +74,17 @@ class TaskManagerTest { } @Test - void testSetFileResult() { + void testSetFileResult() throws Exception { // Arrange String jobId = UUID.randomUUID().toString(); taskManager.createTask(jobId); String fileId = "file-id"; String originalFileName = "test.pdf"; String contentType = "application/pdf"; + long fileSize = 1024L; + + // Mock the fileStorage.getFileSize() call + when(fileStorage.getFileSize(fileId)).thenReturn(fileSize); // Act taskManager.setFileResult(jobId, fileId, originalFileName, contentType); @@ -88,9 +93,17 @@ class TaskManagerTest { JobResult result = taskManager.getJobResult(jobId); assertNotNull(result); assertTrue(result.isComplete()); - assertEquals(fileId, result.getFileId()); - assertEquals(originalFileName, result.getOriginalFileName()); - assertEquals(contentType, result.getContentType()); + assertTrue(result.hasFiles()); + assertFalse(result.hasMultipleFiles()); + + var resultFiles = result.getAllResultFiles(); + assertEquals(1, resultFiles.size()); + + ResultFile resultFile = resultFiles.get(0); + assertEquals(fileId, resultFile.getFileId()); + assertEquals(originalFileName, resultFile.getFileName()); + assertEquals(contentType, resultFile.getContentType()); + assertEquals(fileSize, resultFile.getFileSize()); assertNotNull(result.getCompletedAt()); } @@ -163,8 +176,11 @@ class TaskManagerTest { } @Test - void testGetJobStats() { + void testGetJobStats() throws Exception { // Arrange + // Mock fileStorage.getFileSize for file operations + when(fileStorage.getFileSize("file-id")).thenReturn(1024L); + // 1. Create active job String activeJobId = "active-job"; taskManager.createTask(activeJobId); @@ -216,9 +232,15 @@ class TaskManagerTest { LocalDateTime oldTime = LocalDateTime.now().minusHours(1); ReflectionTestUtils.setField(oldJob, "completedAt", oldTime); ReflectionTestUtils.setField(oldJob, "complete", true); - ReflectionTestUtils.setField(oldJob, "fileId", "file-id"); - ReflectionTestUtils.setField(oldJob, "originalFileName", "test.pdf"); - ReflectionTestUtils.setField(oldJob, "contentType", "application/pdf"); + + // Create a ResultFile and set it using the new approach + ResultFile resultFile = ResultFile.builder() + .fileId("file-id") + .fileName("test.pdf") + .contentType("application/pdf") + .fileSize(1024L) + .build(); + ReflectionTestUtils.setField(oldJob, "resultFiles", java.util.List.of(resultFile)); when(fileStorage.deleteFile("file-id")).thenReturn(true); @@ -252,17 +274,17 @@ class TaskManagerTest { // Verify the executor service is shutdown // This is difficult to test directly, but we can verify it doesn't throw exceptions } - + @Test void testAddNote() { // Arrange String jobId = UUID.randomUUID().toString(); taskManager.createTask(jobId); String note = "Test note"; - + // Act boolean result = taskManager.addNote(jobId, note); - + // Assert assertTrue(result); JobResult jobResult = taskManager.getJobResult(jobId); @@ -271,16 +293,16 @@ class TaskManagerTest { assertEquals(1, jobResult.getNotes().size()); assertEquals(note, jobResult.getNotes().get(0)); } - + @Test void testAddNote_NonExistentJob() { // Arrange String jobId = "non-existent-job"; String note = "Test note"; - + // Act boolean result = taskManager.addNote(jobId, note); - + // Assert assertFalse(result); } diff --git a/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceTest.java b/app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceTest.java similarity index 95% rename from common/src/test/java/stirling/software/common/service/TempFileCleanupServiceTest.java rename to app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceTest.java index 009c00860..34c471227 100644 --- a/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceTest.java +++ b/app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceTest.java @@ -82,10 +82,10 @@ public class TempFileCleanupServiceTest { when(tempFileManagement.isStartupCleanup()).thenReturn(false); when(tempFileManagement.isCleanupSystemTemp()).thenReturn(false); when(tempFileManagement.getCleanupIntervalMinutes()).thenReturn(30L); - + // Set machineType using reflection (still needed for this field) ReflectionTestUtils.setField(cleanupService, "machineType", "Standard"); - + when(tempFileManager.getMaxAgeMillis()).thenReturn(3600000L); // 1 hour } @@ -113,30 +113,30 @@ public class TempFileCleanupServiceTest { Path ourTempFile3 = Files.createFile(customTempDir.resolve("stirling-pdf-789.tmp")); Path ourTempFile4 = Files.createFile(customTempDir.resolve("pdf-save-123-456.tmp")); Path ourTempFile5 = Files.createFile(libreOfficeTempDir.resolve("input_file.pdf")); - + // Old temporary files Path oldTempFile = Files.createFile(systemTempDir.resolve("output_old.pdf")); - + // System temp files that should be cleaned in container mode Path sysTempFile1 = Files.createFile(systemTempDir.resolve("lu123abc.tmp")); Path sysTempFile2 = Files.createFile(customTempDir.resolve("ocr_process123")); Path sysTempFile3 = Files.createFile(customTempDir.resolve("tmp_upload.tmp")); - + // Files that should be preserved Path jettyFile1 = Files.createFile(systemTempDir.resolve("jetty-123.tmp")); Path jettyFile2 = Files.createFile(systemTempDir.resolve("something-with-jetty-inside.tmp")); Path regularFile = Files.createFile(systemTempDir.resolve("important.txt")); - + // Create a nested directory with temp files Path nestedDir = Files.createDirectories(systemTempDir.resolve("nested")); Path nestedTempFile = Files.createFile(nestedDir.resolve("output_nested.pdf")); - + // Empty file (special case) Path emptyFile = Files.createFile(systemTempDir.resolve("empty.tmp")); - + // Configure mock registry to say these files aren't registered when(registry.contains(any(File.class))).thenReturn(false); - + // The set of files that will be deleted in our test Set deletedFiles = new HashSet<>(); @@ -145,31 +145,31 @@ public class TempFileCleanupServiceTest { // Mock Files.list for each directory we'll process mockedFiles.when(() -> Files.list(eq(systemTempDir))) .thenReturn(Stream.of( - ourTempFile1, ourTempFile2, oldTempFile, sysTempFile1, + ourTempFile1, ourTempFile2, oldTempFile, sysTempFile1, jettyFile1, jettyFile2, regularFile, emptyFile, nestedDir)); - + mockedFiles.when(() -> Files.list(eq(customTempDir))) .thenReturn(Stream.of(ourTempFile3, ourTempFile4, sysTempFile2, sysTempFile3)); - + mockedFiles.when(() -> Files.list(eq(libreOfficeTempDir))) .thenReturn(Stream.of(ourTempFile5)); - + mockedFiles.when(() -> Files.list(eq(nestedDir))) .thenReturn(Stream.of(nestedTempFile)); - + // Configure Files.isDirectory for each path mockedFiles.when(() -> Files.isDirectory(eq(nestedDir))).thenReturn(true); mockedFiles.when(() -> Files.isDirectory(any(Path.class))).thenReturn(false); - + // Configure Files.exists to return true for all paths mockedFiles.when(() -> Files.exists(any(Path.class))).thenReturn(true); - + // Configure Files.getLastModifiedTime to return different times based on file names mockedFiles.when(() -> Files.getLastModifiedTime(any(Path.class))) .thenAnswer(invocation -> { Path path = invocation.getArgument(0); String fileName = path.getFileName().toString(); - + // For files with "old" in the name, return a timestamp older than maxAgeMillis if (fileName.contains("old")) { return FileTime.fromMillis(System.currentTimeMillis() - 5000000); @@ -183,13 +183,13 @@ public class TempFileCleanupServiceTest { return FileTime.fromMillis(System.currentTimeMillis() - 60000); // 1 minute ago } }); - + // Configure Files.size to return different sizes based on file names mockedFiles.when(() -> Files.size(any(Path.class))) .thenAnswer(invocation -> { Path path = invocation.getArgument(0); String fileName = path.getFileName().toString(); - + // Return 0 bytes for the empty file if (fileName.equals("empty.tmp")) { return 0L; @@ -199,7 +199,7 @@ public class TempFileCleanupServiceTest { return 1024L; // 1 KB } }); - + // For deleteIfExists, track which files would be deleted mockedFiles.when(() -> Files.deleteIfExists(any(Path.class))) .thenAnswer(invocation -> { @@ -207,28 +207,28 @@ public class TempFileCleanupServiceTest { deletedFiles.add(path); return true; }); - + // Act - set containerMode to false for this test invokeCleanupDirectoryStreaming(systemTempDir, false, 0, 3600000); invokeCleanupDirectoryStreaming(customTempDir, false, 0, 3600000); invokeCleanupDirectoryStreaming(libreOfficeTempDir, false, 0, 3600000); - + // Assert - Only old temp files and empty files should be deleted assertTrue(deletedFiles.contains(oldTempFile), "Old temp file should be deleted"); assertTrue(deletedFiles.contains(emptyFile), "Empty file should be deleted"); - + // Regular temp files should not be deleted because they're too new assertFalse(deletedFiles.contains(ourTempFile1), "Recent temp file should be preserved"); assertFalse(deletedFiles.contains(ourTempFile2), "Recent temp file should be preserved"); assertFalse(deletedFiles.contains(ourTempFile3), "Recent temp file should be preserved"); assertFalse(deletedFiles.contains(ourTempFile4), "Recent temp file should be preserved"); assertFalse(deletedFiles.contains(ourTempFile5), "Recent temp file should be preserved"); - + // System temp files should not be deleted in non-container mode assertFalse(deletedFiles.contains(sysTempFile1), "System temp file should be preserved in non-container mode"); assertFalse(deletedFiles.contains(sysTempFile2), "System temp file should be preserved in non-container mode"); assertFalse(deletedFiles.contains(sysTempFile3), "System temp file should be preserved in non-container mode"); - + // Jetty files and regular files should never be deleted assertFalse(deletedFiles.contains(jettyFile1), "Jetty file should be preserved"); assertFalse(deletedFiles.contains(jettyFile2), "File with jetty in name should be preserved"); @@ -242,10 +242,10 @@ public class TempFileCleanupServiceTest { Path ourTempFile = Files.createFile(systemTempDir.resolve("output_123.pdf")); Path sysTempFile = Files.createFile(systemTempDir.resolve("lu123abc.tmp")); Path regularFile = Files.createFile(systemTempDir.resolve("important.txt")); - + // Configure mock registry to say these files aren't registered when(registry.contains(any(File.class))).thenReturn(false); - + // The set of files that will be deleted in our test Set deletedFiles = new HashSet<>(); @@ -254,21 +254,21 @@ public class TempFileCleanupServiceTest { // Mock Files.list for systemTempDir mockedFiles.when(() -> Files.list(eq(systemTempDir))) .thenReturn(Stream.of(ourTempFile, sysTempFile, regularFile)); - + // Configure Files.isDirectory mockedFiles.when(() -> Files.isDirectory(any(Path.class))).thenReturn(false); - + // Configure Files.exists mockedFiles.when(() -> Files.exists(any(Path.class))).thenReturn(true); - + // Configure Files.getLastModifiedTime to return recent timestamps mockedFiles.when(() -> Files.getLastModifiedTime(any(Path.class))) .thenReturn(FileTime.fromMillis(System.currentTimeMillis() - 60000)); // 1 minute ago - + // Configure Files.size to return normal size mockedFiles.when(() -> Files.size(any(Path.class))) .thenReturn(1024L); // 1 KB - + // For deleteIfExists, track which files would be deleted mockedFiles.when(() -> Files.deleteIfExists(any(Path.class))) .thenAnswer(invocation -> { @@ -276,10 +276,10 @@ public class TempFileCleanupServiceTest { deletedFiles.add(path); return true; }); - + // Act - set containerMode to true and maxAgeMillis to 0 for container startup cleanup invokeCleanupDirectoryStreaming(systemTempDir, true, 0, 0); - + // Assert - In container mode, both our temp files and system temp files should be deleted // regardless of age (when maxAgeMillis is 0) assertTrue(deletedFiles.contains(ourTempFile), "Our temp file should be deleted in container mode"); @@ -293,10 +293,10 @@ public class TempFileCleanupServiceTest { // Arrange - Create an empty file Path emptyFile = Files.createFile(systemTempDir.resolve("empty.tmp")); Path recentEmptyFile = Files.createFile(systemTempDir.resolve("recent_empty.tmp")); - + // Configure mock registry to say these files aren't registered when(registry.contains(any(File.class))).thenReturn(false); - + // The set of files that will be deleted in our test Set deletedFiles = new HashSet<>(); @@ -305,19 +305,19 @@ public class TempFileCleanupServiceTest { // Mock Files.list for systemTempDir mockedFiles.when(() -> Files.list(eq(systemTempDir))) .thenReturn(Stream.of(emptyFile, recentEmptyFile)); - + // Configure Files.isDirectory mockedFiles.when(() -> Files.isDirectory(any(Path.class))).thenReturn(false); - + // Configure Files.exists mockedFiles.when(() -> Files.exists(any(Path.class))).thenReturn(true); - + // Configure Files.getLastModifiedTime to return different times based on file names mockedFiles.when(() -> Files.getLastModifiedTime(any(Path.class))) .thenAnswer(invocation -> { Path path = invocation.getArgument(0); String fileName = path.getFileName().toString(); - + if (fileName.equals("empty.tmp")) { // More than 5 minutes old return FileTime.fromMillis(System.currentTimeMillis() - 6 * 60 * 1000); @@ -326,11 +326,11 @@ public class TempFileCleanupServiceTest { return FileTime.fromMillis(System.currentTimeMillis() - 2 * 60 * 1000); } }); - + // Configure Files.size to return 0 for empty files mockedFiles.when(() -> Files.size(any(Path.class))) .thenReturn(0L); - + // For deleteIfExists, track which files would be deleted mockedFiles.when(() -> Files.deleteIfExists(any(Path.class))) .thenAnswer(invocation -> { @@ -338,14 +338,14 @@ public class TempFileCleanupServiceTest { deletedFiles.add(path); return true; }); - + // Act invokeCleanupDirectoryStreaming(systemTempDir, false, 0, 3600000); - + // Assert - assertTrue(deletedFiles.contains(emptyFile), + assertTrue(deletedFiles.contains(emptyFile), "Empty file older than 5 minutes should be deleted"); - assertFalse(deletedFiles.contains(recentEmptyFile), + assertFalse(deletedFiles.contains(recentEmptyFile), "Empty file newer than 5 minutes should not be deleted"); } } @@ -356,14 +356,14 @@ public class TempFileCleanupServiceTest { Path dir1 = Files.createDirectories(systemTempDir.resolve("dir1")); Path dir2 = Files.createDirectories(dir1.resolve("dir2")); Path dir3 = Files.createDirectories(dir2.resolve("dir3")); - + Path tempFile1 = Files.createFile(dir1.resolve("output_1.pdf")); Path tempFile2 = Files.createFile(dir2.resolve("output_2.pdf")); Path tempFile3 = Files.createFile(dir3.resolve("output_old_3.pdf")); - + // Configure mock registry to say these files aren't registered when(registry.contains(any(File.class))).thenReturn(false); - + // The set of files that will be deleted in our test Set deletedFiles = new HashSet<>(); @@ -372,16 +372,16 @@ public class TempFileCleanupServiceTest { // Mock Files.list for each directory mockedFiles.when(() -> Files.list(eq(systemTempDir))) .thenReturn(Stream.of(dir1)); - + mockedFiles.when(() -> Files.list(eq(dir1))) .thenReturn(Stream.of(tempFile1, dir2)); - + mockedFiles.when(() -> Files.list(eq(dir2))) .thenReturn(Stream.of(tempFile2, dir3)); - + mockedFiles.when(() -> Files.list(eq(dir3))) .thenReturn(Stream.of(tempFile3)); - + // Configure Files.isDirectory for each path mockedFiles.when(() -> Files.isDirectory(eq(dir1))).thenReturn(true); mockedFiles.when(() -> Files.isDirectory(eq(dir2))).thenReturn(true); @@ -389,16 +389,16 @@ public class TempFileCleanupServiceTest { mockedFiles.when(() -> Files.isDirectory(eq(tempFile1))).thenReturn(false); mockedFiles.when(() -> Files.isDirectory(eq(tempFile2))).thenReturn(false); mockedFiles.when(() -> Files.isDirectory(eq(tempFile3))).thenReturn(false); - + // Configure Files.exists to return true for all paths mockedFiles.when(() -> Files.exists(any(Path.class))).thenReturn(true); - + // Configure Files.getLastModifiedTime to return different times based on file names mockedFiles.when(() -> Files.getLastModifiedTime(any(Path.class))) .thenAnswer(invocation -> { Path path = invocation.getArgument(0); String fileName = path.getFileName().toString(); - + if (fileName.contains("old")) { // Old file return FileTime.fromMillis(System.currentTimeMillis() - 5000000); @@ -407,11 +407,11 @@ public class TempFileCleanupServiceTest { return FileTime.fromMillis(System.currentTimeMillis() - 60000); } }); - + // Configure Files.size to return normal size mockedFiles.when(() -> Files.size(any(Path.class))) .thenReturn(1024L); - + // For deleteIfExists, track which files would be deleted mockedFiles.when(() -> Files.deleteIfExists(any(Path.class))) .thenAnswer(invocation -> { @@ -419,14 +419,14 @@ public class TempFileCleanupServiceTest { deletedFiles.add(path); return true; }); - + // Act invokeCleanupDirectoryStreaming(systemTempDir, false, 0, 3600000); - + // Debug - print what was deleted System.out.println("Deleted files: " + deletedFiles); System.out.println("Looking for: " + tempFile3); - + // Assert assertFalse(deletedFiles.contains(tempFile1), "Recent temp file should be preserved"); assertFalse(deletedFiles.contains(tempFile2), "Recent temp file should be preserved"); @@ -437,28 +437,28 @@ public class TempFileCleanupServiceTest { /** * Helper method to invoke the private cleanupDirectoryStreaming method using reflection */ - private void invokeCleanupDirectoryStreaming(Path directory, boolean containerMode, int depth, long maxAgeMillis) + private void invokeCleanupDirectoryStreaming(Path directory, boolean containerMode, int depth, long maxAgeMillis) throws IOException { try { // Create a consumer that tracks deleted files AtomicInteger deleteCount = new AtomicInteger(0); Consumer deleteCallback = path -> deleteCount.incrementAndGet(); - + // Get the method with updated signature var method = TempFileCleanupService.class.getDeclaredMethod( - "cleanupDirectoryStreaming", + "cleanupDirectoryStreaming", Path.class, boolean.class, int.class, long.class, boolean.class, Consumer.class); method.setAccessible(true); - + // Invoke the method with appropriate parameters method.invoke(cleanupService, directory, containerMode, depth, maxAgeMillis, false, deleteCallback); } catch (Exception e) { throw new RuntimeException("Error invoking cleanupDirectoryStreaming", e); } } - + // Matcher for exact path equality private static Path eq(Path path) { return argThat(arg -> arg != null && arg.equals(path)); } -} \ No newline at end of file +} diff --git a/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java b/app/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java rename to app/common/src/test/java/stirling/software/common/util/CheckProgramInstallTest.java diff --git a/common/src/test/java/stirling/software/common/util/CustomHtmlSanitizerTest.java b/app/common/src/test/java/stirling/software/common/util/CustomHtmlSanitizerTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/CustomHtmlSanitizerTest.java rename to app/common/src/test/java/stirling/software/common/util/CustomHtmlSanitizerTest.java diff --git a/common/src/test/java/stirling/software/common/util/EmlToPdfTest.java b/app/common/src/test/java/stirling/software/common/util/EmlToPdfTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/EmlToPdfTest.java rename to app/common/src/test/java/stirling/software/common/util/EmlToPdfTest.java diff --git a/common/src/test/java/stirling/software/common/util/ErrorUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/ErrorUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/ErrorUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/ErrorUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/FileInfoTest.java b/app/common/src/test/java/stirling/software/common/util/FileInfoTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/FileInfoTest.java rename to app/common/src/test/java/stirling/software/common/util/FileInfoTest.java diff --git a/common/src/test/java/stirling/software/common/util/FileMonitorTest.java b/app/common/src/test/java/stirling/software/common/util/FileMonitorTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/FileMonitorTest.java rename to app/common/src/test/java/stirling/software/common/util/FileMonitorTest.java diff --git a/common/src/test/java/stirling/software/common/util/FileToPdfTest.java b/app/common/src/test/java/stirling/software/common/util/FileToPdfTest.java similarity index 99% rename from common/src/test/java/stirling/software/common/util/FileToPdfTest.java rename to app/common/src/test/java/stirling/software/common/util/FileToPdfTest.java index f1df1cf25..96def4fa3 100644 --- a/common/src/test/java/stirling/software/common/util/FileToPdfTest.java +++ b/app/common/src/test/java/stirling/software/common/util/FileToPdfTest.java @@ -27,7 +27,7 @@ public class FileToPdfTest { String fileName = "test.html"; // Sample file name indicating an HTML file boolean disableSanitize = false; // Flag to control sanitization TempFileManager tempFileManager = mock(TempFileManager.class); // Mock TempFileManager - + // Mock the temp file creation to return real temp files try { when(tempFileManager.createTempFile(anyString())) diff --git a/common/src/test/java/stirling/software/common/util/GeneralUtilsAdditionalTest.java b/app/common/src/test/java/stirling/software/common/util/GeneralUtilsAdditionalTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/GeneralUtilsAdditionalTest.java rename to app/common/src/test/java/stirling/software/common/util/GeneralUtilsAdditionalTest.java diff --git a/common/src/test/java/stirling/software/common/util/GeneralUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/GeneralUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/GeneralUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/GeneralUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/ImageProcessingUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/ImageProcessingUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/ImageProcessingUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/ImageProcessingUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/PDFToFileTest.java b/app/common/src/test/java/stirling/software/common/util/PDFToFileTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/PDFToFileTest.java rename to app/common/src/test/java/stirling/software/common/util/PDFToFileTest.java diff --git a/common/src/test/java/stirling/software/common/util/PdfUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/PdfUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/PdfUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/PdfUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/ProcessExecutorTest.java b/app/common/src/test/java/stirling/software/common/util/ProcessExecutorTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/ProcessExecutorTest.java rename to app/common/src/test/java/stirling/software/common/util/ProcessExecutorTest.java diff --git a/common/src/test/java/stirling/software/common/util/PropertyConfigsTest.java b/app/common/src/test/java/stirling/software/common/util/PropertyConfigsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/PropertyConfigsTest.java rename to app/common/src/test/java/stirling/software/common/util/PropertyConfigsTest.java diff --git a/common/src/test/java/stirling/software/common/util/ProviderUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/ProviderUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/ProviderUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/ProviderUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/RequestUriUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/RequestUriUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/RequestUriUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/RequestUriUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/SpringContextHolderTest.java b/app/common/src/test/java/stirling/software/common/util/SpringContextHolderTest.java similarity index 96% rename from common/src/test/java/stirling/software/common/util/SpringContextHolderTest.java rename to app/common/src/test/java/stirling/software/common/util/SpringContextHolderTest.java index 9aa1aadf1..fe3fea769 100644 --- a/common/src/test/java/stirling/software/common/util/SpringContextHolderTest.java +++ b/app/common/src/test/java/stirling/software/common/util/SpringContextHolderTest.java @@ -22,7 +22,7 @@ class SpringContextHolderTest { void testSetApplicationContext() { // Act contextHolder.setApplicationContext(mockApplicationContext); - + // Assert assertTrue(SpringContextHolder.isInitialized()); } @@ -33,10 +33,10 @@ class SpringContextHolderTest { contextHolder.setApplicationContext(mockApplicationContext); TestBean expectedBean = new TestBean(); when(mockApplicationContext.getBean(TestBean.class)).thenReturn(expectedBean); - + // Act TestBean result = SpringContextHolder.getBean(TestBean.class); - + // Assert assertSame(expectedBean, result); verify(mockApplicationContext).getBean(TestBean.class); @@ -46,10 +46,10 @@ class SpringContextHolderTest { @Test void testGetBean_ApplicationContextNotSet() { // Don't set application context - + // Act TestBean result = SpringContextHolder.getBean(TestBean.class); - + // Assert assertNull(result); } @@ -59,10 +59,10 @@ class SpringContextHolderTest { // Arrange contextHolder.setApplicationContext(mockApplicationContext); when(mockApplicationContext.getBean(TestBean.class)).thenThrow(new org.springframework.beans.BeansException("Bean not found") {}); - + // Act TestBean result = SpringContextHolder.getBean(TestBean.class); - + // Assert assertNull(result); } @@ -70,4 +70,4 @@ class SpringContextHolderTest { // Simple test class private static class TestBean { } -} \ No newline at end of file +} diff --git a/common/src/test/java/stirling/software/common/util/UIScalingTest.java b/app/common/src/test/java/stirling/software/common/util/UIScalingTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/UIScalingTest.java rename to app/common/src/test/java/stirling/software/common/util/UIScalingTest.java diff --git a/common/src/test/java/stirling/software/common/util/UrlUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/UrlUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/UrlUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/UrlUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/WebResponseUtilsTest.java b/app/common/src/test/java/stirling/software/common/util/WebResponseUtilsTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/WebResponseUtilsTest.java rename to app/common/src/test/java/stirling/software/common/util/WebResponseUtilsTest.java diff --git a/common/src/test/java/stirling/software/common/util/misc/CustomColorReplaceStrategyTest.java b/app/common/src/test/java/stirling/software/common/util/misc/CustomColorReplaceStrategyTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/misc/CustomColorReplaceStrategyTest.java rename to app/common/src/test/java/stirling/software/common/util/misc/CustomColorReplaceStrategyTest.java diff --git a/common/src/test/java/stirling/software/common/util/misc/HighContrastColorReplaceDeciderTest.java b/app/common/src/test/java/stirling/software/common/util/misc/HighContrastColorReplaceDeciderTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/misc/HighContrastColorReplaceDeciderTest.java rename to app/common/src/test/java/stirling/software/common/util/misc/HighContrastColorReplaceDeciderTest.java diff --git a/common/src/test/java/stirling/software/common/util/misc/InvertFullColorStrategyTest.java b/app/common/src/test/java/stirling/software/common/util/misc/InvertFullColorStrategyTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/misc/InvertFullColorStrategyTest.java rename to app/common/src/test/java/stirling/software/common/util/misc/InvertFullColorStrategyTest.java diff --git a/common/src/test/java/stirling/software/common/util/misc/PdfTextStripperCustomTest.java b/app/common/src/test/java/stirling/software/common/util/misc/PdfTextStripperCustomTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/misc/PdfTextStripperCustomTest.java rename to app/common/src/test/java/stirling/software/common/util/misc/PdfTextStripperCustomTest.java diff --git a/common/src/test/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategyTest.java b/app/common/src/test/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategyTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategyTest.java rename to app/common/src/test/java/stirling/software/common/util/misc/ReplaceAndInvertColorStrategyTest.java diff --git a/common/src/test/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditorTest.java b/app/common/src/test/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditorTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditorTest.java rename to app/common/src/test/java/stirling/software/common/util/propertyeditor/StringToArrayListPropertyEditorTest.java diff --git a/common/src/test/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditorTest.java b/app/common/src/test/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditorTest.java similarity index 100% rename from common/src/test/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditorTest.java rename to app/common/src/test/java/stirling/software/common/util/propertyeditor/StringToMapPropertyEditorTest.java diff --git a/common/src/test/resources/example.pdf b/app/common/src/test/resources/example.pdf similarity index 100% rename from common/src/test/resources/example.pdf rename to app/common/src/test/resources/example.pdf diff --git a/stirling-pdf/.gitignore b/app/core/.gitignore similarity index 98% rename from stirling-pdf/.gitignore rename to app/core/.gitignore index 3861a89a3..f85be51d5 100644 --- a/stirling-pdf/.gitignore +++ b/app/core/.gitignore @@ -124,7 +124,7 @@ SwaggerDoc.json *.rar *.db /build/* -/stirling-pdf/build/* +/app/core/build/* # Byte-compiled / optimized / DLL files __pycache__/ @@ -193,4 +193,4 @@ id_ed25519.pub **/jcef-bundle/ # node_modules -node_modules/ \ No newline at end of file +node_modules/ diff --git a/stirling-pdf/build.gradle b/app/core/build.gradle similarity index 96% rename from stirling-pdf/build.gradle rename to app/core/build.gradle index a97d04808..0974a0577 100644 --- a/stirling-pdf/build.gradle +++ b/app/core/build.gradle @@ -62,7 +62,7 @@ dependencies { exclude group: 'com.google.code.gson', module: 'gson' } implementation 'org.apache.pdfbox:jbig2-imageio:3.0.4' - implementation 'com.opencsv:opencsv:5.11.1' // https://mvnrepository.com/artifact/com.opencsv/opencsv + implementation 'com.opencsv:opencsv:5.11.2' // https://mvnrepository.com/artifact/com.opencsv/opencsv // Batik implementation 'org.apache.xmlgraphics:batik-all:1.19' @@ -146,5 +146,10 @@ bootJar { } } +// Configure main class for Spring Boot +springBoot { + mainClass = 'stirling.software.SPDF.SPDFApplication' +} + bootJar.dependsOn ':common:jar' bootJar.dependsOn ':proprietary:jar' diff --git a/stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/CMSProcessableInputStream.java b/app/core/src/main/java/org/apache/pdfbox/examples/signature/CMSProcessableInputStream.java similarity index 100% rename from stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/CMSProcessableInputStream.java rename to app/core/src/main/java/org/apache/pdfbox/examples/signature/CMSProcessableInputStream.java diff --git a/stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java b/app/core/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java similarity index 100% rename from stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java rename to app/core/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java diff --git a/stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/TSAClient.java b/app/core/src/main/java/org/apache/pdfbox/examples/signature/TSAClient.java similarity index 100% rename from stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/TSAClient.java rename to app/core/src/main/java/org/apache/pdfbox/examples/signature/TSAClient.java diff --git a/stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/ValidationTimeStamp.java b/app/core/src/main/java/org/apache/pdfbox/examples/signature/ValidationTimeStamp.java similarity index 100% rename from stirling-pdf/src/main/java/org/apache/pdfbox/examples/signature/ValidationTimeStamp.java rename to app/core/src/main/java/org/apache/pdfbox/examples/signature/ValidationTimeStamp.java diff --git a/stirling-pdf/src/main/java/org/apache/pdfbox/examples/util/ConnectedInputStream.java b/app/core/src/main/java/org/apache/pdfbox/examples/util/ConnectedInputStream.java similarity index 100% rename from stirling-pdf/src/main/java/org/apache/pdfbox/examples/util/ConnectedInputStream.java rename to app/core/src/main/java/org/apache/pdfbox/examples/util/ConnectedInputStream.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java b/app/core/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java rename to app/core/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/LibreOfficeListener.java b/app/core/src/main/java/stirling/software/SPDF/LibreOfficeListener.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/LibreOfficeListener.java rename to app/core/src/main/java/stirling/software/SPDF/LibreOfficeListener.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/SPDFApplication.java b/app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/SPDFApplication.java rename to app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/UI/WebBrowser.java b/app/core/src/main/java/stirling/software/SPDF/UI/WebBrowser.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/UI/WebBrowser.java rename to app/core/src/main/java/stirling/software/SPDF/UI/WebBrowser.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/UI/impl/DesktopBrowser.java b/app/core/src/main/java/stirling/software/SPDF/UI/impl/DesktopBrowser.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/UI/impl/DesktopBrowser.java rename to app/core/src/main/java/stirling/software/SPDF/UI/impl/DesktopBrowser.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/UI/impl/LoadingWindow.java b/app/core/src/main/java/stirling/software/SPDF/UI/impl/LoadingWindow.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/UI/impl/LoadingWindow.java rename to app/core/src/main/java/stirling/software/SPDF/UI/impl/LoadingWindow.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/AppUpdateService.java b/app/core/src/main/java/stirling/software/SPDF/config/AppUpdateService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/AppUpdateService.java rename to app/core/src/main/java/stirling/software/SPDF/config/AppUpdateService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java b/app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java rename to app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java index eb9f2be33..088c0c0bf 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/CleanUrlInterceptor.java @@ -29,7 +29,8 @@ public class CleanUrlInterceptor implements HandlerInterceptor { "type", "principal", "startDate", - "endDate"); + "endDate", + "async"); @Override public boolean preHandle( diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java similarity index 54% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java rename to app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index 361eeace3..e8ac284a8 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -21,6 +21,8 @@ public class EndpointConfiguration { private final ApplicationProperties applicationProperties; private Map endpointStatuses = new ConcurrentHashMap<>(); private Map> endpointGroups = new ConcurrentHashMap<>(); + private Set disabledGroups = new HashSet<>(); + private Map> endpointAlternatives = new ConcurrentHashMap<>(); private final boolean runningProOrHigher; public EndpointConfiguration( @@ -34,13 +36,14 @@ public class EndpointConfiguration { public void enableEndpoint(String endpoint) { endpointStatuses.put(endpoint, true); + log.debug("Enabled endpoint: {}", endpoint); } public void disableEndpoint(String endpoint) { - if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) { - log.debug("Disabling {}", endpoint); - endpointStatuses.put(endpoint, false); + if (!Boolean.FALSE.equals(endpointStatuses.get(endpoint))) { + log.debug("Disabling endpoint: {}", endpoint); } + endpointStatuses.put(endpoint, false); } public Map getEndpointStatuses() { @@ -48,25 +51,96 @@ public class EndpointConfiguration { } public boolean isEndpointEnabled(String endpoint) { + String original = endpoint; if (endpoint.startsWith("/")) { endpoint = endpoint.substring(1); } - return endpointStatuses.getOrDefault(endpoint, true); - } - public boolean isGroupEnabled(String group) { - Set endpoints = endpointGroups.get(group); - if (endpoints == null || endpoints.isEmpty()) { - log.debug("Group '{}' does not exist or has no endpoints", group); + // Rule 1: Explicit flag wins - if disabled via disableEndpoint(), stay disabled + Boolean explicitStatus = endpointStatuses.get(endpoint); + if (Boolean.FALSE.equals(explicitStatus)) { + log.debug("isEndpointEnabled('{}') -> false (explicitly disabled)", original); return false; } - for (String endpoint : endpoints) { - if (!isEndpointEnabled(endpoint)) { + // Rule 2: Functional-group override - check if endpoint belongs to any disabled functional + // group + for (String group : endpointGroups.keySet()) { + if (disabledGroups.contains(group) && endpointGroups.get(group).contains(endpoint)) { + // Skip tool groups (qpdf, OCRmyPDF, Ghostscript, LibreOffice, etc.) + if (!isToolGroup(group)) { + log.debug( + "isEndpointEnabled('{}') -> false (functional group '{}' disabled)", + original, + group); + return false; + } + } + } + + // Rule 3: Tool-group fallback - check if at least one alternative tool group is enabled + Set alternatives = endpointAlternatives.get(endpoint); + if (alternatives != null && !alternatives.isEmpty()) { + boolean hasEnabledToolGroup = + alternatives.stream() + .anyMatch(toolGroup -> !disabledGroups.contains(toolGroup)); + log.debug( + "isEndpointEnabled('{}') -> {} (tool groups check)", + original, + hasEnabledToolGroup); + return hasEnabledToolGroup; + } + + // Rule 4: Single-dependency check - if no alternatives defined, check if endpoint belongs + // to any disabled tool groups + for (String group : endpointGroups.keySet()) { + if (isToolGroup(group) + && disabledGroups.contains(group) + && endpointGroups.get(group).contains(endpoint)) { + log.debug( + "isEndpointEnabled('{}') -> false (single tool group '{}' disabled, no alternatives)", + original, + group); return false; } } + // Default: enabled if not explicitly disabled + boolean enabled = !Boolean.FALSE.equals(explicitStatus); + log.debug("isEndpointEnabled('{}') -> {} (default)", original, enabled); + return enabled; + } + + public boolean isGroupEnabled(String group) { + // Rule 1: If group is explicitly disabled, it stays disabled + if (disabledGroups.contains(group)) { + log.debug("isGroupEnabled('{}') -> false (explicitly disabled)", group); + return false; + } + + Set endpoints = endpointGroups.get(group); + if (endpoints == null || endpoints.isEmpty()) { + log.debug("isGroupEnabled('{}') -> false (no endpoints)", group); + return false; + } + + // Rule 2: For functional groups, check if all endpoints are enabled + // Rule 3: For tool groups, they're enabled unless explicitly disabled (handled above) + if (isToolGroup(group)) { + log.debug("isGroupEnabled('{}') -> true (tool group not disabled)", group); + return true; + } + + // For functional groups, check each endpoint individually + for (String endpoint : endpoints) { + if (!isEndpointEnabledDirectly(endpoint)) { + log.debug( + "isGroupEnabled('{}') -> false (endpoint '{}' disabled)", group, endpoint); + return false; + } + } + + log.debug("isGroupEnabled('{}') -> true (all endpoints enabled)", group); return true; } @@ -74,38 +148,84 @@ public class EndpointConfiguration { endpointGroups.computeIfAbsent(group, k -> new HashSet<>()).add(endpoint); } - public void enableGroup(String group) { - Set endpoints = endpointGroups.get(group); - if (endpoints != null) { - for (String endpoint : endpoints) { - enableEndpoint(endpoint); - } - } + public void addEndpointAlternative(String endpoint, String toolGroup) { + endpointAlternatives.computeIfAbsent(endpoint, k -> new HashSet<>()).add(toolGroup); } public void disableGroup(String group) { - Set endpoints = endpointGroups.get(group); - if (endpoints != null) { - for (String endpoint : endpoints) { - disableEndpoint(endpoint); + if (disabledGroups.add(group)) { + if (isToolGroup(group)) { + log.debug( + "Disabling tool group: {} (endpoints with alternatives remain available)", + group); + } else { + log.debug( + "Disabling functional group: {} (will disable all endpoints in group)", + group); + } + } + // Only cascade to endpoints for *functional* groups + if (!isToolGroup(group)) { + Set endpoints = endpointGroups.get(group); + if (endpoints != null) { + endpoints.forEach(this::disableEndpoint); } } } + public void enableGroup(String group) { + if (disabledGroups.remove(group)) { + log.debug("Enabling group: {}", group); + } + Set endpoints = endpointGroups.get(group); + if (endpoints != null) { + endpoints.forEach(this::enableEndpoint); + } + } + + public Set getDisabledGroups() { + return new HashSet<>(disabledGroups); + } + public void logDisabledEndpointsSummary() { - List disabledList = - endpointStatuses.entrySet().stream() - .filter(entry -> !entry.getValue()) // only get disabled endpoints (value - // is false) - .map(Map.Entry::getKey) + // Get all unique endpoints across all groups + Set allEndpoints = + endpointGroups.values().stream() + .flatMap(Set::stream) + .collect(java.util.stream.Collectors.toSet()); + + // Check which endpoints are actually disabled (functionally unavailable) + List functionallyDisabledEndpoints = + allEndpoints.stream() + .filter(endpoint -> !isEndpointEnabled(endpoint)) .sorted() .toList(); - if (!disabledList.isEmpty()) { + // Separate tool groups from functional groups + List disabledToolGroups = + disabledGroups.stream().filter(this::isToolGroup).sorted().toList(); + + List disabledFunctionalGroups = + disabledGroups.stream().filter(group -> !isToolGroup(group)).sorted().toList(); + + if (!disabledToolGroups.isEmpty()) { + log.info( + "Disabled tool groups: {} (endpoints may have alternative implementations)", + String.join(", ", disabledToolGroups)); + } + + if (!disabledFunctionalGroups.isEmpty()) { + log.info("Disabled functional groups: {}", String.join(", ", disabledFunctionalGroups)); + } + + if (!functionallyDisabledEndpoints.isEmpty()) { log.info( "Total disabled endpoints: {}. Disabled endpoints: {}", - disabledList.size(), - String.join(", ", disabledList)); + functionallyDisabledEndpoints.size(), + String.join(", ", functionallyDisabledEndpoints)); + } else if (!disabledToolGroups.isEmpty()) { + log.info( + "No endpoints disabled despite missing tools - fallback implementations available"); } } @@ -212,8 +332,6 @@ public class EndpointConfiguration { // Unoconvert addEndpointToGroup("Unoconvert", "file-to-pdf"); - addEndpointToGroup("tesseract", "ocr-pdf"); - // Java addEndpointToGroup("Java", "merge-pdfs"); addEndpointToGroup("Java", "remove-pages"); @@ -254,6 +372,7 @@ public class EndpointConfiguration { addEndpointToGroup("Java", "remove-image-pdf"); addEndpointToGroup("Java", "pdf-to-markdown"); addEndpointToGroup("Java", "add-attachments"); + addEndpointToGroup("Java", "compress-pdf"); // Javascript addEndpointToGroup("Javascript", "pdf-organizer"); @@ -261,8 +380,42 @@ public class EndpointConfiguration { addEndpointToGroup("Javascript", "compare"); addEndpointToGroup("Javascript", "adjust-contrast"); - // qpdf dependent endpoints + /* qpdf */ addEndpointToGroup("qpdf", "repair"); + addEndpointToGroup("qpdf", "compress-pdf"); + + /* Ghostscript */ + addEndpointToGroup("Ghostscript", "repair"); + addEndpointToGroup("Ghostscript", "compress-pdf"); + + /* tesseract */ + addEndpointToGroup("tesseract", "ocr-pdf"); + + /* OCRmyPDF */ + addEndpointToGroup("OCRmyPDF", "ocr-pdf"); + + // Multi-tool endpoints - endpoints that can be handled by multiple tools + addEndpointAlternative("repair", "qpdf"); + addEndpointAlternative("repair", "Ghostscript"); + addEndpointAlternative("compress-pdf", "qpdf"); + addEndpointAlternative("compress-pdf", "Ghostscript"); + addEndpointAlternative("compress-pdf", "Java"); + addEndpointAlternative("ocr-pdf", "tesseract"); + addEndpointAlternative("ocr-pdf", "OCRmyPDF"); + + // file-to-pdf has multiple implementations + addEndpointAlternative("file-to-pdf", "LibreOffice"); + addEndpointAlternative("file-to-pdf", "Python"); + addEndpointAlternative("file-to-pdf", "Unoconvert"); + + // pdf-to-html and pdf-to-markdown can use either LibreOffice or Pdftohtml + addEndpointAlternative("pdf-to-html", "LibreOffice"); + addEndpointAlternative("pdf-to-html", "Pdftohtml"); + addEndpointAlternative("pdf-to-markdown", "Pdftohtml"); + + // markdown-to-pdf can use either Weasyprint or Java + addEndpointAlternative("markdown-to-pdf", "Weasyprint"); + addEndpointAlternative("markdown-to-pdf", "Java"); // Weasyprint dependent endpoints addEndpointToGroup("Weasyprint", "html-to-pdf"); @@ -304,4 +457,43 @@ public class EndpointConfiguration { public Set getEndpointsForGroup(String group) { return endpointGroups.getOrDefault(group, new HashSet<>()); } + + private boolean isToolGroup(String group) { + return "qpdf".equals(group) + || "OCRmyPDF".equals(group) + || "Ghostscript".equals(group) + || "LibreOffice".equals(group) + || "tesseract".equals(group) + || "CLI".equals(group) + || "Python".equals(group) + || "OpenCV".equals(group) + || "Unoconvert".equals(group) + || "Java".equals(group) + || "Javascript".equals(group) + || "Weasyprint".equals(group) + || "Pdftohtml".equals(group); + } + + private boolean isEndpointEnabledDirectly(String endpoint) { + if (endpoint.startsWith("/")) { + endpoint = endpoint.substring(1); + } + + // Check explicit disable flag + Boolean explicitStatus = endpointStatuses.get(endpoint); + if (Boolean.FALSE.equals(explicitStatus)) { + return false; + } + + // Check if endpoint belongs to any disabled functional group + for (String group : endpointGroups.keySet()) { + if (disabledGroups.contains(group) && endpointGroups.get(group).contains(endpoint)) { + if (!isToolGroup(group)) { + return false; + } + } + } + + return true; + } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointInspector.java b/app/core/src/main/java/stirling/software/SPDF/config/EndpointInspector.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointInspector.java rename to app/core/src/main/java/stirling/software/SPDF/config/EndpointInspector.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java b/app/core/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java rename to app/core/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java similarity index 96% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java rename to app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java index 7dd6d2b3b..6d857c679 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java @@ -34,6 +34,8 @@ public class ExternalAppDepConfig { new HashMap<>() { { + put("gs", List.of("Ghostscript")); + put("ocrmypdf", List.of("OCRmyPDF")); put("soffice", List.of("LibreOffice")); put(weasyprintPath, List.of("Weasyprint")); put("pdftohtml", List.of("Pdftohtml")); @@ -109,6 +111,8 @@ public class ExternalAppDepConfig { @PostConstruct public void checkDependencies() { // Check core dependencies + checkDependencyAndDisableGroup("gs"); + checkDependencyAndDisableGroup("ocrmypdf"); checkDependencyAndDisableGroup("tesseract"); checkDependencyAndDisableGroup("soffice"); checkDependencyAndDisableGroup("qpdf"); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/InitialSetup.java b/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/InitialSetup.java rename to app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java b/app/core/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java rename to app/core/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/LogbackPropertyLoader.java b/app/core/src/main/java/stirling/software/SPDF/config/LogbackPropertyLoader.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/LogbackPropertyLoader.java rename to app/core/src/main/java/stirling/software/SPDF/config/LogbackPropertyLoader.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/MetricsConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/MetricsConfig.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/MetricsConfig.java rename to app/core/src/main/java/stirling/software/SPDF/config/MetricsConfig.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/MetricsFilter.java b/app/core/src/main/java/stirling/software/SPDF/config/MetricsFilter.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/MetricsFilter.java rename to app/core/src/main/java/stirling/software/SPDF/config/MetricsFilter.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java rename to app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/StartupApplicationListener.java b/app/core/src/main/java/stirling/software/SPDF/config/StartupApplicationListener.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/StartupApplicationListener.java rename to app/core/src/main/java/stirling/software/SPDF/config/StartupApplicationListener.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/TauriProcessMonitor.java b/app/core/src/main/java/stirling/software/SPDF/config/TauriProcessMonitor.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/TauriProcessMonitor.java rename to app/core/src/main/java/stirling/software/SPDF/config/TauriProcessMonitor.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java similarity index 89% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java rename to app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java index efb024e89..31047d209 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java @@ -28,8 +28,6 @@ public class WebMvcConfig implements WebMvcConfigurer { registry.addResourceHandler("/**") .addResourceLocations( "file:" + InstallationPathConfig.getStaticPath(), "classpath:/static/"); - registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/"); - registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/"); // .setCachePeriod(0); // Optional: disable caching } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionFilter.java b/app/core/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionFilter.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionFilter.java rename to app/core/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionFilter.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionManager.java b/app/core/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionManager.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionManager.java rename to app/core/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintBasedSessionManager.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintGenerator.java b/app/core/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintGenerator.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintGenerator.java rename to app/core/src/main/java/stirling/software/SPDF/config/fingerprint/FingerprintGenerator.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/CropController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/CropController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java similarity index 91% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/MergeController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java index ddd988ef9..4e05392c8 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/MergeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java @@ -35,7 +35,9 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.general.MergePdfsRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; +import stirling.software.common.util.PdfErrorUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -146,7 +148,7 @@ public class MergeController { try (PDDocument doc = pdfDocumentFactory.load(file)) { pageIndex += doc.getNumberOfPages(); } catch (IOException e) { - log.error("Error loading document for TOC generation", e); + ExceptionUtils.logException("document loading for TOC generation", e); pageIndex++; // Increment by at least one if we can't determine page count } } @@ -189,8 +191,17 @@ public class MergeController { mergedTempFile = Files.createTempFile("merged-", ".pdf").toFile(); mergerUtility.setDestinationFileName(mergedTempFile.getAbsolutePath()); - mergerUtility.mergeDocuments( - pdfDocumentFactory.getStreamCacheFunction(totalSize)); // Merge the documents + try { + mergerUtility.mergeDocuments( + pdfDocumentFactory.getStreamCacheFunction( + totalSize)); // Merge the documents + } catch (IOException e) { + ExceptionUtils.logException("PDF merge", e); + if (PdfErrorUtils.isCorruptedPdfError(e)) { + throw ExceptionUtils.createMultiplePdfCorruptedException(e); + } + throw e; + } // Load the merged PDF document mergedDocument = pdfDocumentFactory.load(mergedTempFile); @@ -229,7 +240,11 @@ public class MergeController { baos, mergedFileName); // Return the modified PDF } catch (Exception ex) { - log.error("Error in merge pdf process", ex); + if (ex instanceof IOException && PdfErrorUtils.isCorruptedPdfError((IOException) ex)) { + log.warn("Corrupted PDF detected in merge pdf process: {}", ex.getMessage()); + } else { + log.error("Error in merge pdf process", ex); + } throw ex; } finally { if (mergedDocument != null) { diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java index 3bf2ec802..717c85016 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java @@ -25,6 +25,7 @@ import stirling.software.SPDF.model.SortTypes; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.general.RearrangePagesRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.WebResponseUtils; @@ -288,8 +289,8 @@ public class RearrangePagesPDFController { .replaceFirst("[.][^.]+$", "") + "_rearranged.pdf"); } catch (IOException e) { - log.error("Failed rearranging documents", e); - return null; + ExceptionUtils.logException("document rearrangement", e); + throw e; } } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/RotationController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java similarity index 92% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/RotationController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java index afdfc54d9..58b502cfa 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/RotationController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/RotationController.java @@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor; import stirling.software.SPDF.model.api.general.RotatePDFRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -43,7 +44,8 @@ public class RotationController { // Validate the angle is a multiple of 90 if (angle % 90 != 0) { - throw new IllegalArgumentException("Angle must be a multiple of 90"); + throw ExceptionUtils.createIllegalArgumentException( + "error.angleNotMultipleOf90", "Angle must be a multiple of 90"); } // Load the PDF document diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java similarity index 96% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java index b2d689728..56f6f77fa 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java @@ -27,6 +27,7 @@ import lombok.RequiredArgsConstructor; import stirling.software.SPDF.model.api.general.ScalePagesRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -120,9 +121,7 @@ public class ScalePagesController { return sizeMap.get(targetPDRectangle); } - throw new IllegalArgumentException( - "Invalid PDRectangle. It must be one of the following: A0, A1, A2, A3, A4, A5, A6," - + " LETTER, LEGAL, KEEP"); + throw ExceptionUtils.createInvalidPageSizeException(targetPDRectangle); } private Map getSizeMap() { diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java similarity index 93% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java index 1b65891ac..f2425ac9a 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java @@ -29,6 +29,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -71,7 +72,7 @@ public class SplitPDFController { pageNumbers.add(totalPages - 1); } - log.info( + log.debug( "Splitting PDF into pages: {}", pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(","))); @@ -84,7 +85,7 @@ public class SplitPDFController { for (int i = previousPageNumber; i <= splitPoint; i++) { PDPage page = document.getPage(i); splitDocument.addPage(page); - log.info("Adding page {} to split document", i); + log.debug("Adding page {} to split document", i); } previousPageNumber = splitPoint + 1; @@ -96,7 +97,7 @@ public class SplitPDFController { splitDocumentsBoas.add(baos); } catch (Exception e) { - log.error("Failed splitting documents and saving them", e); + ExceptionUtils.logException("document splitting and saving", e); throw e; } } @@ -122,14 +123,14 @@ public class SplitPDFController { zipOut.write(pdf); zipOut.closeEntry(); - log.info("Wrote split document {} to zip file", fileName); + log.debug("Wrote split document {} to zip file", fileName); } } catch (Exception e) { log.error("Failed writing to zip", e); throw e; } - log.info("Successfully created zip file with split documents: {}", zipFile.toString()); + log.debug("Successfully created zip file with split documents: {}", zipFile.toString()); byte[] data = Files.readAllBytes(zipFile); Files.deleteIfExists(zipFile); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java similarity index 94% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java index 94cf6aa6d..f0f9fb012 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java @@ -35,6 +35,7 @@ import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest; import stirling.software.common.model.PdfMetadata; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.PdfMetadataService; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -131,7 +132,8 @@ public class SplitPdfByChaptersController { Integer bookmarkLevel = request.getBookmarkLevel(); // levels start from 0 (top most bookmarks) if (bookmarkLevel < 0) { - throw new IllegalArgumentException("Invalid bookmark level"); + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidArgument", "Invalid argument: {0}", "bookmark level"); } sourceDocument = pdfDocumentFactory.load(file); @@ -139,7 +141,8 @@ public class SplitPdfByChaptersController { if (outline == null) { log.warn("No outline found for {}", file.getOriginalFilename()); - throw new IllegalArgumentException("No outline found"); + throw ExceptionUtils.createIllegalArgumentException( + "error.pdfBookmarksNotFound", "No PDF bookmarks/outline found in document"); } List bookmarks = new ArrayList<>(); try { @@ -156,7 +159,7 @@ public class SplitPdfByChaptersController { Bookmark lastBookmark = bookmarks.get(bookmarks.size() - 1); } catch (Exception e) { - log.error("Unable to extract outline items", e); + ExceptionUtils.logException("outline extraction", e); return ResponseEntity.internalServerError() .body("Unable to extract outline items".getBytes()); } @@ -252,7 +255,7 @@ public class SplitPdfByChaptersController { zipOut.write(pdf); zipOut.closeEntry(); - log.info("Wrote split document {} to zip file", fileName); + log.debug("Wrote split document {} to zip file", fileName); } } catch (Exception e) { log.error("Failed writing to zip", e); @@ -280,7 +283,7 @@ public class SplitPdfByChaptersController { i++) { PDPage page = sourceDocument.getPage(i); splitDocument.addPage(page); - log.info("Adding page {} to split document", i); + log.debug("Adding page {} to split document", i); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (includeMetadata) { @@ -291,7 +294,7 @@ public class SplitPdfByChaptersController { splitDocumentsBoas.add(baos); } catch (Exception e) { - log.error("Failed splitting documents and saving them", e); + ExceptionUtils.logException("document splitting and saving", e); throw e; } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java similarity index 94% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java index 3df62816f..0dbbd933c 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.WebResponseUtils; @@ -96,13 +97,15 @@ public class SplitPdfBySizeController { handleSplitByDocCount(sourceDocument, documentCount, zipOut, filename); } else { log.error("Invalid split type: {}", type); - throw new IllegalArgumentException( - "Invalid argument for split type: " + type); + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidArgument", + "Invalid argument: {0}", + "split type: " + type); } log.debug("PDF splitting completed successfully"); } catch (Exception e) { - log.error("Error loading or processing PDF document", e); + ExceptionUtils.logException("PDF document loading or processing", e); throw e; } } catch (IOException e) { @@ -111,7 +114,7 @@ public class SplitPdfBySizeController { } } catch (Exception e) { - log.error("Exception during PDF splitting process", e); + ExceptionUtils.logException("PDF splitting process", e); throw e; // Re-throw to ensure proper error response } finally { try { @@ -275,8 +278,8 @@ public class SplitPdfBySizeController { currentDoc = pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDocument); log.debug("Successfully created initial output document"); } catch (Exception e) { - log.error("Error creating initial output document", e); - throw new IOException("Failed to create initial output document", e); + ExceptionUtils.logException("initial output document creation", e); + throw ExceptionUtils.createFileProcessingException("split", e); } int fileIndex = 1; @@ -295,7 +298,7 @@ public class SplitPdfBySizeController { log.debug("Successfully added page {} to current document", pageIndex); } catch (Exception e) { log.error("Error adding page {} to current document", pageIndex, e); - throw new IOException("Failed to add page to document", e); + throw ExceptionUtils.createFileProcessingException("split", e); } currentPageCount++; @@ -320,7 +323,7 @@ public class SplitPdfBySizeController { log.debug("Successfully created new document"); } catch (Exception e) { log.error("Error creating new document for next part", e); - throw new IOException("Failed to create new document", e); + throw ExceptionUtils.createFileProcessingException("split", e); } currentPageCount = 0; @@ -329,7 +332,7 @@ public class SplitPdfBySizeController { } } catch (Exception e) { log.error("Error iterating through pages", e); - throw new IOException("Failed to iterate through pages", e); + throw ExceptionUtils.createFileProcessingException("split", e); } // Add the last document if it contains any pages @@ -351,7 +354,7 @@ public class SplitPdfBySizeController { } } catch (Exception e) { log.error("Error checking or saving final document", e); - throw new IOException("Failed to process final document", e); + throw ExceptionUtils.createFileProcessingException("split", e); } finally { try { log.debug("Closing final document"); @@ -390,7 +393,7 @@ public class SplitPdfBySizeController { log.debug("Successfully created document {} of {}", i + 1, documentCount); } catch (Exception e) { log.error("Error creating document {} of {}", i + 1, documentCount, e); - throw new IOException("Failed to create document", e); + throw ExceptionUtils.createFileProcessingException("split", e); } int pagesToAdd = pagesPerDocument + (i < extraPages ? 1 : 0); @@ -408,7 +411,7 @@ public class SplitPdfBySizeController { currentPageIndex++; } catch (Exception e) { log.error("Error adding page {} to document {}", j + 1, i + 1, e); - throw new IOException("Failed to add page to document", e); + throw ExceptionUtils.createFileProcessingException("split", e); } } @@ -437,7 +440,7 @@ public class SplitPdfBySizeController { log.debug("Successfully saved document part {} ({} bytes)", index, outStream.size()); } catch (Exception e) { log.error("Error saving document part {} to byte array", index, e); - throw new IOException("Failed to save document to byte array", e); + throw ExceptionUtils.createFileProcessingException("split", e); } try { @@ -465,7 +468,7 @@ public class SplitPdfBySizeController { log.debug("Successfully added document part {} to ZIP", index); } catch (Exception e) { log.error("Error adding document part {} to ZIP", index, e); - throw new IOException("Failed to add document to ZIP file", e); + throw ExceptionUtils.createFileProcessingException("split", e); } } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java similarity index 93% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java index 9085f41b1..104a0f351 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java @@ -70,17 +70,17 @@ public class ToSinglePageController { float yOffset = totalHeight; // For each page, copy its content to the new page at the correct offset + int pageIndex = 0; for (PDPage page : sourceDocument.getPages()) { - PDFormXObject form = - layerUtility.importPageAsForm( - sourceDocument, sourceDocument.getPages().indexOf(page)); + PDFormXObject form = layerUtility.importPageAsForm(sourceDocument, pageIndex); AffineTransform af = AffineTransform.getTranslateInstance( 0, yOffset - page.getMediaBox().getHeight()); layerUtility.wrapInSaveRestore(newPage); - String defaultLayerName = "Layer" + sourceDocument.getPages().indexOf(page); + String defaultLayerName = "Layer" + pageIndex; layerUtility.appendFormAsLayer(newPage, form, af, defaultLayerName); yOffset -= page.getMediaBox().getHeight(); + pageIndex++; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEmlToPDF.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java similarity index 91% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java index 4eff3a872..9b3b64506 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java @@ -17,6 +17,7 @@ import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.api.converters.HTMLToPdfRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.FileToPdf; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; @@ -46,14 +47,14 @@ public class ConvertHtmlToPDF { MultipartFile fileInput = request.getFileInput(); if (fileInput == null) { - throw new IllegalArgumentException( - "Please provide an HTML or ZIP file for conversion."); + throw ExceptionUtils.createHtmlFileRequiredException(); } String originalFilename = Filenames.toSimpleFileName(fileInput.getOriginalFilename()); if (originalFilename == null || (!originalFilename.endsWith(".html") && !originalFilename.endsWith(".zip"))) { - throw new IllegalArgumentException("File must be either .html or .zip format."); + throw ExceptionUtils.createIllegalArgumentException( + "error.fileFormatRequired", "File must be in {0} format", ".html or .zip"); } boolean disableSanitize = diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java index 3125f8335..2466a0007 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java @@ -34,6 +34,7 @@ import stirling.software.SPDF.model.api.converters.ConvertToImageRequest; import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.CheckProgramInstall; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.PdfUtils; import stirling.software.common.util.ProcessExecutor; @@ -104,7 +105,7 @@ public class ConvertImgPDFController { log.error("resultant bytes for {} is null, error converting ", filename); } if ("webp".equalsIgnoreCase(imageFormat) && !CheckProgramInstall.isPythonAvailable()) { - throw new IOException("Python is not installed. Required for WebP conversion."); + throw ExceptionUtils.createPythonRequiredForWebpException(); } else if ("webp".equalsIgnoreCase(imageFormat) && CheckProgramInstall.isPythonAvailable()) { // Write the output stream to a temp file diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java similarity index 92% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java index 1bf2d94a8..6cb22be7e 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java @@ -27,6 +27,7 @@ import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.api.GeneralFile; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.FileToPdf; import stirling.software.common.util.TempFileManager; import stirling.software.common.util.WebResponseUtils; @@ -55,12 +56,14 @@ public class ConvertMarkdownToPdf { MultipartFile fileInput = generalFile.getFileInput(); if (fileInput == null) { - throw new IllegalArgumentException("Please provide a Markdown file for conversion."); + throw ExceptionUtils.createIllegalArgumentException( + "error.fileFormatRequired", "File must be in {0} format", "Markdown"); } String originalFilename = Filenames.toSimpleFileName(fileInput.getOriginalFilename()); if (originalFilename == null || !originalFilename.endsWith(".md")) { - throw new IllegalArgumentException("File must be in .md format."); + throw ExceptionUtils.createIllegalArgumentException( + "error.fileFormatRequired", "File must be in {0} format", ".md"); } // Convert Markdown to HTML using CommonMark diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java index 89282b925..7c5435aaa 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java @@ -67,6 +67,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.converters.PdfToPdfARequest; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; @@ -90,7 +91,7 @@ public class ConvertPDFToPDFA { // Validate input file type if (!"application/pdf".equals(inputFile.getContentType())) { log.error("Invalid input file type: {}", inputFile.getContentType()); - throw new IllegalArgumentException("Input file must be a PDF"); + throw ExceptionUtils.createPdfFileRequiredException(); } // Get the original filename without extension @@ -241,15 +242,13 @@ public class ConvertPDFToPDFA { if (returnCode.getRc() != 0) { log.error("PDF/A conversion failed with return code: {}", returnCode.getRc()); - throw new RuntimeException("PDF/A conversion failed"); + throw ExceptionUtils.createPdfaConversionFailedException(); } // Get the output file File[] outputFiles = tempOutputDir.toFile().listFiles(); if (outputFiles == null || outputFiles.length != 1) { - throw new RuntimeException( - "Expected one output PDF, found " - + (outputFiles == null ? "none" : outputFiles.length)); + throw ExceptionUtils.createPdfaConversionFailedException(); } return outputFiles[0].toPath(); } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java similarity index 88% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java index b16cc01d9..a7e194d4f 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java @@ -23,6 +23,7 @@ import stirling.software.SPDF.model.api.converters.UrlToPdfRequest; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; @@ -50,16 +51,19 @@ public class ConvertWebsiteToPDF { String URL = request.getUrlInput(); if (!applicationProperties.getSystem().getEnableUrlToPDF()) { - throw new IllegalArgumentException("This endpoint has been disabled by the admin."); + throw ExceptionUtils.createIllegalArgumentException( + "error.endpointDisabled", "This endpoint has been disabled by the admin"); } // Validate the URL format if (!URL.matches("^https?://.*") || !GeneralUtils.isValidURL(URL)) { - throw new IllegalArgumentException("Invalid URL format provided."); + throw ExceptionUtils.createInvalidArgumentException( + "URL", "provided format is invalid"); } // validate the URL is reachable if (!GeneralUtils.isURLReachable(URL)) { - throw new IllegalArgumentException("URL is not reachable, please provide a valid URL."); + throw ExceptionUtils.createIllegalArgumentException( + "error.urlNotReachable", "URL is not reachable, please provide a valid URL"); } Path tempOutputFile = null; diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java similarity index 95% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java index 96322ad80..ce9dab8c5 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java @@ -25,6 +25,7 @@ import stirling.software.SPDF.model.api.filter.FileSizeRequest; import stirling.software.SPDF.model.api.filter.PageRotationRequest; import stirling.software.SPDF.model.api.filter.PageSizeRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.PdfUtils; import stirling.software.common.util.WebResponseUtils; @@ -96,7 +97,7 @@ public class FilterController { valid = actualPageCount < pageCount; break; default: - throw new IllegalArgumentException("Invalid comparator: " + comparator); + throw ExceptionUtils.createInvalidArgumentException("comparator", comparator); } if (valid) return WebResponseUtils.multiPartFileToWebResponse(inputFile); @@ -139,7 +140,7 @@ public class FilterController { valid = actualArea < standardArea; break; default: - throw new IllegalArgumentException("Invalid comparator: " + comparator); + throw ExceptionUtils.createInvalidArgumentException("comparator", comparator); } if (valid) return WebResponseUtils.multiPartFileToWebResponse(inputFile); @@ -172,7 +173,7 @@ public class FilterController { valid = actualFileSize < fileSize; break; default: - throw new IllegalArgumentException("Invalid comparator: " + comparator); + throw ExceptionUtils.createInvalidArgumentException("comparator", comparator); } if (valid) return WebResponseUtils.multiPartFileToWebResponse(inputFile); @@ -208,7 +209,7 @@ public class FilterController { valid = actualRotation < rotation; break; default: - throw new IllegalArgumentException("Invalid comparator: " + comparator); + throw ExceptionUtils.createInvalidArgumentException("comparator", comparator); } if (valid) return WebResponseUtils.multiPartFileToWebResponse(inputFile); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AttachmentController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java similarity index 82% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java index 8509f5056..ab8e5b3f8 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java @@ -47,11 +47,13 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.SPDF.model.api.misc.OptimizePdfRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; @@ -61,16 +63,18 @@ import stirling.software.common.util.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class CompressController { private final CustomPDFDocumentFactory pdfDocumentFactory; - private final boolean qpdfEnabled; + private final EndpointConfiguration endpointConfiguration; - public CompressController( - CustomPDFDocumentFactory pdfDocumentFactory, - EndpointConfiguration endpointConfiguration) { - this.pdfDocumentFactory = pdfDocumentFactory; - this.qpdfEnabled = endpointConfiguration.isGroupEnabled("qpdf"); + private boolean isQpdfEnabled() { + return endpointConfiguration.isGroupEnabled("qpdf"); + } + + private boolean isGhostscriptEnabled() { + return endpointConfiguration.isGroupEnabled("Ghostscript"); } @Data @@ -597,12 +601,12 @@ public class CompressController { if (bytesRead > 0) { byte[] dataToHash = bytesRead == buffer.length ? buffer : Arrays.copyOf(buffer, bytesRead); - return bytesToHexString(generatMD5(dataToHash)); + return bytesToHexString(generateMD5(dataToHash)); } return "empty-stream"; } } catch (Exception e) { - log.error("Error generating image hash", e); + ExceptionUtils.logException("image hash generation", e); return "fallback-" + System.identityHashCode(image); } } @@ -615,12 +619,12 @@ public class CompressController { return sb.toString(); } - private byte[] generatMD5(byte[] data) throws IOException { + private byte[] generateMD5(byte[] data) throws IOException { try { MessageDigest md = MessageDigest.getInstance("MD5"); return md.digest(data); // Get the MD5 hash of the image bytes } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("MD5 algorithm not available", e); + throw ExceptionUtils.createMd5AlgorithmException(e); } } @@ -697,25 +701,69 @@ public class CompressController { boolean sizeMet = false; boolean imageCompressionApplied = false; - boolean qpdfCompressionApplied = false; - - if (qpdfEnabled && optimizeLevel <= 3) { - optimizeLevel = 4; - } + boolean externalCompressionApplied = false; while (!sizeMet && optimizeLevel <= 9) { - // Apply image compression for levels 4-9 - if ((optimizeLevel >= 3 || Boolean.TRUE.equals(convertToGrayscale)) - && !imageCompressionApplied) { - double scaleFactor = getScaleFactorForLevel(optimizeLevel); - float jpegQuality = getJpegQualityForLevel(optimizeLevel); + // Apply external compression first + if (!externalCompressionApplied) { + boolean ghostscriptSuccess = false; - // Compress images + // Try Ghostscript first if available - for ANY compression level + if (isGhostscriptEnabled()) { + try { + applyGhostscriptCompression( + request, optimizeLevel, currentFile, tempFiles); + log.info("Ghostscript compression applied successfully"); + ghostscriptSuccess = true; + } catch (IOException e) { + log.warn("Ghostscript compression failed, trying fallback methods"); + } + } + + // Fallback to QPDF if Ghostscript failed or not available (levels 1-3 only) + if (!ghostscriptSuccess && isQpdfEnabled() && optimizeLevel <= 3) { + try { + applyQpdfCompression(request, optimizeLevel, currentFile, tempFiles); + log.info("QPDF compression applied successfully"); + } catch (IOException e) { + log.warn("QPDF compression also failed"); + } + } + + if (!ghostscriptSuccess && !isQpdfEnabled()) { + log.info( + "No external compression tools available, using image compression only"); + } + + externalCompressionApplied = true; + + // Skip image compression if Ghostscript succeeded + if (ghostscriptSuccess) { + imageCompressionApplied = true; + } + } + + // Apply image compression for levels 4+ only if Ghostscript didn't run + if ((optimizeLevel >= 4 || Boolean.TRUE.equals(convertToGrayscale)) + && !imageCompressionApplied) { + // Use different scale factors based on level + double scaleFactor = + switch (optimizeLevel) { + case 4 -> 0.95; // 95% of original size + case 5 -> 0.9; // 90% of original size + case 6 -> 0.8; // 80% of original size + case 7 -> 0.7; // 70% of original size + case 8 -> 0.65; // 65% of original size + case 9 -> 0.5; // 50% of original size + default -> 1.0; + }; + + log.info("Applying image compression with scale factor: {}", scaleFactor); Path compressedImageFile = compressImagesInPDF( currentFile, scaleFactor, - jpegQuality, + 0.7f, // Default JPEG quality Boolean.TRUE.equals(convertToGrayscale)); tempFiles.add(compressedImageFile); @@ -723,18 +771,6 @@ public class CompressController { imageCompressionApplied = true; } - // Apply QPDF compression for all levels - if (!qpdfCompressionApplied && qpdfEnabled) { - applyQpdfCompression(request, optimizeLevel, currentFile, tempFiles); - qpdfCompressionApplied = true; - } else if (!qpdfCompressionApplied) { - // If QPDF is disabled, mark as applied and log - if (!qpdfEnabled) { - log.info("Skipping QPDF compression as QPDF group is disabled"); - } - qpdfCompressionApplied = true; - } - // Check if target size reached or not in auto mode long outputFileSize = Files.size(currentFile); if (outputFileSize <= expectedOutputSize || !autoMode) { @@ -754,7 +790,7 @@ public class CompressController { } else { // Reset flags for next iteration with higher optimization level imageCompressionApplied = false; - qpdfCompressionApplied = false; + externalCompressionApplied = false; optimizeLevel = newOptimizeLevel; } } @@ -788,6 +824,96 @@ public class CompressController { } } + // Run Ghostscript compression + private void applyGhostscriptCompression( + OptimizePdfRequest request, int optimizeLevel, Path currentFile, List tempFiles) + throws IOException { + + long preGsSize = Files.size(currentFile); + log.info("Pre-Ghostscript file size: {}", GeneralUtils.formatBytes(preGsSize)); + + // Create output file for Ghostscript + Path gsOutputFile = Files.createTempFile("gs_output_", ".pdf"); + tempFiles.add(gsOutputFile); + + // Build Ghostscript command based on optimization level + List command = new ArrayList<>(); + command.add("gs"); + command.add("-sDEVICE=pdfwrite"); + command.add("-dCompatibilityLevel=1.5"); + command.add("-dNOPAUSE"); + command.add("-dQUIET"); + command.add("-dBATCH"); + + // Map optimization levels to Ghostscript settings + switch (optimizeLevel) { + case 1: + command.add("-dPDFSETTINGS=/prepress"); + break; + case 2: + command.add("-dPDFSETTINGS=/printer"); + break; + case 3: + command.add("-dPDFSETTINGS=/ebook"); + break; + case 4: + case 5: + command.add("-dPDFSETTINGS=/screen"); + break; + case 6: + case 7: + command.add("-dPDFSETTINGS=/screen"); + command.add("-dColorImageResolution=150"); + command.add("-dGrayImageResolution=150"); + command.add("-dMonoImageResolution=300"); + break; + case 8: + case 9: + command.add("-dPDFSETTINGS=/screen"); + command.add("-dColorImageResolution=100"); + command.add("-dGrayImageResolution=100"); + command.add("-dMonoImageResolution=200"); + break; + case 10: + command.add("-dPDFSETTINGS=/screen"); + command.add("-dColorImageResolution=72"); + command.add("-dGrayImageResolution=72"); + command.add("-dMonoImageResolution=150"); + break; + default: + command.add("-dPDFSETTINGS=/screen"); + break; + } + + command.add("-sOutputFile=" + gsOutputFile.toString()); + command.add(currentFile.toString()); + + ProcessExecutorResult returnCode = null; + try { + returnCode = + ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT) + .runCommandWithOutputHandling(command); + + if (returnCode.getRc() == 0) { + // Update current file to the Ghostscript output + Files.copy(gsOutputFile, currentFile, StandardCopyOption.REPLACE_EXISTING); + + long postGsSize = Files.size(currentFile); + double gsReduction = 100.0 - ((postGsSize * 100.0) / preGsSize); + log.info( + "Post-Ghostscript file size: {} (reduced by {}%)", + GeneralUtils.formatBytes(postGsSize), String.format("%.1f", gsReduction)); + } else { + log.warn("Ghostscript compression failed with return code: {}", returnCode.getRc()); + throw new IOException("Ghostscript compression failed"); + } + + } catch (Exception e) { + log.warn("Ghostscript compression failed, will fallback to other methods", e); + throw new IOException("Ghostscript compression failed", e); + } + } + // Run QPDF compression private void applyQpdfCompression( OptimizePdfRequest request, int optimizeLevel, Path currentFile, List tempFiles) diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java similarity index 97% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java index cfbc88e8b..5c432ce57 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -134,7 +135,7 @@ public class DecompressPdfController { stream.setInt(COSName.LENGTH, decompressedBytes.length); } } catch (IOException e) { - log.error("Error decompressing stream", e); + ExceptionUtils.logException("stream decompression", e); // Continue processing other streams even if this one fails } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java index d5d3a63fb..7ecc04e1a 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java @@ -33,6 +33,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest; import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.util.CheckProgramInstall; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.WebResponseUtils; @@ -72,7 +73,8 @@ public class ExtractImageScansController { List tempDirs = new ArrayList<>(); if (!CheckProgramInstall.isPythonAvailable()) { - throw new IOException("Python is not installed."); + throw ExceptionUtils.createIOException( + "error.toolNotInstalled", "{0} is not installed", null, "Python"); } String pythonVersion = CheckProgramInstall.getAvailablePythonCommand(); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java similarity index 60% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java index cb06b9f4d..09486f9e8 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java @@ -41,6 +41,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFExtractImagesRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ImageProcessingUtils; import stirling.software.common.util.WebResponseUtils; @@ -90,39 +91,57 @@ public class ExtractImagesController { Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); Set> futures = new HashSet<>(); - // Iterate over each page - for (int pgNum = 0; pgNum < document.getPages().getCount(); pgNum++) { - PDPage page = document.getPage(pgNum); - Future future = - executor.submit( - () -> { - // Use the page number directly from the iterator, so no need to - // calculate manually - int pageNum = document.getPages().indexOf(page) + 1; + // Safely iterate over each page, handling corrupt PDFs where page count might be wrong + try { + int pageCount = document.getPages().getCount(); + log.debug("Document reports {} pages", pageCount); - try { - // Call the image extraction method for each page - extractImagesFromPage( - page, - format, - filename, - pageNum, - processedImages, - zos, - allowDuplicates); - } catch (IOException e) { - // Log the error and continue processing other pages - log.error( - "Error extracting images from page {}: {}", - pageNum, - e.getMessage()); - } + int consecutiveFailures = 0; - return null; // Callable requires a return type - }); + for (int pgNum = 0; pgNum < pageCount; pgNum++) { + try { + PDPage page = document.getPage(pgNum); + consecutiveFailures = 0; // Reset on success + final int currentPageNum = pgNum + 1; // Convert to 1-based page numbering + Future future = + executor.submit( + () -> { + try { + // Call the image extraction method for each page + extractImagesFromPage( + page, + format, + filename, + currentPageNum, + processedImages, + zos, + allowDuplicates); + } catch (Exception e) { + // Log the error and continue processing other pages + ExceptionUtils.logException( + "image extraction from page " + + currentPageNum, + e); + } - // Add the Future object to the list to track completion - futures.add(future); + return null; // Callable requires a return type + }); + + // Add the Future object to the list to track completion + futures.add(future); + } catch (Exception e) { + consecutiveFailures++; + ExceptionUtils.logException("page access for page " + (pgNum + 1), e); + + if (consecutiveFailures >= 3) { + log.warn("Stopping page iteration after 3 consecutive failures"); + break; + } + } + } + } catch (Exception e) { + ExceptionUtils.logException("page count determination", e); + throw e; } // Wait for all tasks to complete @@ -180,34 +199,39 @@ public class ExtractImagesController { } int count = 1; for (COSName name : page.getResources().getXObjectNames()) { - if (page.getResources().isImageXObject(name)) { - PDImageXObject image = (PDImageXObject) page.getResources().getXObject(name); - if (!allowDuplicates) { - byte[] data = ImageProcessingUtils.getImageData(image.getImage()); - byte[] imageHash = md.digest(data); - synchronized (processedImages) { - if (processedImages.stream() - .anyMatch(hash -> Arrays.equals(hash, imageHash))) { - continue; // Skip already processed images + try { + if (page.getResources().isImageXObject(name)) { + PDImageXObject image = (PDImageXObject) page.getResources().getXObject(name); + if (!allowDuplicates) { + byte[] data = ImageProcessingUtils.getImageData(image.getImage()); + byte[] imageHash = md.digest(data); + synchronized (processedImages) { + if (processedImages.stream() + .anyMatch(hash -> Arrays.equals(hash, imageHash))) { + continue; // Skip already processed images + } + processedImages.add(imageHash); } - processedImages.add(imageHash); + } + + RenderedImage renderedImage = image.getImage(); + + // Convert to standard RGB colorspace if needed + BufferedImage bufferedImage = convertToRGB(renderedImage, format); + + // Write image to zip file + String imageName = filename + "_page_" + pageNum + "_" + count++ + "." + format; + synchronized (zos) { + zos.putNextEntry(new ZipEntry(imageName)); + ByteArrayOutputStream imageBaos = new ByteArrayOutputStream(); + ImageIO.write(bufferedImage, format, imageBaos); + zos.write(imageBaos.toByteArray()); + zos.closeEntry(); } } - - RenderedImage renderedImage = image.getImage(); - - // Convert to standard RGB colorspace if needed - BufferedImage bufferedImage = convertToRGB(renderedImage, format); - - // Write image to zip file - String imageName = filename + "_page_" + pageNum + "_" + count++ + "." + format; - synchronized (zos) { - zos.putNextEntry(new ZipEntry(imageName)); - ByteArrayOutputStream imageBaos = new ByteArrayOutputStream(); - ImageIO.write(bufferedImage, format, imageBaos); - zos.write(imageBaos.toByteArray()); - zos.closeEntry(); - } + } catch (IOException e) { + ExceptionUtils.logException("image extraction", e); + throw ExceptionUtils.handlePdfException(e, "during image extraction"); } } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanController.java similarity index 89% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanController.java index 7872a4b09..d221ed52c 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanController.java @@ -47,6 +47,11 @@ public class FakeScanController { private final CustomPDFDocumentFactory pdfDocumentFactory; private static final Random RANDOM = new Random(); + // Size limits to prevent OutOfMemoryError + private static final int MAX_IMAGE_WIDTH = 8192; + private static final int MAX_IMAGE_HEIGHT = 8192; + private static final long MAX_IMAGE_PIXELS = 16_777_216; // 4096x4096 + @PostMapping(value = "/fake-scan", consumes = "multipart/form-data") @Operation( summary = "Convert PDF to look like a scanned document", @@ -82,8 +87,46 @@ public class FakeScanController { PDFRenderer pdfRenderer = new PDFRenderer(document); for (int i = 0; i < document.getNumberOfPages(); i++) { - // Render page to image with specified resolution - BufferedImage image = pdfRenderer.renderImageWithDPI(i, resolution); + // Get page dimensions to calculate safe resolution + PDRectangle pageSize = document.getPage(i).getMediaBox(); + float pageWidthPts = pageSize.getWidth(); + float pageHeightPts = pageSize.getHeight(); + + // Calculate what the image dimensions would be at the requested resolution + int projectedWidth = (int) Math.ceil(pageWidthPts * resolution / 72.0); + int projectedHeight = (int) Math.ceil(pageHeightPts * resolution / 72.0); + long projectedPixels = (long) projectedWidth * projectedHeight; + + // Calculate safe resolution that stays within limits + int safeResolution = resolution; + if (projectedWidth > MAX_IMAGE_WIDTH + || projectedHeight > MAX_IMAGE_HEIGHT + || projectedPixels > MAX_IMAGE_PIXELS) { + double widthScale = (double) MAX_IMAGE_WIDTH / projectedWidth; + double heightScale = (double) MAX_IMAGE_HEIGHT / projectedHeight; + double pixelScale = Math.sqrt((double) MAX_IMAGE_PIXELS / projectedPixels); + double minScale = Math.min(Math.min(widthScale, heightScale), pixelScale); + safeResolution = (int) Math.max(72, resolution * minScale); + + log.warn( + "Page {} would be too large at {}dpi ({}x{} pixels). Reducing to {}dpi", + i + 1, + resolution, + projectedWidth, + projectedHeight, + safeResolution); + } + + // Render page to image with safe resolution + BufferedImage image = pdfRenderer.renderImageWithDPI(i, safeResolution); + + log.debug( + "Processing page {} with dimensions {}x{} ({} pixels) at {}dpi", + i + 1, + image.getWidth(), + image.getHeight(), + (long) image.getWidth() * image.getHeight(), + safeResolution); // 1. Convert to grayscale or keep color BufferedImage processed; diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java new file mode 100644 index 000000000..c1fd4ade1 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java @@ -0,0 +1,414 @@ +package stirling.software.SPDF.controller.api.misc; + +import java.awt.image.BufferedImage; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.imageio.ImageIO; + +import org.apache.pdfbox.multipdf.PDFMergerUtility; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.apache.pdfbox.text.PDFTextStripper; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import io.github.pixee.security.Filenames; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.SPDF.model.api.misc.ProcessPdfWithOcrRequest; +import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; +import stirling.software.common.util.ProcessExecutor; +import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; +import stirling.software.common.util.TempDirectory; +import stirling.software.common.util.TempFile; +import stirling.software.common.util.TempFileManager; +import stirling.software.common.util.WebResponseUtils; + +@RestController +@RequestMapping("/api/v1/misc") +@Tag(name = "Misc", description = "Miscellaneous APIs") +@Slf4j +@RequiredArgsConstructor +public class OCRController { + + private final ApplicationProperties applicationProperties; + private final CustomPDFDocumentFactory pdfDocumentFactory; + private final TempFileManager tempFileManager; + private final EndpointConfiguration endpointConfiguration; + + private boolean isOcrMyPdfEnabled() { + return endpointConfiguration.isGroupEnabled("OCRmyPDF"); + } + + private boolean isTesseractEnabled() { + return endpointConfiguration.isGroupEnabled("tesseract"); + } + + /** Gets the list of available Tesseract languages from the tessdata directory */ + public List getAvailableTesseractLanguages() { + String tessdataDir = applicationProperties.getSystem().getTessdataDir(); + File[] files = new File(tessdataDir).listFiles(); + if (files == null) { + return Collections.emptyList(); + } + return Arrays.stream(files) + .filter(file -> file.getName().endsWith(".traineddata")) + .map(file -> file.getName().replace(".traineddata", "")) + .filter(lang -> !"osd".equalsIgnoreCase(lang)) + .toList(); + } + + @PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") + @Operation( + summary = "Process a PDF file with OCR", + description = + "This endpoint processes a PDF file using OCR (Optical Character Recognition). " + + "Users can specify languages, sidecar, deskew, clean, cleanFinal, ocrType, ocrRenderType, and removeImagesAfter options. " + + "Uses OCRmyPDF if available, falls back to Tesseract. Input:PDF Output:PDF Type:SI-Conditional") + public ResponseEntity processPdfWithOCR( + @ModelAttribute ProcessPdfWithOcrRequest request) + throws IOException, InterruptedException { + MultipartFile inputFile = request.getFileInput(); + List selectedLanguages = request.getLanguages(); + Boolean sidecar = request.isSidecar(); + Boolean deskew = request.isDeskew(); + Boolean clean = request.isClean(); + Boolean cleanFinal = request.isCleanFinal(); + String ocrType = request.getOcrType(); + String ocrRenderType = request.getOcrRenderType(); + Boolean removeImagesAfter = request.isRemoveImagesAfter(); + + if (selectedLanguages == null || selectedLanguages.isEmpty()) { + throw ExceptionUtils.createOcrLanguageRequiredException(); + } + + if (!"hocr".equals(ocrRenderType) && !"sandwich".equals(ocrRenderType)) { + throw new IOException("ocrRenderType wrong"); + } + + // Get available Tesseract languages + List availableLanguages = getAvailableTesseractLanguages(); + + // Validate selected languages + selectedLanguages = + selectedLanguages.stream().filter(availableLanguages::contains).toList(); + + if (selectedLanguages.isEmpty()) { + throw ExceptionUtils.createOcrInvalidLanguagesException(); + } + + // Use try-with-resources for proper temp file management + try (TempFile tempInputFile = new TempFile(tempFileManager, ".pdf"); + TempFile tempOutputFile = new TempFile(tempFileManager, ".pdf")) { + + inputFile.transferTo(tempInputFile.getFile()); + + TempFile sidecarTextFile = null; + + try { + // Use OCRmyPDF if available (no fallback - error if it fails) + if (isOcrMyPdfEnabled()) { + if (sidecar != null && sidecar) { + sidecarTextFile = new TempFile(tempFileManager, ".txt"); + } + + processWithOcrMyPdf( + selectedLanguages, + sidecar, + deskew, + clean, + cleanFinal, + ocrType, + ocrRenderType, + removeImagesAfter, + tempInputFile.getPath(), + tempOutputFile.getPath(), + sidecarTextFile != null ? sidecarTextFile.getPath() : null); + log.info("OCRmyPDF processing completed successfully"); + } + // Use Tesseract only if OCRmyPDF is not available + else if (isTesseractEnabled()) { + processWithTesseract( + selectedLanguages, + ocrType, + tempInputFile.getPath(), + tempOutputFile.getPath()); + log.info("Tesseract processing completed successfully"); + } else { + throw ExceptionUtils.createOcrToolsUnavailableException(); + } + + // Read the processed PDF file + byte[] pdfBytes = Files.readAllBytes(tempOutputFile.getPath()); + + // Return the OCR processed PDF as a response + String outputFilename = + Filenames.toSimpleFileName(inputFile.getOriginalFilename()) + .replaceFirst("[.][^.]+$", "") + + "_OCR.pdf"; + + if (sidecar != null && sidecar && sidecarTextFile != null) { + // Create a zip file containing both the PDF and the text file + String outputZipFilename = + Filenames.toSimpleFileName(inputFile.getOriginalFilename()) + .replaceFirst("[.][^.]+$", "") + + "_OCR.zip"; + + try (TempFile tempZipFile = new TempFile(tempFileManager, ".zip"); + ZipOutputStream zipOut = + new ZipOutputStream( + Files.newOutputStream(tempZipFile.getPath()))) { + + // Add PDF file to the zip + ZipEntry pdfEntry = new ZipEntry(outputFilename); + zipOut.putNextEntry(pdfEntry); + zipOut.write(pdfBytes); + zipOut.closeEntry(); + + // Add text file to the zip + ZipEntry txtEntry = new ZipEntry(outputFilename.replace(".pdf", ".txt")); + zipOut.putNextEntry(txtEntry); + Files.copy(sidecarTextFile.getPath(), zipOut); + zipOut.closeEntry(); + + zipOut.finish(); + + byte[] zipBytes = Files.readAllBytes(tempZipFile.getPath()); + + // Return the zip file containing both the PDF and the text file + return WebResponseUtils.bytesToWebResponse( + zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM); + } + } else { + // Return the OCR processed PDF as a response + return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename); + } + + } finally { + // Clean up sidecar temp file if created + if (sidecarTextFile != null) { + try { + sidecarTextFile.close(); + } catch (Exception e) { + log.warn("Failed to close sidecar temp file", e); + } + } + } + } + } + + private void processWithOcrMyPdf( + List selectedLanguages, + Boolean sidecar, + Boolean deskew, + Boolean clean, + Boolean cleanFinal, + String ocrType, + String ocrRenderType, + Boolean removeImagesAfter, + Path tempInputFile, + Path tempOutputFile, + Path sidecarTextPath) + throws IOException, InterruptedException { + + // Build OCRmyPDF command + String languageOption = String.join("+", selectedLanguages); + + List command = + new ArrayList<>( + Arrays.asList( + "ocrmypdf", + "--verbose", + "2", + "--output-type", + "pdf", + "--pdf-renderer", + ocrRenderType)); + + if (sidecar != null && sidecar && sidecarTextPath != null) { + command.add("--sidecar"); + command.add(sidecarTextPath.toString()); + } + + if (deskew != null && deskew) { + command.add("--deskew"); + } + if (clean != null && clean) { + command.add("--clean"); + } + if (cleanFinal != null && cleanFinal) { + command.add("--clean-final"); + } + if (ocrType != null && !"".equals(ocrType)) { + if ("skip-text".equals(ocrType)) { + command.add("--skip-text"); + } else if ("force-ocr".equals(ocrType)) { + command.add("--force-ocr"); + } + } + + command.addAll( + Arrays.asList( + "--language", + languageOption, + tempInputFile.toString(), + tempOutputFile.toString())); + + // Run CLI command + ProcessExecutorResult result = + ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF) + .runCommandWithOutputHandling(command); + + if (result.getRc() != 0 + && result.getMessages().contains("multiprocessing/synchronize.py") + && result.getMessages().contains("OSError: [Errno 38] Function not implemented")) { + command.add("--jobs"); + command.add("1"); + result = + ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF) + .runCommandWithOutputHandling(command); + } + + if (result.getRc() != 0) { + throw new IOException("OCRmyPDF failed with return code: " + result.getRc()); + } + + // Remove images from the OCR processed PDF if the flag is set to true + if (removeImagesAfter != null && removeImagesAfter) { + try (TempFile tempPdfWithoutImages = new TempFile(tempFileManager, "_no_images.pdf")) { + List gsCommand = + Arrays.asList( + "gs", + "-sDEVICE=pdfwrite", + "-dFILTERIMAGE", + "-o", + tempPdfWithoutImages.getPath().toString(), + tempOutputFile.toString()); + + ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT) + .runCommandWithOutputHandling(gsCommand); + + // Replace output file with version without images + Files.copy( + tempPdfWithoutImages.getPath(), + tempOutputFile, + java.nio.file.StandardCopyOption.REPLACE_EXISTING); + } + } + } + + private void processWithTesseract( + List selectedLanguages, String ocrType, Path tempInputFile, Path tempOutputFile) + throws IOException, InterruptedException { + + // Create temp directory for Tesseract processing + try (TempDirectory tempDir = new TempDirectory(tempFileManager)) { + File tempOutputDir = new File(tempDir.getPath().toFile(), "output"); + File tempImagesDir = new File(tempDir.getPath().toFile(), "images"); + File finalOutputFile = new File(tempDir.getPath().toFile(), "final_output.pdf"); + + // Create directories + tempOutputDir.mkdirs(); + tempImagesDir.mkdirs(); + + PDFMergerUtility merger = new PDFMergerUtility(); + merger.setDestinationFileName(finalOutputFile.toString()); + + try (PDDocument document = pdfDocumentFactory.load(tempInputFile.toFile())) { + PDFRenderer pdfRenderer = new PDFRenderer(document); + int pageCount = document.getNumberOfPages(); + + for (int pageNum = 0; pageNum < pageCount; pageNum++) { + PDPage page = document.getPage(pageNum); + boolean hasText = false; + + // Check for existing text + try (PDDocument tempDoc = new PDDocument()) { + tempDoc.addPage(page); + PDFTextStripper stripper = new PDFTextStripper(); + hasText = !stripper.getText(tempDoc).trim().isEmpty(); + } + + boolean shouldOcr = + switch (ocrType) { + case "skip-text" -> !hasText; + case "force-ocr" -> true; + default -> true; + }; + + File pageOutputPath = + new File(tempOutputDir, String.format("page_%d.pdf", pageNum)); + + if (shouldOcr) { + // Convert page to image + BufferedImage image = pdfRenderer.renderImageWithDPI(pageNum, 300); + File imagePath = + new File(tempImagesDir, String.format("page_%d.png", pageNum)); + ImageIO.write(image, "png", imagePath); + + // Build OCR command + List command = new ArrayList<>(); + command.add("tesseract"); + command.add(imagePath.toString()); + command.add( + new File(tempOutputDir, String.format("page_%d", pageNum)) + .toString()); + command.add("-l"); + command.add(String.join("+", selectedLanguages)); + command.add("pdf"); // Always output PDF + + ProcessExecutorResult result = + ProcessExecutor.getInstance(ProcessExecutor.Processes.TESSERACT) + .runCommandWithOutputHandling(command); + + if (result.getRc() != 0) { + throw ExceptionUtils.createRuntimeException( + "error.commandFailed", + "{0} command failed with exit code: {1}", + null, + "Tesseract", + result.getRc()); + } + + // Add OCR'd PDF to merger + merger.addSource(pageOutputPath); + } else { + // Save original page without OCR + try (PDDocument pageDoc = new PDDocument()) { + pageDoc.addPage(page); + pageDoc.save(pageOutputPath); + merger.addSource(pageOutputPath); + } + } + } + } + + // Merge all pages into final PDF + merger.mergeDocuments(null); + + // Copy final output to the expected location + Files.copy( + finalOutputFile.toPath(), + tempOutputFile, + java.nio.file.StandardCopyOption.REPLACE_EXISTING); + } + } +} diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java new file mode 100644 index 000000000..7cde1d078 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java @@ -0,0 +1,133 @@ +package stirling.software.SPDF.controller.api.misc; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import io.github.pixee.security.Filenames; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.common.model.api.PDFFile; +import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ProcessExecutor; +import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; +import stirling.software.common.util.TempFile; +import stirling.software.common.util.TempFileManager; +import stirling.software.common.util.WebResponseUtils; + +@RestController +@RequestMapping("/api/v1/misc") +@Tag(name = "Misc", description = "Miscellaneous APIs") +@Slf4j +@RequiredArgsConstructor +public class RepairController { + + private final CustomPDFDocumentFactory pdfDocumentFactory; + private final TempFileManager tempFileManager; + private final EndpointConfiguration endpointConfiguration; + + private boolean isGhostscriptEnabled() { + return endpointConfiguration.isGroupEnabled("Ghostscript"); + } + + private boolean isQpdfEnabled() { + return endpointConfiguration.isGroupEnabled("qpdf"); + } + + @PostMapping(consumes = "multipart/form-data", value = "/repair") + @Operation( + summary = "Repair a PDF file", + description = + "This endpoint repairs a given PDF file by running Ghostscript (primary), qpdf (fallback), or PDFBox (if no external tools available). The PDF is" + + " first saved to a temporary location, repaired, read back, and then" + + " returned as a response. Input:PDF Output:PDF Type:SISO") + public ResponseEntity repairPdf(@ModelAttribute PDFFile file) + throws IOException, InterruptedException { + MultipartFile inputFile = file.getFileInput(); + + // Use TempFile with try-with-resources for automatic cleanup + try (TempFile tempInputFile = new TempFile(tempFileManager, ".pdf"); + TempFile tempOutputFile = new TempFile(tempFileManager, ".pdf")) { + + // Save the uploaded file to the temporary location + inputFile.transferTo(tempInputFile.getFile()); + + boolean repairSuccess = false; + + // Try Ghostscript first if available + if (isGhostscriptEnabled()) { + try { + List gsCommand = new ArrayList<>(); + gsCommand.add("gs"); + gsCommand.add("-o"); + gsCommand.add(tempOutputFile.getPath().toString()); + gsCommand.add("-sDEVICE=pdfwrite"); + gsCommand.add(tempInputFile.getPath().toString()); + + ProcessExecutorResult gsResult = + ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT) + .runCommandWithOutputHandling(gsCommand); + + if (gsResult.getRc() == 0) { + repairSuccess = true; + } + } catch (Exception e) { + // Log and continue to QPDF fallback + log.warn("Ghostscript repair failed, trying QPDF fallback: ", e); + } + } + + // Fallback to QPDF if Ghostscript failed or not available + if (!repairSuccess && isQpdfEnabled()) { + List qpdfCommand = new ArrayList<>(); + qpdfCommand.add("qpdf"); + qpdfCommand.add("--replace-input"); // Automatically fixes problems it can + qpdfCommand.add("--qdf"); // Linearizes and normalizes PDF structure + qpdfCommand.add("--object-streams=disable"); // Can help with some corruptions + qpdfCommand.add(tempInputFile.getPath().toString()); + qpdfCommand.add(tempOutputFile.getPath().toString()); + + ProcessExecutorResult qpdfResult = + ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF) + .runCommandWithOutputHandling(qpdfCommand); + + repairSuccess = true; + } + + // Use PDFBox as last resort if no external tools are available + if (!repairSuccess) { + if (!isGhostscriptEnabled() && !isQpdfEnabled()) { + // Basic PDFBox repair - load and save to fix structural issues + try (var document = pdfDocumentFactory.load(tempInputFile.getFile())) { + document.save(tempOutputFile.getFile()); + repairSuccess = true; + } + } else { + throw new IOException("PDF repair failed with available tools"); + } + } + + // Read the repaired PDF file + byte[] pdfBytes = pdfDocumentFactory.loadToBytes(tempOutputFile.getFile()); + + // Return the repaired PDF as a response + String outputFilename = + Filenames.toSimpleFileName(inputFile.getOriginalFilename()) + .replaceFirst("[.][^.]+$", "") + + "_repaired.pdf"; + return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename); + } + } +} diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java index e7dfba041..21fd61d11 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/UnlockPDFFormsController.java @@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -34,7 +33,6 @@ import stirling.software.common.util.WebResponseUtils; public class UnlockPDFFormsController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired public UnlockPDFFormsController(CustomPDFDocumentFactory pdfDocumentFactory) { this.pdfDocumentFactory = pdfDocumentFactory; } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java similarity index 89% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java index 222ecd1c6..5c1fd5f4a 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java @@ -150,11 +150,22 @@ public class PipelineProcessor { } } if (!hasInputFileType) { + String filename = file.getFilename(); + String providedExtension = "no extension"; + if (filename != null && filename.contains(".")) { + providedExtension = + filename.substring(filename.lastIndexOf(".")).toLowerCase(); + } + logPrintStream.println( "No files with extension " + String.join(", ", inputFileTypes) + " found for operation " - + operation); + + operation + + ". Provided file '" + + filename + + "' has extension: " + + providedExtension); hasErrors = true; } } @@ -203,11 +214,32 @@ public class PipelineProcessor { hasErrors = true; } } else { + // Get details about what files were actually provided + List providedExtensions = + outputFiles.stream() + .map( + file -> { + String filename = file.getFilename(); + if (filename != null && filename.contains(".")) { + return filename.substring( + filename.lastIndexOf(".")) + .toLowerCase(); + } + return "no extension"; + }) + .distinct() + .toList(); + logPrintStream.println( "No files with extension " + String.join(", ", inputFileTypes) + " found for multi-input operation " - + operation); + + operation + + ". Provided files have extensions: " + + String.join(", ", providedExtensions) + + " (total files: " + + outputFiles.size() + + ")"); hasErrors = true; } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java similarity index 96% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index 612c666c4..7675355da 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -65,6 +65,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.github.pixee.security.Filenames; +import io.micrometer.common.util.StringUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -73,6 +74,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -132,7 +134,7 @@ public class CertSignController { } doc.saveIncremental(output); } catch (Exception e) { - log.error("exception", e); + ExceptionUtils.logException("PDF signing", e); } } @@ -165,8 +167,11 @@ public class CertSignController { Integer pageNumber = request.getPageNumber() != null ? (request.getPageNumber() - 1) : null; Boolean showLogo = request.getShowLogo(); - if (certType == null) { - throw new IllegalArgumentException("Cert type must be provided"); + if (StringUtils.isBlank(certType)) { + throw ExceptionUtils.createIllegalArgumentException( + "error.optionsNotSpecified", + "{0} options are not specified", + "certificate type"); } KeyStore ks = null; @@ -189,7 +194,10 @@ public class CertSignController { ks.load(jksfile.getInputStream(), password.toCharArray()); break; default: - throw new IllegalArgumentException("Invalid cert type: " + certType); + throw ExceptionUtils.createIllegalArgumentException( + "error.invalidArgument", + "Invalid argument: {0}", + "certificate type: " + certType); } CreateSignature createSignature = new CreateSignature(ks, password.toCharArray()); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java similarity index 92% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java index c630106e4..f3c0a5e29 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java @@ -63,6 +63,7 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.common.model.api.PDFFile; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -149,23 +150,39 @@ public class GetInfoOnPDF { try { PDMetadata pdMetadata = document.getDocumentCatalog().getMetadata(); if (pdMetadata != null) { - COSInputStream metaStream = pdMetadata.createInputStream(); - DomXmpParser domXmpParser = new DomXmpParser(); - XMPMetadata xmpMeta = domXmpParser.parse(metaStream); + try (COSInputStream metaStream = pdMetadata.createInputStream()) { + // First try to read raw metadata as string to check for standard keywords + byte[] metadataBytes = metaStream.readAllBytes(); + String rawMetadata = new String(metadataBytes, StandardCharsets.UTF_8); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - new XmpSerializer().serialize(xmpMeta, baos, true); - String xmpString = new String(baos.toByteArray(), StandardCharsets.UTF_8); + if (rawMetadata.contains(standardKeyword)) { + return true; + } + } - if (xmpString.contains(standardKeyword)) { - return true; + // If raw check doesn't find it, try parsing with XMP parser + try (COSInputStream metaStream = pdMetadata.createInputStream()) { + try { + DomXmpParser domXmpParser = new DomXmpParser(); + XMPMetadata xmpMeta = domXmpParser.parse(metaStream); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new XmpSerializer().serialize(xmpMeta, baos, true); + String xmpString = new String(baos.toByteArray(), StandardCharsets.UTF_8); + + if (xmpString.contains(standardKeyword)) { + return true; + } + } catch (XmpParsingException e) { + // XMP parsing failed, but we already checked raw metadata above + log.debug( + "XMP parsing failed for standard check, but raw metadata was already checked: {}", + e.getMessage()); + } } } - } catch ( - Exception - e) { // Catching general exception for brevity, ideally you'd catch specific - // exceptions. - log.error("exception", e); + } catch (Exception e) { + ExceptionUtils.logException("PDF standard checking", e); } return false; @@ -391,14 +408,22 @@ public class GetInfoOnPDF { if (pdMetadata != null) { try { - COSInputStream is = pdMetadata.createInputStream(); - DomXmpParser domXmpParser = new DomXmpParser(); - XMPMetadata xmpMeta = domXmpParser.parse(is); + try (COSInputStream is = pdMetadata.createInputStream()) { + DomXmpParser domXmpParser = new DomXmpParser(); + XMPMetadata xmpMeta = domXmpParser.parse(is); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - new XmpSerializer().serialize(xmpMeta, os, true); - xmpString = new String(os.toByteArray(), StandardCharsets.UTF_8); - } catch (XmpParsingException | IOException e) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + new XmpSerializer().serialize(xmpMeta, os, true); + xmpString = new String(os.toByteArray(), StandardCharsets.UTF_8); + } + } catch (XmpParsingException e) { + // XMP parsing failed, try to read raw metadata instead + log.debug("XMP parsing failed, reading raw metadata: {}", e.getMessage()); + try (COSInputStream is = pdMetadata.createInputStream()) { + byte[] metadataBytes = is.readAllBytes(); + xmpString = new String(metadataBytes, StandardCharsets.UTF_8); + } + } catch (IOException e) { log.error("exception", e); } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java similarity index 89% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index 4567fcb7e..ef382ee44 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor; import stirling.software.SPDF.model.api.security.AddPasswordRequest; import stirling.software.SPDF.model.api.security.PDFPasswordRequest; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.WebResponseUtils; @RestController @@ -42,12 +43,19 @@ public class PasswordController { MultipartFile fileInput = request.getFileInput(); String password = request.getPassword(); PDDocument document = pdfDocumentFactory.load(fileInput, password); - document.setAllSecurityToBeRemoved(true); - return WebResponseUtils.pdfDocToWebResponse( - document, - Filenames.toSimpleFileName(fileInput.getOriginalFilename()) - .replaceFirst("[.][^.]+$", "") - + "_password_removed.pdf"); + + try { + document.setAllSecurityToBeRemoved(true); + return WebResponseUtils.pdfDocToWebResponse( + document, + Filenames.toSimpleFileName(fileInput.getOriginalFilename()) + .replaceFirst("[.][^.]+$", "") + + "_password_removed.pdf"); + } catch (IOException e) { + document.close(); + ExceptionUtils.logException("password removal", e); + throw ExceptionUtils.handlePdfException(e); + } } @PostMapping(consumes = "multipart/form-data", value = "/add-password") diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java similarity index 96% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java index b3f01ef47..a98f0c0d1 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java @@ -41,6 +41,7 @@ import stirling.software.SPDF.model.api.security.SignatureValidationRequest; import stirling.software.SPDF.model.api.security.SignatureValidationResult; import stirling.software.SPDF.service.CertificateValidationService; import stirling.software.common.service.CustomPDFDocumentFactory; +import stirling.software.common.util.ExceptionUtils; @RestController @RequestMapping("/api/v1/security") @@ -82,7 +83,12 @@ public class ValidateSignatureController { CertificateFactory cf = CertificateFactory.getInstance("X.509"); customCert = (X509Certificate) cf.generateCertificate(certStream); } catch (CertificateException e) { - throw new RuntimeException("Invalid certificate file: " + e.getMessage()); + throw ExceptionUtils.createRuntimeException( + "error.invalidFormat", + "Invalid {0} format: {1}", + e, + "certificate file", + e.getMessage()); } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/ConverterWebController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java similarity index 96% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java index 72486a28f..1084e2fe0 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/GeneralWebController.java @@ -29,6 +29,7 @@ import stirling.software.SPDF.service.SignatureService; import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.service.UserServiceInterface; +import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.GeneralUtils; @Controller @@ -263,13 +264,17 @@ public class GeneralWebController { } return null; } catch (Exception e) { - throw new RuntimeException("Error processing filename", e); + throw ExceptionUtils.createRuntimeException( + "error.fontLoadingFailed", + "Error processing font file", + e); } }) .filter(Objects::nonNull) .toList(); } catch (Exception e) { - throw new RuntimeException("Failed to read font directory from " + locationPattern, e); + throw ExceptionUtils.createRuntimeException( + "error.fontDirectoryReadFailed", "Failed to read font directory", e); } } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/SecurityWebController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/SecurityWebController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/SecurityWebController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/SecurityWebController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/SignatureController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/SignatureController.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/SignatureController.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/SignatureController.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/UploadLimitService.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/UploadLimitService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/UploadLimitService.java rename to app/core/src/main/java/stirling/software/SPDF/controller/web/UploadLimitService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java b/app/core/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java rename to app/core/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/Dependency.java b/app/core/src/main/java/stirling/software/SPDF/model/Dependency.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/Dependency.java rename to app/core/src/main/java/stirling/software/SPDF/model/Dependency.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/PDFText.java b/app/core/src/main/java/stirling/software/SPDF/model/PDFText.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/PDFText.java rename to app/core/src/main/java/stirling/software/SPDF/model/PDFText.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/PipelineConfig.java b/app/core/src/main/java/stirling/software/SPDF/model/PipelineConfig.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/PipelineConfig.java rename to app/core/src/main/java/stirling/software/SPDF/model/PipelineConfig.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/PipelineOperation.java b/app/core/src/main/java/stirling/software/SPDF/model/PipelineOperation.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/PipelineOperation.java rename to app/core/src/main/java/stirling/software/SPDF/model/PipelineOperation.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/PipelineResult.java b/app/core/src/main/java/stirling/software/SPDF/model/PipelineResult.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/PipelineResult.java rename to app/core/src/main/java/stirling/software/SPDF/model/PipelineResult.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/SignatureFile.java b/app/core/src/main/java/stirling/software/SPDF/model/SignatureFile.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/SignatureFile.java rename to app/core/src/main/java/stirling/software/SPDF/model/SignatureFile.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/SortTypes.java b/app/core/src/main/java/stirling/software/SPDF/model/SortTypes.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/SortTypes.java rename to app/core/src/main/java/stirling/software/SPDF/model/SortTypes.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/EditTableOfContentsRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/ImageFile.java b/app/core/src/main/java/stirling/software/SPDF/model/api/ImageFile.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/ImageFile.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/ImageFile.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java b/app/core/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java b/app/core/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java b/app/core/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFExtractImagesRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/PDFExtractImagesRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFExtractImagesRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/PDFExtractImagesRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFWithImageFormatRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/PDFWithImageFormatRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFWithImageFormatRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/PDFWithImageFormatRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java b/app/core/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFWithPageSize.java b/app/core/src/main/java/stirling/software/SPDF/model/api/PDFWithPageSize.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/PDFWithPageSize.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/PDFWithPageSize.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertPDFToMarkdown.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToImageRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToImageRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToImageRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToImageRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToPdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToPdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToPdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/ConvertToPdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToBookRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToBookRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToBookRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToBookRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPresentationRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPresentationRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPresentationRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPresentationRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToTextOrRTFRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToTextOrRTFRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToTextOrRTFRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToTextOrRTFRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToWordRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToWordRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/PdfToWordRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToWordRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/UrlToPdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/UrlToPdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/converters/UrlToPdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/converters/UrlToPdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/ContainsTextRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/filter/ContainsTextRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/ContainsTextRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/filter/ContainsTextRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/FileSizeRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/filter/FileSizeRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/FileSizeRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/filter/FileSizeRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/PageRotationRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/filter/PageRotationRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/PageRotationRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/filter/PageRotationRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/PageSizeRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/filter/PageSizeRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/filter/PageSizeRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/filter/PageSizeRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/MergeMultiplePagesRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/MergePdfsRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/MergePdfsRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/MergePdfsRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/MergePdfsRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/OverlayPdfsRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/OverlayPdfsRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/OverlayPdfsRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/OverlayPdfsRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/RearrangePagesRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/RearrangePagesRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/RearrangePagesRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/RearrangePagesRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/RotatePDFRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/ScalePagesRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/ScalePagesRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/ScalePagesRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/ScalePagesRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/SplitPdfBySizeOrCountRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/SplitPdfBySizeOrCountRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/general/SplitPdfBySizeOrCountRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/general/SplitPdfBySizeOrCountRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AddAttachmentRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddAttachmentRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AddAttachmentRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddAttachmentRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AutoSplitPdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/AutoSplitPdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/AutoSplitPdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/AutoSplitPdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ExtractHeaderRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/ExtractHeaderRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ExtractHeaderRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/ExtractHeaderRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ExtractImageScansRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/ExtractImageScansRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ExtractImageScansRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/ExtractImageScansRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/FakeScanRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/FakeScanRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/FakeScanRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/FakeScanRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/MetadataRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/MetadataRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/MetadataRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/MetadataRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/OptimizePdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java similarity index 68% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java index 00279eb96..2955d7160 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java +++ b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java @@ -19,6 +19,18 @@ public class ProcessPdfWithOcrRequest extends PDFFile { defaultValue = "[\"eng\"]") private List languages; + @Schema(description = "Include OCR text in a sidecar text file if set to true") + private boolean sidecar; + + @Schema(description = "Deskew the input file if set to true") + private boolean deskew; + + @Schema(description = "Clean the input file if set to true") + private boolean clean; + + @Schema(description = "Clean the final output if set to true") + private boolean cleanFinal; + @Schema( description = "Specify the OCR type, e.g., 'skip-text', 'force-ocr', or 'Normal'", requiredMode = Schema.RequiredMode.REQUIRED, @@ -31,4 +43,7 @@ public class ProcessPdfWithOcrRequest extends PDFFile { allowableValues = {"hocr", "sandwich"}, defaultValue = "hocr") private String ocrRenderType = "hocr"; + + @Schema(description = "Remove images from the output PDF if set to true") + private boolean removeImagesAfter; } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/RemoveBlankPagesRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/RemoveBlankPagesRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/RemoveBlankPagesRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/RemoveBlankPagesRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ReplaceAndInvertColorRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/misc/ReplaceAndInvertColorRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/misc/ReplaceAndInvertColorRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/misc/ReplaceAndInvertColorRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/ManualRedactPdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/ManualRedactPdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/ManualRedactPdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/ManualRedactPdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationRequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationRequest.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationRequest.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationRequest.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationResult.java b/app/core/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationResult.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationResult.java rename to app/core/src/main/java/stirling/software/SPDF/model/api/security/SignatureValidationResult.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/pdf/FlexibleCSVWriter.java b/app/core/src/main/java/stirling/software/SPDF/pdf/FlexibleCSVWriter.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/pdf/FlexibleCSVWriter.java rename to app/core/src/main/java/stirling/software/SPDF/pdf/FlexibleCSVWriter.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/pdf/TextFinder.java b/app/core/src/main/java/stirling/software/SPDF/pdf/TextFinder.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/pdf/TextFinder.java rename to app/core/src/main/java/stirling/software/SPDF/pdf/TextFinder.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/ApiDocService.java b/app/core/src/main/java/stirling/software/SPDF/service/ApiDocService.java similarity index 99% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/ApiDocService.java rename to app/core/src/main/java/stirling/software/SPDF/service/ApiDocService.java index d5cc76af8..0e46af08d 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/service/ApiDocService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/ApiDocService.java @@ -120,8 +120,8 @@ public class ApiDocService { ObjectMapper mapper = new ObjectMapper(); apiDocsJsonRootNode = mapper.readTree(apiDocsJson); JsonNode paths = apiDocsJsonRootNode.path("paths"); - paths.fields() - .forEachRemaining( + paths.propertyStream() + .forEach( entry -> { String path = entry.getKey(); JsonNode pathNode = entry.getValue(); diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/AttachmentService.java b/app/core/src/main/java/stirling/software/SPDF/service/AttachmentService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/AttachmentService.java rename to app/core/src/main/java/stirling/software/SPDF/service/AttachmentService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/AttachmentServiceInterface.java b/app/core/src/main/java/stirling/software/SPDF/service/AttachmentServiceInterface.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/AttachmentServiceInterface.java rename to app/core/src/main/java/stirling/software/SPDF/service/AttachmentServiceInterface.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/CertificateValidationService.java b/app/core/src/main/java/stirling/software/SPDF/service/CertificateValidationService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/CertificateValidationService.java rename to app/core/src/main/java/stirling/software/SPDF/service/CertificateValidationService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/LanguageService.java b/app/core/src/main/java/stirling/software/SPDF/service/LanguageService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/LanguageService.java rename to app/core/src/main/java/stirling/software/SPDF/service/LanguageService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java b/app/core/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java similarity index 98% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java rename to app/core/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java index acd0669c0..181757a04 100644 --- a/stirling-pdf/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java @@ -77,7 +77,7 @@ public class MetricsAggregatorService { double lastCount = lastSentMetrics.getOrDefault(key, 0.0); double difference = currentCount - lastCount; if (difference > 0) { - logger.info("{}, {}", key, difference); + logger.debug("{}, {}", key, difference); metrics.put(key, difference); lastSentMetrics.put(key, currentCount); } diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/PdfImageRemovalService.java b/app/core/src/main/java/stirling/software/SPDF/service/PdfImageRemovalService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/PdfImageRemovalService.java rename to app/core/src/main/java/stirling/software/SPDF/service/PdfImageRemovalService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/SignatureService.java b/app/core/src/main/java/stirling/software/SPDF/service/SignatureService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/SignatureService.java rename to app/core/src/main/java/stirling/software/SPDF/service/SignatureService.java diff --git a/stirling-pdf/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java b/app/core/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java similarity index 100% rename from stirling-pdf/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java rename to app/core/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java diff --git a/stirling-pdf/src/main/java/stirling/software/common/controller/JobController.java b/app/core/src/main/java/stirling/software/common/controller/JobController.java similarity index 51% rename from stirling-pdf/src/main/java/stirling/software/common/controller/JobController.java rename to app/core/src/main/java/stirling/software/common/controller/JobController.java index 510488a64..44b15265b 100644 --- a/stirling-pdf/src/main/java/stirling/software/common/controller/JobController.java +++ b/app/core/src/main/java/stirling/software/common/controller/JobController.java @@ -1,7 +1,11 @@ package stirling.software.common.controller; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Map; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -14,6 +18,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.common.model.job.JobResult; +import stirling.software.common.model.job.ResultFile; import stirling.software.common.service.FileStorage; import stirling.software.common.service.JobQueue; import stirling.software.common.service.TaskManager; @@ -78,16 +83,31 @@ public class JobController { return ResponseEntity.badRequest().body("Job failed: " + result.getError()); } - if (result.getFileId() != null) { + // Handle multiple files - return metadata for client to download individually + if (result.hasMultipleFiles()) { + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body( + Map.of( + "jobId", + jobId, + "hasMultipleFiles", + true, + "files", + result.getAllResultFiles())); + } + + // Handle single file (download directly) + if (result.hasFiles() && !result.hasMultipleFiles()) { try { - byte[] fileContent = fileStorage.retrieveBytes(result.getFileId()); + List files = result.getAllResultFiles(); + ResultFile singleFile = files.get(0); + byte[] fileContent = fileStorage.retrieveBytes(singleFile.getFileId()); return ResponseEntity.ok() - .header("Content-Type", result.getContentType()) + .header("Content-Type", singleFile.getContentType()) .header( "Content-Disposition", - "form-data; name=\"attachment\"; filename=\"" - + result.getOriginalFileName() - + "\"") + createContentDispositionHeader(singleFile.getFileName())) .body(fileContent); } catch (Exception e) { log.error("Error retrieving file for job {}: {}", jobId, e.getMessage(), e); @@ -170,4 +190,127 @@ public class JobController { } } } + + /** + * Get the list of files for a job + * + * @param jobId The job ID + * @return List of files for the job + */ + @GetMapping("/api/v1/general/job/{jobId}/result/files") + public ResponseEntity getJobFiles(@PathVariable("jobId") String jobId) { + JobResult result = taskManager.getJobResult(jobId); + if (result == null) { + return ResponseEntity.notFound().build(); + } + + if (!result.isComplete()) { + return ResponseEntity.badRequest().body("Job is not complete yet"); + } + + if (result.getError() != null) { + return ResponseEntity.badRequest().body("Job failed: " + result.getError()); + } + + List files = result.getAllResultFiles(); + return ResponseEntity.ok( + Map.of( + "jobId", jobId, + "fileCount", files.size(), + "files", files)); + } + + /** + * Get metadata for an individual file by its file ID + * + * @param fileId The file ID + * @return The file metadata + */ + @GetMapping("/api/v1/general/files/{fileId}/metadata") + public ResponseEntity getFileMetadata(@PathVariable("fileId") String fileId) { + try { + // Verify file exists + if (!fileStorage.fileExists(fileId)) { + return ResponseEntity.notFound().build(); + } + + // Find the file metadata from any job that contains this file + ResultFile resultFile = taskManager.findResultFileByFileId(fileId); + + if (resultFile != null) { + return ResponseEntity.ok(resultFile); + } else { + // File exists but no metadata found, get basic info efficiently + long fileSize = fileStorage.getFileSize(fileId); + return ResponseEntity.ok( + Map.of( + "fileId", + fileId, + "fileName", + "unknown", + "contentType", + "application/octet-stream", + "fileSize", + fileSize)); + } + } catch (Exception e) { + log.error("Error retrieving file metadata {}: {}", fileId, e.getMessage(), e); + return ResponseEntity.internalServerError() + .body("Error retrieving file metadata: " + e.getMessage()); + } + } + + /** + * Download an individual file by its file ID + * + * @param fileId The file ID + * @return The file content + */ + @GetMapping("/api/v1/general/files/{fileId}") + public ResponseEntity downloadFile(@PathVariable("fileId") String fileId) { + try { + // Verify file exists + if (!fileStorage.fileExists(fileId)) { + return ResponseEntity.notFound().build(); + } + + // Retrieve file content + byte[] fileContent = fileStorage.retrieveBytes(fileId); + + // Find the file metadata from any job that contains this file + // This is for getting the original filename and content type + ResultFile resultFile = taskManager.findResultFileByFileId(fileId); + + String fileName = resultFile != null ? resultFile.getFileName() : "download"; + String contentType = + resultFile != null ? resultFile.getContentType() : "application/octet-stream"; + + return ResponseEntity.ok() + .header("Content-Type", contentType) + .header("Content-Disposition", createContentDispositionHeader(fileName)) + .body(fileContent); + } catch (Exception e) { + log.error("Error retrieving file {}: {}", fileId, e.getMessage(), e); + return ResponseEntity.internalServerError() + .body("Error retrieving file: " + e.getMessage()); + } + } + + /** + * Create Content-Disposition header with UTF-8 filename support + * + * @param fileName The filename to encode + * @return Content-Disposition header value + */ + private String createContentDispositionHeader(String fileName) { + try { + String encodedFileName = + URLEncoder.encode(fileName, StandardCharsets.UTF_8) + .replace("+", "%20"); // URLEncoder uses + for spaces, but we want %20 + return "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + encodedFileName; + } catch (Exception e) { + // Fallback to basic filename if encoding fails + return "attachment; filename=\"" + fileName + "\""; + } + } } diff --git a/stirling-pdf/src/main/resources/application.properties b/app/core/src/main/resources/application.properties similarity index 100% rename from stirling-pdf/src/main/resources/application.properties rename to app/core/src/main/resources/application.properties diff --git a/stirling-pdf/src/main/resources/banner.txt b/app/core/src/main/resources/banner.txt similarity index 100% rename from stirling-pdf/src/main/resources/banner.txt rename to app/core/src/main/resources/banner.txt diff --git a/stirling-pdf/src/main/resources/certdata.txt b/app/core/src/main/resources/certdata.txt similarity index 100% rename from stirling-pdf/src/main/resources/certdata.txt rename to app/core/src/main/resources/certdata.txt diff --git a/stirling-pdf/src/main/resources/icc/sRGB2014.icc b/app/core/src/main/resources/icc/sRGB2014.icc similarity index 100% rename from stirling-pdf/src/main/resources/icc/sRGB2014.icc rename to app/core/src/main/resources/icc/sRGB2014.icc diff --git a/stirling-pdf/src/main/resources/logback.xml b/app/core/src/main/resources/logback.xml similarity index 96% rename from stirling-pdf/src/main/resources/logback.xml rename to app/core/src/main/resources/logback.xml index d521d42a8..c0779735a 100644 --- a/stirling-pdf/src/main/resources/logback.xml +++ b/app/core/src/main/resources/logback.xml @@ -40,7 +40,7 @@ - diff --git a/stirling-pdf/src/main/resources/messages.properties b/app/core/src/main/resources/messages.properties similarity index 100% rename from stirling-pdf/src/main/resources/messages.properties rename to app/core/src/main/resources/messages.properties diff --git a/stirling-pdf/src/main/resources/messages_ar_AR.properties b/app/core/src/main/resources/messages_ar_AR.properties similarity index 95% rename from stirling-pdf/src/main/resources/messages_ar_AR.properties rename to app/core/src/main/resources/messages_ar_AR.properties index 36617425a..4691fa989 100644 --- a/stirling-pdf/src/main/resources/messages_ar_AR.properties +++ b/app/core/src/main/resources/messages_ar_AR.properties @@ -163,13 +163,74 @@ alphabet=الأبجدية downloadPdf=تنزيل PDF text=نص font=الخط -selectFillter=- حدد - +selectFilter=- حدد - pageNum=رقم الصفحة sizes.small=صغير sizes.medium=وسط sizes.large=كبير sizes.x-large=كبير جدا error.pdfPassword=ملف PDF محمي بكلمة مرور ولم يتم تقديم كلمة المرور أو كانت غير صحيحة +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=حذف username=اسم المستخدم password=كلمة المرور @@ -181,7 +242,6 @@ red=أحمر green=أخضر blue=أزرق custom=مخصص... -WorkInProgess=العمل قيد التقدم، قد لا يعمل أو يحتوي على أخطاء، يرجى الإبلاغ عن أي مشاكل! poweredBy=مدعوم بواسطة yes=نعم no=لا @@ -525,6 +585,10 @@ home.addImage.title=إضافة صورة إلى ملف PDF home.addImage.desc=إضافة صورة إلى موقع معين في PDF (العمل قيد التقدم) addImage.tags=صورة,jpg,صورة,صورة فوتوغرافية +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=إضافة علامة مائية home.watermark.desc=أضف علامة مائية مخصصة إلى مستند PDF الخاص بك. watermark.tags=نص,تكرار,تسمية,خاص,حقوق النشر,علامة تجارية,صورة,jpg,صورة,صورة فوتوغرافية @@ -1205,6 +1269,12 @@ addImage.everyPage=كل صفحة؟ addImage.upload=إضافة صورة addImage.submit=إضافة صورة +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=دمج @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=قم بسحب المفات وإفلاتها هنا fileChooser.extractPDF=جاري الاستخراج... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_az_AZ.properties b/app/core/src/main/resources/messages_az_AZ.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_az_AZ.properties rename to app/core/src/main/resources/messages_az_AZ.properties index bde60af71..79ebfdcdb 100644 --- a/stirling-pdf/src/main/resources/messages_az_AZ.properties +++ b/app/core/src/main/resources/messages_az_AZ.properties @@ -163,13 +163,74 @@ alphabet=Əlifba downloadPdf=PDF Yüklə text=Yazı font=Şrift -selectFillter=-- Seç -- +selectFilter=-- Seç -- pageNum=Səhifə nömrəsi sizes.small=Kiçik sizes.medium=Orta sizes.large=Böyük sizes.x-large=Ekstra Böyük error.pdfPassword=PDF sənədi şifrlənmişdir və şifr təmin edilməmişdir və ya yanlışdır. +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Sil username=İstifadəçi Adı password=Şifr @@ -181,7 +242,6 @@ red=Qırmızı green=Yaşıl blue=Mavi custom=Xüsusi... -WorkInProgess=İş davam edir, İşləməyə bilər və ya xətalarla üzləşə bilərsiniz, Zəhmət olmasa problemləri bildirin! poweredBy=Təchiz edilmişdir yes=Bəli no=Xeyr @@ -525,6 +585,10 @@ home.addImage.title=Şəkil əlavə et home.addImage.desc=PDF-də təyin edilmiş yerə şəkil əlavə edir addImage.tags=şəkil,jpg,fotoşəkil,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Watermark əlavə et home.watermark.desc=PDF sənədinə fərdi watermark əlavə et. watermark.tags=Mətn,təkrarlanan,nişan,sahib olmaq,müəllif hüquqları,əmtəə nişanı,şəkil,jpg,fotoşəkil,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Bütün Səhifələr? addImage.upload=Şəkli Əlavə Et addImage.submit=Şəkli Əlavə Et +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Birləşdirin @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Buraxılışlar diff --git a/stirling-pdf/src/main/resources/messages_bg_BG.properties b/app/core/src/main/resources/messages_bg_BG.properties similarity index 95% rename from stirling-pdf/src/main/resources/messages_bg_BG.properties rename to app/core/src/main/resources/messages_bg_BG.properties index a7167eead..a5f12ec06 100644 --- a/stirling-pdf/src/main/resources/messages_bg_BG.properties +++ b/app/core/src/main/resources/messages_bg_BG.properties @@ -163,13 +163,74 @@ alphabet=Азбука downloadPdf=Изтеглете PDF text=Текст font=Шрифт -selectFillter=-- Изберете -- +selectFilter=-- Изберете -- pageNum=Брой страница sizes.small=Малък sizes.medium=Среден sizes.large=Голям sizes.x-large=X-Голям error.pdfPassword=PDF документът е с парола и или паролата не е предоставена, или е неправилна +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Изтрий username=Потребителско име password=Парола @@ -181,7 +242,6 @@ red=Червено green=Зелено blue=Синьо custom=Персонализиране... -WorkInProgess=Работата е в ход, може да не работи или да има грешки, моля, докладвайте за проблеми! poweredBy=Задвижван чрез yes=Да no=Не @@ -525,6 +585,10 @@ home.addImage.title=Добавяне на изображение home.addImage.desc=Добавя изображение към зададено място към PDF файла addImage.tags=img,jpg,изображение,снимка +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Добавяне на воден знак home.watermark.desc=Добавете персонализиран воден знак към вашия PDF документ. watermark.tags=Текст,повтарящ се,етикет,собствено,авторско право,търговска марка,img,jpg,изображение,снимка @@ -1205,6 +1269,12 @@ addImage.everyPage=Всяка страница? addImage.upload=Добавяне на изображение addImage.submit=Добавяне на изображение +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Обединяване @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Влачете и пуснете PDF файл fileChooser.dragAndDropImage=Влачете и пуснете изображение fileChooser.hoveredDragAndDrop=Влачете и пуснете файл(ове) тук fileChooser.extractPDF=Извличане... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Версии diff --git a/stirling-pdf/src/main/resources/messages_bo_CN.properties b/app/core/src/main/resources/messages_bo_CN.properties similarity index 96% rename from stirling-pdf/src/main/resources/messages_bo_CN.properties rename to app/core/src/main/resources/messages_bo_CN.properties index e0fdbf651..87cf84b24 100644 --- a/stirling-pdf/src/main/resources/messages_bo_CN.properties +++ b/app/core/src/main/resources/messages_bo_CN.properties @@ -163,13 +163,74 @@ alphabet=གསལ་བྱེད། downloadPdf=PDF ཕབ་ལེན། text=ཡི་གེ font=ཡིག་གཟུགས་ཌྷ -selectFillter=-- འདེམས་རོགས། -- +selectFilter=-- འདེམས་རོགས། -- pageNum=ཤོག་གིངས། sizes.small=ཆུང་ཆང་། sizes.medium=འབྲིང་ཚད། sizes.large=ཆེན་པོ། sizes.x-large=ཧ་ཅང་ཆེན་པོ། error.pdfPassword=PDF ཡིག་ཆར་གསང་ཚིག་བཀོད་ཡོད་པ་དང་། གསང་ཚིག་མ་བཀོད་པའམ་ནོར་འདུག +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=སུབ་པ། username=སྤྱོད་མཁན་མིང་། password=གསང་ཚིག། @@ -181,7 +242,6 @@ red=དམར་པོ green=ལྗང་ཁུ། blue=སྔོན་པོ custom=མཚན་ཉིད་རང་སྒྲིག... -WorkInProgess=ལས་ཀ་བྱེད་བཞིན་པ། ནོར་འཁྲུལ་ཡོང་སྲིད། དཀའ་ངལ་ཡོད་ཚེ་སྙན་སེང་གནང་རོགས། poweredBy=མཁོ་སྲོད་བྱེད་མཁན། yes=ཡིན། no=མིན། @@ -525,6 +585,10 @@ home.addImage.title=པར་རིས་སྣོན་པ། home.addImage.desc=PDF ནང་གནས་ས་ངེས་ཅན་ཞིག་ཏུ་པར་རིས་སྣོན་པ། addImage.tags=པར་རིས།,jpg,པར།,འདྲ་པར། +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=ཆུ་རྟགས་སྣོན་པ། home.watermark.desc=PDF ཡིག་ཆར་རང་སྒྲིག་གི་ཆུ་རྟགས་སྣོན་པ། watermark.tags=ཡི་གེ,བསྐྱར་ཟློས།,ཁ་ཡིག,རང་དབང་།,པར་དབང་།,ཚོང་རྟགས།,པར་རིས།,jpg,པར།,འདྲ་པར། @@ -1205,6 +1269,12 @@ addImage.everyPage=ཤོག་ངོས་ཚང་མར་ཡིན་ནམ addImage.upload=པར་རིས་སྣོན་པ། addImage.submit=པར་རིས་སྣོན་པ། +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=སྡེབ་སྦྱོར། @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=PDF ཡིག་ཆ་འཐེན་ནས་འཇ fileChooser.dragAndDropImage=པར་རིས་ཡིག་ཆ་འཐེན་ནས་འཇོག་པ། fileChooser.hoveredDragAndDrop=ཡིག་ཆ་འདིར་འཐེན་ནས་འཇོག་པ། fileChooser.extractPDF=འདོན་རིས་འགྱུར་བའི་སྒྲིག་བཏང་བ། +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=པར་གཞི། diff --git a/stirling-pdf/src/main/resources/messages_ca_CA.properties b/app/core/src/main/resources/messages_ca_CA.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_ca_CA.properties rename to app/core/src/main/resources/messages_ca_CA.properties index 063f8393e..488ac87a8 100644 --- a/stirling-pdf/src/main/resources/messages_ca_CA.properties +++ b/app/core/src/main/resources/messages_ca_CA.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=Descarregueu PDF text=Text font=Tipus de lletra -selectFillter=-- Selecciona -- +selectFilter=-- Selecciona -- pageNum=Número de pàgina sizes.small=Petit sizes.medium=Mitjà sizes.large=Llarg sizes.x-large=X-Large error.pdfPassword=El PDF està protegit o bé el password és incorrecte +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Esborra username=Usuari password=Contrasenya @@ -181,7 +242,6 @@ red=Vermell green=Verd blue=Blau custom=Personalitzat... -WorkInProgess=En desenvolupament, pot no funcionar o contenir errors. Si us plau, informa de qualsevol problema! poweredBy=Impulsat per yes=Si no=No @@ -525,6 +585,10 @@ home.addImage.title=Afegir imatge a PDF home.addImage.desc=Afegeix una imatge en un PDF (en progrés) addImage.tags=img,jpg,imatge,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Afegir Marca d'aigua home.watermark.desc=Afegir una marca d'aigua personalitzada en un PDF watermark.tags=text,repetició,etiqueta,propia,copyright,marca registrada,img,jpg,imatge,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Totes les pàgines? addImage.upload=Afegir Imatge addImage.submit=Afegir Imatge +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Fusiona @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Arrossega i deixa anar un fitxer PDF fileChooser.dragAndDropImage=Arrossega i deixa anar un fitxer d'imatge fileChooser.hoveredDragAndDrop=Arrossega i deixa anar fitxer(s) aquí fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Llançaments diff --git a/stirling-pdf/src/main/resources/messages_cs_CZ.properties b/app/core/src/main/resources/messages_cs_CZ.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_cs_CZ.properties rename to app/core/src/main/resources/messages_cs_CZ.properties index 41a2ae9f9..ab0b45b4d 100644 --- a/stirling-pdf/src/main/resources/messages_cs_CZ.properties +++ b/app/core/src/main/resources/messages_cs_CZ.properties @@ -163,13 +163,74 @@ alphabet=Abeceda downloadPdf=Stáhnout PDF text=Text font=Písmo -selectFillter=-- Vybrat -- +selectFilter=-- Vybrat -- pageNum=Číslo stránky sizes.small=Malé sizes.medium=Střední sizes.large=Velké sizes.x-large=Extra velké error.pdfPassword=PDF dokument je chráněn heslem a buď heslo nebylo zadáno, nebo bylo nesprávné +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Smazat username=Uživatelské jméno password=Heslo @@ -181,7 +242,6 @@ red=Červená green=Zelená blue=Modrá custom=Vlastní... -WorkInProgess=Práce probíhá, nemusí fungovat nebo může obsahovat chyby. Prosím, nahlaste případné problémy! poweredBy=Využívá yes=Ano no=Ne @@ -525,6 +585,10 @@ home.addImage.title=Přidat obrázek home.addImage.desc=Přidá obrázek na určené místo v PDF addImage.tags=img,jpg,obrázek,fotka +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Přidat vodoznak home.watermark.desc=Přidat vlastní vodoznak do vašeho PDF dokumentu. watermark.tags=Text,opakující se,popisek,vlastní,copyright,ochranná známka,img,jpg,obrázek,fotka @@ -1205,6 +1269,12 @@ addImage.everyPage=Každá stránka? addImage.upload=Přidat obrázek addImage.submit=Přidat obrázek +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Sloučit @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Přetáhnout PDF soubor fileChooser.dragAndDropImage=Přetáhnout obrázek fileChooser.hoveredDragAndDrop=Přetáhněte soubor(y) sem fileChooser.extractPDF=Extrahování... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Vydání diff --git a/stirling-pdf/src/main/resources/messages_da_DK.properties b/app/core/src/main/resources/messages_da_DK.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_da_DK.properties rename to app/core/src/main/resources/messages_da_DK.properties index 31a2193f4..ba2b18cf5 100644 --- a/stirling-pdf/src/main/resources/messages_da_DK.properties +++ b/app/core/src/main/resources/messages_da_DK.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=Download PDF text=Tekst font=Skrifttype -selectFillter=-- Vælg -- +selectFilter=-- Vælg -- pageNum=Sidenummer sizes.small=Lille sizes.medium=Mellem sizes.large=Stor sizes.x-large=X-Stor error.pdfPassword=PDF-dokumentet er beskyttet med adgangskode, og enten blev adgangskoden ikke angivet eller var forkert +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Slet username=Brugernavn password=Adgangskode @@ -181,7 +242,6 @@ red=Rød green=Grøn blue=Blå custom=Brugerdefineret... -WorkInProgess=Arbejde i gang, Kan muligvis ikke virke eller have fejl, Rapportér venligst eventuelle problemer! poweredBy=Drevet af yes=Ja no=Nej @@ -525,6 +585,10 @@ home.addImage.title=Tilføj billede home.addImage.desc=Tilføjer et billede på en bestemt placering på PDF'en addImage.tags=img,jpg,billede,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Tilføj Vandmærke home.watermark.desc=Tilføj et brugerdefineret vandmærke til dit PDF-dokument. watermark.tags=Tekst,gentagne,etiket,egen,ophavsret,varemærke,img,jpg,billede,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Hver Side? addImage.upload=Tilføj billede addImage.submit=Tilføj billede +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Flet @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_de_DE.properties b/app/core/src/main/resources/messages_de_DE.properties similarity index 86% rename from stirling-pdf/src/main/resources/messages_de_DE.properties rename to app/core/src/main/resources/messages_de_DE.properties index ac69fdd8e..207a36007 100644 --- a/stirling-pdf/src/main/resources/messages_de_DE.properties +++ b/app/core/src/main/resources/messages_de_DE.properties @@ -138,7 +138,7 @@ lang.yor=Yoruba addPageNumbers.fontSize=Schriftgröße addPageNumbers.fontName=Schriftart pdfPrompt=PDF(s) auswählen -multiPdfPrompt=PDFs auswählen(2+) +multiPdfPrompt=PDFs auswählen (2+) multiPdfDropPrompt=Wählen Sie alle gewünschten PDFs aus (oder ziehen Sie sie per Drag & Drop hierhin) imgPrompt=Wählen Sie ein Bild genericSubmit=Absenden @@ -146,7 +146,7 @@ uploadLimit=Maximale Dateigröße: uploadLimitExceededSingular=ist zu groß. Die maximal zulässige Größe ist uploadLimitExceededPlural=sind zu groß. Die maximal zulässige Größe ist processTimeWarning=Achtung: Abhängig von der Dateigröße kann dieser Prozess bis zu einer Minute dauern -pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Komma getrennte Liste von Seitenzahlen ein): +pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Kommas getrennte Liste von Seitenzahlen ein): pageSelectionPrompt=Benutzerdefinierte Seitenauswahl (Geben Sie eine durch Kommas getrennte Liste von Seitenzahlen 1,5,6 oder Funktionen wie 2n+1 ein): goToPage=Los true=Wahr @@ -163,13 +163,74 @@ alphabet=Alphabet downloadPdf=PDF herunterladen text=Text font=Schriftart -selectFillter=-- Auswählen -- +selectFilter=-- Auswählen -- pageNum=Seitenzahl sizes.small=Klein sizes.medium=Mittel sizes.large=Groß sizes.x-large=Extra Groß error.pdfPassword=Das PDF-Dokument ist passwortgeschützt und das Passwort wurde entweder nicht angegeben oder war falsch +error.pdfCorrupted=Die PDF-Datei scheint beschädigt zu sein. Bitte nutzen Sie zuerst die Funktion "PDFs reparieren", um die Datei zu beheben, bevor Sie fortfahren. +error.pdfCorruptedMultiple=Eine oder mehrere PDF-Dateien scheinen beschädigt zu sein. Bitte versuchen Sie, jede Datei zunächst mit der Funktion "PDFs reparieren" zu korrigieren, bevor Sie sie zusammenführen. +error.pdfCorruptedDuring=Fehler {0}: Die PDF-Datei scheint beschädigt zu sein. Bitte nutzen Sie zuerst die Funktion "PDFs reparieren", um die Datei zu beheben, bevor Sie fortfahren. + +# Frontend corruption error messages +error.pdfInvalid=Die PDF-Datei "{0}" scheint beschädigt oder ungültig zu sein. Bitte versuchen Sie, die Datei mit der Funktion "PDFs reparieren" zu beheben. +error.tryRepair=Versuchen Sie, beschädigte Dateien mit der Funktion "PDFs reparieren" zu beheben. + +# Additional error messages +error.pdfEncryption=Die PDF-Datei enthält möglicherweise beschädigte Verschlüsselungsdaten. Dies kann auftreten, wenn sie mit inkompatiblen Methoden erstellt wurde. Bitte versuchen Sie zunächst die Funktion "PDFs reparieren" oder kontaktieren Sie den Ersteller für eine neue Kopie. +error.fileProcessing=Beim Verarbeiten der Datei während des Vorgangs {0} ist ein Fehler aufgetreten: {1} + +# Generic error message templates +error.toolNotInstalled={0} ist nicht installiert. +error.toolRequired={0} wird für {1} benötigt. +error.conversionFailed={0} Konvertierung fehlgeschlagen +error.commandFailed={0} Befehl fehlgeschlagen +error.algorithmNotAvailable={0}-Algorithmus nicht verfügbar +error.optionsNotSpecified=Optionen für {0} wurden nicht angegeben. +error.fileFormatRequired=Die Datei muss im Format {0} vorliegen. +error.invalidFormat=Ungültiges {0}-Format: {1} +error.endpointDisabled=Dieser Endpunkt wurde vom Administrator deaktiviert. +error.urlNotReachable=Die URL ist nicht erreichbar, bitte geben Sie eine gültige URL an. + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=Der DPI-Wert {0} überschreitet das sichere Maximum von {1}. Hohe DPI-Werte können zu Speicherproblemen und Abstürzen führen. Bitte verwende einen niedrigeren DPI-Wert. +error.pageTooBigForDpi=Die PDF-Seite {0} ist zu groß, um mit {1} DPI gerendert zu werden. Bitte versuche einen niedrigeren DPI-Wert (empfohlen: 150 oder weniger). +error.pageTooBigExceedsArray=Die PDF-Seite {0} ist zu groß, um mit {1} DPI gerendert zu werden. Das Ergebnis überschreitet die zulässige Größe. Bitte versuche einen niedrigeren DPI-Wert (empfohlen: 150 oder weniger). +error.pageTooBigFor300Dpi=Die PDF-Seite {0} ist zu groß, um mit 300 DPI gerendert zu werden. Das Ergebnis überschreitet die zulässige Größe. Bitte verwende für die PDF-zu-Bild-Konvertierung einen niedrigeren DPI-Wert. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API-Schlüssel ist ungültig. +error.userNotFound=Benutzer nicht gefunden. +error.passwordRequired=Passwort darf nicht leer sein. +error.accountLocked=Ihr Konto wurde aufgrund zu vieler fehlgeschlagener Anmeldeversuche gesperrt. +error.invalidEmail=Ungültige E-Mail-Adressen angegeben. +error.emailAttachmentRequired=Für das Versenden der E-Mail ist ein Anhang erforderlich. +error.signatureNotFound=Signaturdatei nicht gefunden. + +# File processing messages +error.fileNotFound=Datei mit der ID {0} nicht gefunden. + +# Database and configuration messages +error.noBackupScripts=Keine Backup-Skripte gefunden. +error.unsupportedProvider={0} wird derzeit nicht unterstützt. +error.pathTraversalDetected=Pfad-Traversal aus Sicherheitsgründen erkannt. + +# Validation messages +error.invalidArgument=Ungültiges Argument: {0} +error.argumentRequired={0} darf nicht null sein. +error.operationFailed=Vorgang fehlgeschlagen: {0} +error.angleNotMultipleOf90=Der Winkel muss ein Vielfaches von 90 sein. +error.pdfBookmarksNotFound=Keine PDF-Lesezeichen/Gliederung im Dokument gefunden. +error.fontLoadingFailed=Fehler bei der Verarbeitung der Schriftdatei. +error.fontDirectoryReadFailed=Konnte das Schriftverzeichnis nicht lesen. delete=Löschen username=Benutzername password=Passwort @@ -181,7 +242,6 @@ red=Rot green=Grün blue=Blau custom=benutzerdefiniert... -WorkInProgess=In Arbeit, funktioniert möglicherweise nicht oder ist fehlerhaft. Bitte melden Sie alle Probleme! poweredBy=Unterstützt von yes=Ja no=Nein @@ -200,7 +260,7 @@ disabledCurrentUserMessage=Der aktuelle Benutzer kann nicht deaktiviert werden downgradeCurrentUserLongMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden. Daher wird der aktuelle Benutzer nicht angezeigt. userAlreadyExistsOAuthMessage=Der Benutzer ist bereits als OAuth2-Benutzer vorhanden. userAlreadyExistsWebMessage=Der Benutzer ist bereits als Webbenutzer vorhanden. -invalidRoleMessage=Invalid role. +invalidRoleMessage=Ungültige Rolle. error=Fehler oops=Hoppla! help=Hilfe @@ -213,7 +273,7 @@ color=Farbe sponsor=Sponsor info=Informationen pro=Pro -proFeatures=Pro Features +proFeatures=Pro-Funktionen page=Seite pages=Seiten loading=Laden... @@ -244,7 +304,7 @@ pipeline.configureButton=Konfigurieren pipeline.defaultOption=Benutzerdefiniert pipeline.submitButton=Ausführen pipeline.help=Hilfe für Pipeline -pipeline.scanHelp=Hilfe zum Ordnerscan +pipeline.scanHelp=Hilfe zum Ordner-Scan pipeline.deletePrompt=Möchten Sie die Pipeline wirklich löschen? ###################### @@ -275,7 +335,7 @@ enterpriseEdition.proTeamFeatureDisabled=Teammanagementfunktionen erfordern eine ################# analytics.title=Möchten Sie Stirling-PDF verbessern? 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=Bitte erwägen Sie die Analytics zu aktivieren, um Stirling-PDF beim Wachsen zu helfen und um unsere User besser zu verstehen. +analytics.paragraph2=Bitte erwägen Sie, Analytics zu aktivieren, um Stirling-PDF beim Wachstum zu unterstützen und um unsere Benutzer besser zu verstehen. analytics.enable=Analytics aktivieren analytics.disable=Analytics deaktivieren analytics.settings=Sie können die Einstellungen für die Analytics in der config/settings.yml Datei bearbeiten @@ -525,6 +585,10 @@ home.addImage.title=Bild einfügen home.addImage.desc=Fügt ein Bild an eine bestimmte Stelle im PDF ein (in Arbeit) addImage.tags=img,jpg,bild,foto +home.attachments.title=Anhänge hinzufügen +home.attachments.desc=Eingebettete Dateien (Anhänge) zu einem PDF hinzufügen oder daraus entfernen +attachments.tags=einbetten, anhängen, datei, anhang, anhänge + home.watermark.title=Wasserzeichen hinzufügen home.watermark.desc=Fügen Sie ein eigenes Wasserzeichen zu Ihrem PDF hinzu watermark.tags=text,wiederholend,beschriftung,besitzen,urheberrecht,marke,img,jpg,bild,foto @@ -607,7 +671,7 @@ home.flatten.title=Abflachen home.flatten.desc=Alle interaktiven Elemente und Formulare aus einem PDF entfernen flatten.tags=statisch,deaktivieren,nicht interaktiv,optimieren -home.repair.title=Reparatur +home.repair.title=PDFs reparieren home.repair.desc=Versucht, ein beschädigtes/kaputtes PDF zu reparieren repair.tags=reparieren,wiederherstellen,korrigieren,wiederherstellen @@ -676,21 +740,21 @@ home.HTMLToPDF.desc=Konvertiert jede HTML-Datei oder Zip-Archiv zu PDF HTMLToPDF.tags=markup,webinhalt,transformation,konvertierung #eml-to-pdf -home.EMLToPDF.title=Email to PDF -home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images -EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail +home.EMLToPDF.title=E-Mail zu PDF +home.EMLToPDF.desc=Konvertiert E-Mail-(EML-)Dateien inklusive Kopfzeilen, Text und eingebetteten Bildern in das PDF-Format +EMLToPDF.tags=e-mail,conversion,eml,nachricht,transformation,konvertieren,mail -EMLToPDF.title=Email To PDF -EMLToPDF.header=Email To PDF -EMLToPDF.submit=Convert -EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF -EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues -EMLToPDF.includeAttachments=Include attachments in PDF -EMLToPDF.maxAttachmentSize=Maximum attachment size (MB) -EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images -EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both -EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code. -EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs +EMLToPDF.title=E-Mail zu PDF +EMLToPDF.header=E-Mail zu PDF +EMLToPDF.submit=Konvertieren +EMLToPDF.downloadHtml=HTML-Zwischendatei statt PDF herunterladen +EMLToPDF.downloadHtmlHelp=Damit können Sie die HTML-Version vor der PDF-Konvertierung ansehen und Formatierungsprobleme beheben +EMLToPDF.includeAttachments=Anhänge in PDF einfügen +EMLToPDF.maxAttachmentSize=Maximale Anhangsgröße (MB) +EMLToPDF.help=Konvertiert E-Mail-(EML-)Dateien inklusive Kopfzeilen, Text und eingebetteten Bildern in das PDF-Format +EMLToPDF.troubleshootingTip1=E-Mail zu HTML ist zuverlässiger, daher wird bei Stapelverarbeitung empfohlen, beide Versionen zu speichern +EMLToPDF.troubleshootingTip2=Bei wenigen E-Mails können Sie bei fehlerhaftem PDF das HTML herunterladen und problematischen HTML/CSS-Code anpassen +EMLToPDF.troubleshootingTip3=Einbettungen funktionieren jedoch nicht mit HTML-Dateien home.MarkdownToPDF.title=Markdown zu PDF home.MarkdownToPDF.desc=Konvertiert jede Markdown-Datei zu PDF @@ -877,28 +941,28 @@ getPdfInfo.title=Alle Informationen anzeigen getPdfInfo.header=Alle Informationen anzeigen getPdfInfo.submit=Informationen anzeigen getPdfInfo.downloadJson=Als JSON herunterladen -getPdfInfo.summary=PDF Summary -getPdfInfo.summary.encrypted=This PDF is encrypted so may face issues with some applications -getPdfInfo.summary.permissions=This PDF has {0} restricted permissions which may limit what you can do with it -getPdfInfo.summary.compliance=This PDF complies with the {0} standard -getPdfInfo.summary.basicInfo=Basic Information -getPdfInfo.summary.docInfo=Document Information -getPdfInfo.summary.encrypted.alert=Encrypted PDF - This document is password protected -getPdfInfo.summary.not.encrypted.alert=Unencrypted PDF - No password protection -getPdfInfo.summary.permissions.alert=Restricted Permissions - {0} actions are not allowed -getPdfInfo.summary.all.permissions.alert=All Permissions Allowed -getPdfInfo.summary.compliance.alert={0} Compliant -getPdfInfo.summary.no.compliance.alert=No Compliance Standards -getPdfInfo.summary.security.section=Security Status -getPdfInfo.section.BasicInfo=Basic Information about the PDF document including file size, page count, and language -getPdfInfo.section.Metadata=Document metadata including title, author, creation date and other document properties -getPdfInfo.section.DocumentInfo=Technical details about the PDF document structure and version -getPdfInfo.section.Compliancy=PDF standards compliance information (PDF/A, PDF/X, etc.) -getPdfInfo.section.Encryption=Security and encryption details of the document -getPdfInfo.section.Permissions=Document permission settings that control what actions can be performed -getPdfInfo.section.Other=Additional document components like bookmarks, layers, and embedded files -getPdfInfo.section.FormFields=Interactive form fields present in the document -getPdfInfo.section.PerPageInfo=Detailed information about each page in the document +getPdfInfo.summary=PDF-Zusammenfassung +getPdfInfo.summary.encrypted=Dieses PDF ist verschlüsselt und kann in manchen Anwendungen Probleme verursachen. +getPdfInfo.summary.permissions=Dieses PDF hat {0} eingeschränkte Berechtigungen, was Ihre Möglichkeiten einschränken kann. +getPdfInfo.summary.compliance=Dieses PDF entspricht dem Standard {0}. +getPdfInfo.summary.basicInfo=Grundlegende Informationen +getPdfInfo.summary.docInfo=Dokumentinformationen +getPdfInfo.summary.encrypted.alert=Verschlüsseltes PDF – Dieses Dokument ist passwortgeschützt. +getPdfInfo.summary.not.encrypted.alert=Nicht verschlüsseltes PDF – Kein Passwortschutz. +getPdfInfo.summary.permissions.alert=Eingeschränkte Berechtigungen – {0} Aktionen sind nicht erlaubt. +getPdfInfo.summary.all.permissions.alert=Alle Berechtigungen erlaubt +getPdfInfo.summary.compliance.alert={0}-konform +getPdfInfo.summary.no.compliance.alert=Kein Konformitätsstandard +getPdfInfo.summary.security.section=Sicherheitsstatus +getPdfInfo.section.BasicInfo=Grundlegende Informationen über das PDF-Dokument inklusive Dateigröße, Seitenanzahl und Sprache. +getPdfInfo.section.Metadata=Dokumentenmetadaten inklusive Titel, Autor, Erstellungsdatum und weiteren Eigenschaften. +getPdfInfo.section.DocumentInfo=Technische Details zur Struktur und Version des PDF-Dokuments. +getPdfInfo.section.Compliancy=Informationen zur Einhaltung von PDF-Standards (PDF/A, PDF/X, etc.). +getPdfInfo.section.Encryption=Sicherheits- und Verschlüsselungsdetails des Dokuments. +getPdfInfo.section.Permissions=Dokumentenberechtigungen, die festlegen, welche Aktionen erlaubt sind. +getPdfInfo.section.Other=Zusätzliche Dokumentbestandteile wie Lesezeichen, Ebenen und eingebettete Dateien. +getPdfInfo.section.FormFields=Interaktive Formularfelder im Dokument. +getPdfInfo.section.PerPageInfo=Detaillierte Informationen zu jeder Seite im Dokument. #markdown-to-pdf @@ -948,7 +1012,7 @@ AddStampRequest.header=PDF Stempel AddStampRequest.title=PDF Stempel AddStampRequest.stampType=Stempeltyp AddStampRequest.stampText=Stempeltext -AddStampRequest.stampImage=Stampelbild +AddStampRequest.stampImage=Stempelbild AddStampRequest.alphabet=Alphabet AddStampRequest.fontSize=Schriftart/Bildgröße AddStampRequest.rotation=Drehung @@ -1205,6 +1269,12 @@ addImage.everyPage=In jede Seite einfügen? addImage.upload=Bild hinzufügen addImage.submit=Bild hinzufügen +#attachments +attachments.title=Anhänge hinzufügen +attachments.header=Anhänge hinzufügen +attachments.description=Ermöglicht das Hinzufügen von Anhängen zum PDF +attachments.descriptionPlaceholder=Beschreibung für die Anhänge eingeben... +attachments.addButton=Anhänge hinzufügen #merge merge.title=Zusammenführen @@ -1212,7 +1282,7 @@ merge.header=Mehrere PDFs zusammenführen (2+) merge.sortByName=Nach Namen sortieren merge.sortByDate=Nach Datum sortieren merge.removeCertSign=Digitale Signatur in der zusammengeführten Datei entfernen? -merge.generateToc=Generate table of contents in the merged file? +merge.generateToc=Inhaltsverzeichnis in der zusammengeführten Datei erstellen? merge.submit=Zusammenführen @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF-Datei fileChooser.dragAndDropImage=Drag & Drop Bilddatei fileChooser.hoveredDragAndDrop=Datei(en) hierhin Ziehen & Fallenlassen fileChooser.extractPDF=Extrahiere... +fileChooser.addAttachments=Drag & Drop Anhänge #release notes releases.footer=Veröffentlichungen @@ -1638,82 +1709,82 @@ validateSignature.cert.selfSigned=Selbstsigniert validateSignature.cert.bits=bits # Audit Dashboard -audit.dashboard.title=Audit Dashboard -audit.dashboard.systemStatus=Audit System Status +audit.dashboard.title=Audit-Dashboard +audit.dashboard.systemStatus=Systemstatus prüfen audit.dashboard.status=Status -audit.dashboard.enabled=Enabled -audit.dashboard.disabled=Disabled -audit.dashboard.currentLevel=Current Level -audit.dashboard.retentionPeriod=Retention Period -audit.dashboard.days=days -audit.dashboard.totalEvents=Total Events +audit.dashboard.enabled=Aktiviert +audit.dashboard.disabled=Deaktiviert +audit.dashboard.currentLevel=Aktuelle Ebene +audit.dashboard.retentionPeriod=Aufbewahrungsdauer +audit.dashboard.days=Tage +audit.dashboard.totalEvents=Gesamtereignisse # Audit Dashboard Tabs audit.dashboard.tab.dashboard=Dashboard -audit.dashboard.tab.events=Audit Events +audit.dashboard.tab.events=Überwachungsereignisse audit.dashboard.tab.export=Export # Dashboard Charts -audit.dashboard.eventsByType=Events by Type -audit.dashboard.eventsByUser=Events by User -audit.dashboard.eventsOverTime=Events Over Time -audit.dashboard.period.7days=7 Days -audit.dashboard.period.30days=30 Days -audit.dashboard.period.90days=90 Days +audit.dashboard.eventsByType=Ereignisse nach Typ +audit.dashboard.eventsByUser=Ereignisse nach Benutzer +audit.dashboard.eventsOverTime=Ereignisse im Laufe der Zeit +audit.dashboard.period.7days=7 Tage +audit.dashboard.period.30days=30 Tage +audit.dashboard.period.90days=90 Tage # Events Tab -audit.dashboard.auditEvents=Audit Events -audit.dashboard.filter.eventType=Event Type -audit.dashboard.filter.allEventTypes=All event types -audit.dashboard.filter.user=User -audit.dashboard.filter.userPlaceholder=Filter by user -audit.dashboard.filter.startDate=Start Date -audit.dashboard.filter.endDate=End Date -audit.dashboard.filter.apply=Apply Filters -audit.dashboard.filter.reset=Reset Filters +audit.dashboard.auditEvents=Überwachungsereignisse +audit.dashboard.filter.eventType=Ereignisart +audit.dashboard.filter.allEventTypes=Alle Ereignisstypen +audit.dashboard.filter.user=Benutzer +audit.dashboard.filter.userPlaceholder=Nach Benutzer filtern +audit.dashboard.filter.startDate=Startdatum +audit.dashboard.filter.endDate=Enddatum +audit.dashboard.filter.apply=Filter anwenden +audit.dashboard.filter.reset=Filter zurücksetzen # Table Headers audit.dashboard.table.id=ID -audit.dashboard.table.time=Time -audit.dashboard.table.user=User -audit.dashboard.table.type=Type +audit.dashboard.table.time=Zeit +audit.dashboard.table.user=Benutzer +audit.dashboard.table.type=Typ audit.dashboard.table.details=Details -audit.dashboard.table.viewDetails=View Details +audit.dashboard.table.viewDetails=Details anzeigen # Pagination -audit.dashboard.pagination.show=Show -audit.dashboard.pagination.entries=entries -audit.dashboard.pagination.pageInfo1=Page -audit.dashboard.pagination.pageInfo2=of -audit.dashboard.pagination.totalRecords=Total records: +audit.dashboard.pagination.show=Zeigen +audit.dashboard.pagination.entries=Einträge +audit.dashboard.pagination.pageInfo1=Seite +audit.dashboard.pagination.pageInfo2=von +audit.dashboard.pagination.totalRecords=Gesamtdatensätze: # Modal -audit.dashboard.modal.eventDetails=Event Details +audit.dashboard.modal.eventDetails=Ereignisdetails audit.dashboard.modal.id=ID -audit.dashboard.modal.user=User -audit.dashboard.modal.type=Type -audit.dashboard.modal.time=Time -audit.dashboard.modal.data=Data +audit.dashboard.modal.user=Benutzer +audit.dashboard.modal.type=Typ +audit.dashboard.modal.time=Zeit +audit.dashboard.modal.data=Daten # Export Tab -audit.dashboard.export.title=Export Audit Data -audit.dashboard.export.format=Export Format -audit.dashboard.export.csv=CSV (Comma Separated Values) -audit.dashboard.export.json=JSON (JavaScript Object Notation) -audit.dashboard.export.button=Export Data -audit.dashboard.export.infoTitle=Export Information -audit.dashboard.export.infoDesc1=The export will include all audit events matching the selected filters. For large datasets, the export may take a few moments to generate. -audit.dashboard.export.infoDesc2=Exported data will include: -audit.dashboard.export.infoItem1=Event ID -audit.dashboard.export.infoItem2=User -audit.dashboard.export.infoItem3=Event Type -audit.dashboard.export.infoItem4=Timestamp -audit.dashboard.export.infoItem5=Event Data +audit.dashboard.export.title=Audit-Daten exportieren +audit.dashboard.export.format=Exportformat +audit.dashboard.export.csv=CSV (Kommagetrennte Werte) +audit.dashboard.export.json=JSON (JavaScript-Objektnotation) +audit.dashboard.export.button=Daten exportieren +audit.dashboard.export.infoTitle=Informationen zum Export +audit.dashboard.export.infoDesc1=Der Export umfasst alle Protokollereignisse, die den gewählten Filtern entsprechen. Bei großen Datenmengen kann die Erstellung einige Zeit dauern. +audit.dashboard.export.infoDesc2=Exportierte Daten enthalten: +audit.dashboard.export.infoItem1=Ereignis-ID +audit.dashboard.export.infoItem2=Benutzer +audit.dashboard.export.infoItem3=Ereignistyp +audit.dashboard.export.infoItem4=Zeitstempel +audit.dashboard.export.infoItem5=Ereignisdaten # JavaScript i18n keys -audit.dashboard.js.noEventsFound=No audit events found matching the current filters -audit.dashboard.js.errorLoading=Error loading data: -audit.dashboard.js.errorRendering=Error rendering table: -audit.dashboard.js.loadingPage=Loading page +audit.dashboard.js.noEventsFound=Keine Protokollereignisse mit den aktuellen Filtern gefunden +audit.dashboard.js.errorLoading=Fehler beim Laden der Daten: +audit.dashboard.js.errorRendering=Fehler beim Anzeigen der Tabelle: +audit.dashboard.js.loadingPage=Seite wird geladen #################### # Cookie banner # diff --git a/stirling-pdf/src/main/resources/messages_el_GR.properties b/app/core/src/main/resources/messages_el_GR.properties similarity index 95% rename from stirling-pdf/src/main/resources/messages_el_GR.properties rename to app/core/src/main/resources/messages_el_GR.properties index 9c3966d98..b04948a41 100644 --- a/stirling-pdf/src/main/resources/messages_el_GR.properties +++ b/app/core/src/main/resources/messages_el_GR.properties @@ -163,13 +163,74 @@ alphabet=Αλφάβητο downloadPdf=Λήψη PDF text=Κείμενο font=Γραμματοσειρά -selectFillter=-- Επιλέξτε -- +selectFilter=-- Επιλέξτε -- pageNum=Αριθμός σελίδας sizes.small=Μικρό sizes.medium=Μεσαίο sizes.large=Μεγάλο sizes.x-large=Πολύ μεγάλο error.pdfPassword=Το PDF έχει προστασία κωδικού και είτε δεν δόθηκε κωδικός ή ήταν λανθασμένος +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Διαγραφή username=Όνομα χρήστη password=Κωδικός @@ -181,7 +242,6 @@ red=Κόκκινο green=Πράσινο blue=Μπλε custom=Προσαρμογή... -WorkInProgess=Εργασία σε εξέλιξη, μπορεί να μην λειτουργεί ή να έχει σφάλματα, παρακαλώ αναφέρετε τυχόν προβλήματα! poweredBy=Με την υποστήριξη του yes=Ναι no=Όχι @@ -525,6 +585,10 @@ home.addImage.title=Προσθήκη εικόνας home.addImage.desc=Προσθήκη εικόνας σε συγκεκριμένη θέση στο PDF addImage.tags=εικόνα,jpg,φωτογραφία +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Προσθήκη υδατογραφήματος home.watermark.desc=Προσθήκη προσαρμοσμένου υδατογραφήματος στο έγγραφο PDF. watermark.tags=κείμενο,επαναλαμβανόμενο,ετικέτα,ιδιοκτησία,πνευματικά δικαιώματα,εμπορικό σήμα,εικόνα,jpg,φωτογραφία @@ -1205,6 +1269,12 @@ addImage.everyPage=Κάθε σελίδα; addImage.upload=Προσθήκη εικόνας addImage.submit=Προσθήκη εικόνας +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Συγχώνευση @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Σύρετε & αφήστε αρχείο PDF fileChooser.dragAndDropImage=Σύρετε & αφήστε αρχείο εικόνας fileChooser.hoveredDragAndDrop=Σύρετε & αφήστε αρχείο(α) εδώ fileChooser.extractPDF=Εξαγωγή... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Εκδόσεις diff --git a/stirling-pdf/src/main/resources/messages_en_GB.properties b/app/core/src/main/resources/messages_en_GB.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_en_GB.properties rename to app/core/src/main/resources/messages_en_GB.properties index e7fc3770a..1325a9e3e 100644 --- a/stirling-pdf/src/main/resources/messages_en_GB.properties +++ b/app/core/src/main/resources/messages_en_GB.properties @@ -163,13 +163,74 @@ alphabet=Alphabet downloadPdf=Download PDF text=Text font=Font -selectFillter=-- Select -- +selectFilter=-- Select -- pageNum=Page Number sizes.small=Small sizes.medium=Medium sizes.large=Large sizes.x-large=X-Large error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Delete username=Username password=Password @@ -181,7 +242,6 @@ red=Red green=Green blue=Blue custom=Custom... -WorkInProgess=Work in progress, May not work or be buggy, Please report any problems! poweredBy=Powered by yes=Yes no=No diff --git a/stirling-pdf/src/main/resources/messages_en_US.properties b/app/core/src/main/resources/messages_en_US.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_en_US.properties rename to app/core/src/main/resources/messages_en_US.properties index 4b76acbb8..0b37cc0ea 100644 --- a/stirling-pdf/src/main/resources/messages_en_US.properties +++ b/app/core/src/main/resources/messages_en_US.properties @@ -163,13 +163,74 @@ alphabet=Alphabet downloadPdf=Download PDF text=Text font=Font -selectFillter=-- Select -- +selectFilter=-- Select -- pageNum=Page Number sizes.small=Small sizes.medium=Medium sizes.large=Large sizes.x-large=X-Large error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Delete username=Username password=Password @@ -181,7 +242,6 @@ red=Red green=Green blue=Blue custom=Custom... -WorkInProgess=Work in progress, May not work or be buggy, Please report any problems! poweredBy=Powered by yes=Yes no=No @@ -525,6 +585,10 @@ home.addImage.title=Add image home.addImage.desc=Adds a image onto a set location on the PDF addImage.tags=img,jpg,picture,photo +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Add Watermark home.watermark.desc=Add a custom watermark to your PDF document. watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo @@ -1205,6 +1269,12 @@ addImage.everyPage=Every Page? addImage.upload=Add image addImage.submit=Add image +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Merge @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_es_ES.properties b/app/core/src/main/resources/messages_es_ES.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_es_ES.properties rename to app/core/src/main/resources/messages_es_ES.properties index e5411f38c..bf86c3dee 100644 --- a/stirling-pdf/src/main/resources/messages_es_ES.properties +++ b/app/core/src/main/resources/messages_es_ES.properties @@ -163,13 +163,74 @@ alphabet=Alfabeto downloadPdf=Descargar PDF text=Texto font=Fuente -selectFillter=-- Seleccionar -- +selectFilter=-- Seleccionar -- pageNum=Número de página sizes.small=Pequeño sizes.medium=Mediano sizes.large=Grande sizes.x-large=Extra grande error.pdfPassword=El documento PDF está protegido con contraseña y no se ha proporcionado o es incorrecta +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Borrar username=Nombre de usuario password=Contraseña @@ -181,7 +242,6 @@ red=Rojo green=Verde blue=Azul custom=Personalizado... -WorkInProgess=Tarea en progreso, puede no funcionar o ralentizarse; ¡por favor, informe de cualquier problema! poweredBy=Desarrollado por yes=Sí no=No @@ -525,6 +585,10 @@ home.addImage.title=Agregar imagen al PDF home.addImage.desc=Agregar una imagen en el PDF en una ubicación establecida (en desarrollo) addImage.tags=img,jpg,imagen,fotografía +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Añadir marca de agua home.watermark.desc=Añadir una marca de agua predefinida al documento PDF watermark.tags=Texto,repetir,etiquetar,propietario,copyright,marca comercial,img,jpg,imagen,fotografía @@ -1205,6 +1269,12 @@ addImage.everyPage=¿Todas las páginas? addImage.upload=Añadir imagen addImage.submit=Enviar imagen +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Unir @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Arrastrar & Soltar archivo PDF fileChooser.dragAndDropImage=Arrastrar & Soltar archivo de Imagen fileChooser.hoveredDragAndDrop=Arrastrar & Soltar archivos(s) aquí fileChooser.extractPDF=Extrayendo... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Versiones diff --git a/stirling-pdf/src/main/resources/messages_eu_ES.properties b/app/core/src/main/resources/messages_eu_ES.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_eu_ES.properties rename to app/core/src/main/resources/messages_eu_ES.properties index 0593b8df4..8a614af65 100644 --- a/stirling-pdf/src/main/resources/messages_eu_ES.properties +++ b/app/core/src/main/resources/messages_eu_ES.properties @@ -163,13 +163,74 @@ alphabet=Alfabetoa downloadPdf=PDFa deskargatu text=Testua font=Letra-tipoa -selectFillter=-- Aukeratu filtroa -- +selectFilter=-- Aukeratu filtroa -- pageNum=Orrialde-zenbakia sizes.small=Txikia sizes.medium=Erdikoa sizes.large=Handia sizes.x-large=Oso handia error.pdfPassword=PDF dokumentua pasahitzarekin babestuta dago eta pasahitza ez da sartu edo okerra da +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=ezabatu username=Erabiltzaile izena password=Pasahitza @@ -181,7 +242,6 @@ red=Gorria green=Berdea blue=Urdina custom=Pertsonalizatu... -WorkInProgess=Work in progress, May not work or be buggy, Please report any problems! poweredBy=Powered by yes=Yes no=No @@ -525,6 +585,10 @@ home.addImage.title=Gehitu irudia PDFari home.addImage.desc=Gehitu irudi bat PDFan ezarritako kokaleku batean (lanean) addImage.tags=img,jpg,picture,photo +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Gehitu ur-marka home.watermark.desc=Gehitu aurrez zehaztutako ur-marka bat PFD dokumentuari watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo @@ -1205,6 +1269,12 @@ addImage.everyPage=Orrialde guztiak? addImage.upload=Gehitu irudia addImage.submit=Gehitu irudia +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Elkartu @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_fa_IR.properties b/app/core/src/main/resources/messages_fa_IR.properties similarity index 95% rename from stirling-pdf/src/main/resources/messages_fa_IR.properties rename to app/core/src/main/resources/messages_fa_IR.properties index b37917f2f..50dc3f6f7 100644 --- a/stirling-pdf/src/main/resources/messages_fa_IR.properties +++ b/app/core/src/main/resources/messages_fa_IR.properties @@ -163,13 +163,74 @@ alphabet=حروف الفبا downloadPdf=دانلود PDF text=متن font=فونت -selectFillter=-- انتخاب کنید -- +selectFilter=-- انتخاب کنید -- pageNum=شماره صفحه sizes.small=کوچک sizes.medium=متوسط sizes.large=بزرگ sizes.x-large=خیلی بزرگ error.pdfPassword=سند PDF دارای رمز عبور است و یا رمز عبور وارد نشده یا نادرست است +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=حذف username=نام کاربری password=رمز عبور @@ -181,7 +242,6 @@ red=قرمز green=سبز blue=آبی custom=سفارشی... -WorkInProgess=کار در حال پیشرفت است، ممکن است کار نکند یا دارای اشکال باشد، لطفاً هر مشکلی را گزارش دهید! poweredBy=قدرت گرفته از yes=بله no=خیر @@ -525,6 +585,10 @@ home.addImage.title=افزودن تصویر home.addImage.desc=افزودن یک تصویر به یک مکان مشخص در PDF addImage.tags=تصویر،jpg،عکس +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=افزودن واترمارک home.watermark.desc=افزودن یک واترمارک سفارشی به سند PDF. watermark.tags=متن،تکراری،برچسب،خود،کپی‌رایت،علامت تجاری،تصویر،jpg،عکس @@ -1205,6 +1269,12 @@ addImage.everyPage=هر صفحه؟ addImage.upload=افزودن تصویر addImage.submit=افزودن تصویر +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=ادغام @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=فایل(های) خود را اینجا بکشید و رها کنید fileChooser.extractPDF=در حال استخراج... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=نسخه‌ها diff --git a/stirling-pdf/src/main/resources/messages_fr_FR.properties b/app/core/src/main/resources/messages_fr_FR.properties similarity index 74% rename from stirling-pdf/src/main/resources/messages_fr_FR.properties rename to app/core/src/main/resources/messages_fr_FR.properties index 6b674cb9e..7b1e71100 100644 --- a/stirling-pdf/src/main/resources/messages_fr_FR.properties +++ b/app/core/src/main/resources/messages_fr_FR.properties @@ -142,9 +142,9 @@ multiPdfPrompt=Sélectionnez les PDF multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin imgPrompt=Choisir une image genericSubmit=Envoyer -uploadLimit=Maximum file size: -uploadLimitExceededSingular=is too large. Maximum allowed size is -uploadLimitExceededPlural=are too large. Maximum allowed size is +uploadLimit=Taille maximale du fichier : +uploadLimitExceededSingular=est trop grand. La taille maximale autorisée est de +uploadLimitExceededPlural=sont trop grands. La taille maximale autorisée est de processTimeWarning=Attention, ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier. pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) : pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) : @@ -163,13 +163,74 @@ alphabet=Alphabet downloadPdf=Télécharger le PDF text=Texte font=Police -selectFillter=-- Sélectionnez -- +selectFilter=-- Sélectionnez -- pageNum=Numéro de page sizes.small=Petit sizes.medium=Moyen sizes.large=Grand sizes.x-large=Très grand error.pdfPassword=Le document PDF est protégé par un mot de passe qui n'a pas été fourni ou était incorrect +error.pdfCorrupted=Le fichier PDF semble être corrompu ou endommagé. Veuillez d'abord utiliser la fonction « Réparer » pour corriger le fichier avant de poursuivre cette opération. +error.pdfCorruptedMultiple=Un ou plusieurs fichiers PDF semblent être corrompus ou endommagés. Veuillez utiliser la fonction « Réparer » sur chaque fichier avant d'essayer de les fusionner. +error.pdfCorruptedDuring=Erreur {0} : le fichier PDF semble être corrompu ou endommagé. Veuillez d'abord utiliser la fonction « Réparer » pour corriger le fichier avant de poursuivre cette opération. + +# Frontend corruption error messages +error.pdfInvalid=Le fichier PDF « {0} » semble être corrompu ou avoir une structure invalide. Veuillez utiliser la fonction « Réparer » pour corriger le fichier avant de continuer. +error.tryRepair=Essayez d'utiliser la fonction « Réparer » pour corriger les fichiers corrompus. + +# Additional error messages +error.pdfEncryption=Le PDF semble contenir des données de chiffrement corrompues. Cela peut se produire si le PDF a été créé avec des méthodes de chiffrement incompatibles. Veuillez d'abord utiliser la fonction « Réparer », ou contactez le créateur du document pour obtenir une nouvelle copie. +error.fileProcessing=Une erreur est survenue lors du traitement du fichier pendant l'opération {0} : {1} + +# Generic error message templates +error.toolNotInstalled={0} n'est pas installé +error.toolRequired={0} est requis pour {1} +error.conversionFailed=Échec de la conversion {0} +error.commandFailed=Échec de la commande {0} +error.algorithmNotAvailable=L'algorithme {0} n'est pas disponible +error.optionsNotSpecified=Les options pour {0} ne sont pas spécifiées +error.fileFormatRequired=Le fichier doit être au format {0} +error.invalidFormat=Format {0} invalide : {1} +error.endpointDisabled=Ce point de terminaison a été désactivé par l'administrateur +error.urlNotReachable=L'URL est inaccessible, veuillez fournir une URL valide + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=La valeur DPI {0} dépasse la limite maximale sécurisée de {1}. Des valeurs DPI trop élevées peuvent provoquer des problèmes de mémoire et des plantages. Veuillez utiliser une valeur DPI plus faible. +error.pageTooBigForDpi=La page PDF {0} est trop grande pour être rendue à {1} DPI. Veuillez essayer une valeur DPI plus faible (recommandé : 150 ou moins). +error.pageTooBigExceedsArray=La page PDF {0} est trop grande pour être rendue à {1} DPI. L'image résultante dépasserait la taille maximale autorisée pour un tableau en Java. Veuillez essayer une valeur DPI plus faible (recommandé : 150 ou moins). +error.pageTooBigFor300Dpi=La page PDF {0} est trop grande pour être rendue à 300 DPI. L'image résultante dépasserait la taille maximale autorisée pour un tableau en Java. Veuillez utiliser une valeur DPI plus faible pour la conversion PDF en image. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=La clé API n'est pas valide. +error.userNotFound=Utilisateur non trouvé. +error.passwordRequired=Le mot de passe ne doit pas être nul. +error.accountLocked=Votre compte a été verrouillé après trop de tentatives de connexion échouées. +error.invalidEmail=Adresses e-mail invalides fournies. +error.emailAttachmentRequired=Une pièce jointe est requise pour envoyer l'e-mail. +error.signatureNotFound=Fichier de signature introuvable. + +# File processing messages +error.fileNotFound=Fichier introuvable avec l'ID : {0} + +# Database and configuration messages +error.noBackupScripts=Aucun script de sauvegarde trouvé. +error.unsupportedProvider={0} n'est pas actuellement pris en charge. +error.pathTraversalDetected=Tentative de traversée de chemin détectée pour des raisons de sécurité. + +# Validation messages +error.invalidArgument=Argument invalide : {0} +error.argumentRequired={0} ne doit pas être nul +error.operationFailed=Échec de l'opération : {0} +error.angleNotMultipleOf90=L'angle doit être un multiple de 90 +error.pdfBookmarksNotFound=Aucun signet ou plan PDF trouvé dans le document +error.fontLoadingFailed=Erreur lors du traitement du fichier de police +error.fontDirectoryReadFailed=Échec de la lecture du répertoire de polices delete=Supprimer username=Nom d'utilisateur password=Mot de passe @@ -181,7 +242,6 @@ red=Rouge green=Vert blue=Bleu custom=Personnalisé… -WorkInProgess=En cours de développement, merci de nous remonter les problèmes que vous pourriez constater! poweredBy=Propulsé par yes=Oui no=Non @@ -200,7 +260,7 @@ disabledCurrentUserMessage=L'utilisateur actuel ne peut pas être désactivé downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché. userAlreadyExistsOAuthMessage=L'utilisateur existe déjà en tant qu'utilisateur OAuth2. userAlreadyExistsWebMessage=L'utilisateur existe déjà en tant qu'utilisateur Web. -invalidRoleMessage=Invalid role. +invalidRoleMessage=Rôle non valide. error=Erreur oops=Oups ! help=Aide @@ -213,27 +273,27 @@ color=Couleur sponsor=Sponsoriser info=Informations pro=Pro -proFeatures=Pro Features +proFeatures=Fonctions pro page=Page pages=Pages loading=Chargement... addToDoc=Ajouter au Document reset=Réinitialiser apply=Appliquer -noFileSelected=No file selected. Please upload one. -view=View -cancel=Cancel +noFileSelected=Aucun fichier sélectionné. Veuillez en télécharger un. +view=Voir +cancel=Annuler -back.toSettings=Back to Settings -back.toHome=Back to Home -back.toAdmin=Back to Admin +back.toSettings=Retour aux paramètres +back.toHome=Retour à l'accueil +back.toAdmin=Retour à l'administration legal.privacy=Politique de Confidentialité legal.terms=Conditions Générales legal.accessibility=Accessibilité legal.cookie=Politique des Cookies legal.impressum=Mentions Légales -legal.showCookieBanner=Cookie Preferences +legal.showCookieBanner=Préférences pour les cookies ############### # Pipeline # @@ -267,7 +327,7 @@ enterpriseEdition.button=Passer à Pro enterpriseEdition.warning=Cette fonctionnalité est uniquement disponible pour les utilisateurs Pro. enterpriseEdition.yamlAdvert=Stirling PDF Pro prend en charge les fichiers de configuration YAML et d'autres fonctionnalités SSO. enterpriseEdition.ssoAdvert=Vous cherchez plus de fonctionnalités de gestion des utilisateurs ? Découvrez Stirling PDF Pro -enterpriseEdition.proTeamFeatureDisabled=Team management features require a Pro licence or higher +enterpriseEdition.proTeamFeatureDisabled=Les fonctions de gestion d'équipe nécessitent une licence Pro ou supérieure ################# @@ -348,8 +408,8 @@ account.property=Propriété account.webBrowserSettings=Paramètres du navigateur account.syncToBrowser=Synchroniser : Compte → Navigateur account.syncToAccount=Synchroniser : Compte ← Navigateur -account.adminTitle=Administrator Tools -account.adminNotif=You have admin privileges. Access system settings and user management. +account.adminTitle=Outils d'administrations +account.adminNotif=Vous avez des privilèges d'administrateur. Accédez aux paramètres du système et à la gestion des utilisateurs. adminUserSettings.title=Administration des paramètres des utilisateurs @@ -379,75 +439,75 @@ adminUserSettings.activeUsers=Utilisateurs actifs : adminUserSettings.disabledUsers=Utilisateurs désactivés : adminUserSettings.totalUsers=Utilisateurs au total : adminUserSettings.lastRequest=Dernière requête -adminUserSettings.usage=View Usage -adminUserSettings.teams=View/Edit Teams -adminUserSettings.team=Team -adminUserSettings.manageTeams=Manage Teams -adminUserSettings.createTeam=Create Team -adminUserSettings.viewTeam=View Team -adminUserSettings.deleteTeam=Delete Team -adminUserSettings.teamName=Team Name -adminUserSettings.teamExists=Team already exists -adminUserSettings.teamCreated=Team created successfully -adminUserSettings.teamChanged=User's team was updated -adminUserSettings.teamHidden=Hidden -adminUserSettings.totalMembers=Total Members -adminUserSettings.confirmDeleteTeam=Are you sure you want to delete this team? +adminUserSettings.usage=Voir l'utilisation +adminUserSettings.teams=Voir/modifier les équipes +adminUserSettings.team=Équipe +adminUserSettings.manageTeams=Gérer les équipes +adminUserSettings.createTeam=Créer une équipe +adminUserSettings.viewTeam=Voir l'équipe +adminUserSettings.deleteTeam=Supprimer l'équipe +adminUserSettings.teamName=Nom de l'équipe +adminUserSettings.teamExists=L'équipe existe déjà +adminUserSettings.teamCreated=Création réussie d'une équipe +adminUserSettings.teamChanged=Les membres de l'équipe de l'utilisateur ont été mis à jour. +adminUserSettings.teamHidden=Caché +adminUserSettings.totalMembers=Membres totaux +adminUserSettings.confirmDeleteTeam=Êtes-vous sûr de vouloir supprimer cette équipe ? -teamCreated=Team created successfully -teamExists=A team with that name already exists -teamNameExists=Another team with that name already exists -teamNotFound=Team not found -teamDeleted=Team deleted -teamHasUsers=Cannot delete a team with users assigned -teamRenamed=Team renamed successfully +teamCreated=Équipe créée avec succès +teamExists=Une équipe portant ce nom existe déjà +teamNameExists=Une autre équipe portant ce nom existe déjà +teamNotFound=Équipe non trouvée +teamDeleted=Équipe supprimée +teamHasUsers=Impossible de supprimer une équipe à laquelle des membres ont été affectés +teamRenamed=L'équipe a été renommée avec succès # Team user management -team.addUser=Add User to Team -team.selectUser=Select User -team.warning.moveUser=Warning: This will move the user from "{0}" team to "{1}" team. Are you sure? -team.confirm.moveUser=Are you sure you want to move this user from "{0}" team to "{1}" team? -team.userAdded=User successfully added to team -team.back=Back to Teams -team.internal=Internal Team -team.internalTeamNotAccessible=The Internal team is a system team and cannot be accessed -team.cannotMoveInternalUsers=Users in the Internal team cannot be moved to other teams -team.hidden=Hidden -team.name=Team Name -team.totalMembers=Total Members -team.members=Members -team.username=Username -team.role=Role -team.status=Status -team.enabled=Enabled -team.disabled=Disabled -team.noMembers=This team has no members yet. +team.addUser=Ajouter un membre à l'équipe +team.selectUser=Sélectionner l'utilisateur +team.warning.moveUser=Attention : L'utilisateur passera de l'équipe "{0}" à l'équipe "{1}". Êtes-vous sûr de vous ? +team.confirm.moveUser=Êtes-vous sûr de vouloir déplacer cet utilisateur de l'équipe "{0}" vers l'équipe "{1}" ? +team.userAdded=L'utilisateur a été ajouté avec succès à l'équipe +team.back=Retour aux équipes +team.internal=Équipe interne +team.internalTeamNotAccessible=L'équipe interne est une équipe système et n'est pas accessible. +team.cannotMoveInternalUsers=Les utilisateurs de l'équipe interne ne peuvent pas être déplacés vers d'autres équipes. +team.hidden=Caché +team.name=Nom de l'équipe +team.totalMembers=Membres totaux +team.members=Membres +team.username=Nom d'utilisateur +team.role=Rôle +team.status=Statut +team.enabled=Activé +team.disabled=Désactivé +team.noMembers=Cette équipe n'a pas encore de membres. -endpointStatistics.title=Endpoint Statistics -endpointStatistics.header=Endpoint Statistics +endpointStatistics.title=Statistiques des points de terminaison +endpointStatistics.header=Statistiques des points de terminaison endpointStatistics.top10=Top 10 endpointStatistics.top20=Top 20 -endpointStatistics.all=All -endpointStatistics.refresh=Refresh -endpointStatistics.includeHomepage=Include Homepage ('/') -endpointStatistics.includeLoginPage=Include Login Page ('/login') -endpointStatistics.totalEndpoints=Total Endpoints -endpointStatistics.totalVisits=Total Visits -endpointStatistics.showing=Showing -endpointStatistics.selectedVisits=Selected Visits -endpointStatistics.endpoint=Endpoint -endpointStatistics.visits=Visits -endpointStatistics.percentage=Percentage -endpointStatistics.loading=Loading... -endpointStatistics.failedToLoad=Failed to load endpoint data. Please try refreshing. -endpointStatistics.home=Home -endpointStatistics.login=Login +endpointStatistics.all=Tout +endpointStatistics.refresh=Rafraîchir +endpointStatistics.includeHomepage=Inclure la page d'accueil ('/') +endpointStatistics.includeLoginPage=Inclure la page de connexion ('/login') +endpointStatistics.totalEndpoints=Nombre total de points de terminaison +endpointStatistics.totalVisits=Nombre total de visites +endpointStatistics.showing=Affichage +endpointStatistics.selectedVisits=Visites sélectionnées +endpointStatistics.endpoint=Point de terminaison +endpointStatistics.visits=Visites +endpointStatistics.percentage=Pourcentage +endpointStatistics.loading=Chargement... +endpointStatistics.failedToLoad=Échec du chargement des données des points de terminaisons. Veuillez réessayer. +endpointStatistics.home=Accueil +endpointStatistics.login=Connexion endpointStatistics.top=Top -endpointStatistics.numberOfVisits=Number of Visits -endpointStatistics.visitsTooltip=Visits: {0} ({1}% of total) -endpointStatistics.retry=Retry +endpointStatistics.numberOfVisits=Nombre de visites +endpointStatistics.visitsTooltip=Visites : {0} ({1}% du total) +endpointStatistics.retry=Réessayer database.title=Import/Export de la Base de Données database.header=Import/Export de la Base de Données @@ -525,6 +585,10 @@ home.addImage.title=Ajouter une image home.addImage.desc=Ajoutez une image à un emplacement défini sur un PDF. addImage.tags=img,jpg,image,photo +home.attachments.title=Ajouter des pièces jointes +home.attachments.desc=Ajouter ou supprimer des fichiers intégrés (pièces jointes) dans un PDF +attachments.tags=intégrer,joindre,fichier,pièce,jointe,embed,attach,file,attachment,attachments + home.watermark.title=Ajouter un filigrane home.watermark.desc=Ajoutez un filigrane personnalisé à votre PDF. watermark.tags=texte,filigrane,label,propriété,droit d'auteur,marque déposée,img,jpg,image,photo,copyright,trademark @@ -550,9 +614,9 @@ home.compressPdfs.title=Compresser home.compressPdfs.desc=Compressez les PDF pour réduire leur tailles. compressPdfs.tags=compresser,réduire,taille,squish,small,tiny -home.unlockPDFForms.title=Unlock PDF Forms -home.unlockPDFForms.desc=Remove read-only property of form fields in a PDF document. -unlockPDFForms.tags=remove,delete,form,field,readonly +home.unlockPDFForms.title=Déverrouiller les formulaires PDF +home.unlockPDFForms.desc=Supprimer la propriété lecture seule des champs de formulaire dans un document PDF +unlockPDFForms.tags=supprimer,propriété,déverrouiller,formulaire,champs,lecture,remove,delete,form,field,readonly home.changeMetadata.title=Modifier les métadonnées home.changeMetadata.desc=Modifiez, supprimez ou ajoutez des métadonnées à un PDF. @@ -676,21 +740,21 @@ home.HTMLToPDF.desc=Convertissez n'importe quel fichier HTML ou ZIP en PDF. HTMLToPDF.tags=html,markup,contenu Web,transformation,convert #eml-to-pdf -home.EMLToPDF.title=Email to PDF -home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images -EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail +home.EMLToPDF.title=Email en PDF +home.EMLToPDF.desc=Convertit les fichiers email (EML) en PDF, y compris les en-têtes, le corps et les images intégrées +EMLToPDF.tags=email,conversion,courrier,conversion,eml,message,transformation,convert,mail -EMLToPDF.title=Email To PDF -EMLToPDF.header=Email To PDF -EMLToPDF.submit=Convert -EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF -EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues -EMLToPDF.includeAttachments=Include attachments in PDF -EMLToPDF.maxAttachmentSize=Maximum attachment size (MB) -EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images -EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both -EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code. -EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs +EMLToPDF.title=Email en PDF +EMLToPDF.header=Email en PDF +EMLToPDF.submit=Convertir +EMLToPDF.downloadHtml=Télécharger le fichier HTML intermédiaire au lieu du PDF +EMLToPDF.downloadHtmlHelp=Cela vous permet de voir la version HTML avant la conversion en PDF et peut aider à corriger les problèmes de mise en forme +EMLToPDF.includeAttachments=Inclure les pièces jointes dans le PDF +EMLToPDF.maxAttachmentSize=Taille maximale des pièces jointes (Mo) +EMLToPDF.help=Convertit les fichiers email (EML) en PDF, y compris les en-têtes, le corps et les images intégrées +EMLToPDF.troubleshootingTip1=La conversion Email vers HTML est plus fiable, il est donc recommandé de sauvegarder les deux lors d'un traitement par lot +EMLToPDF.troubleshootingTip2=Avec un petit nombre d'emails, si le PDF est mal formé, vous pouvez télécharger le HTML et corriger manuellement le code HTML/CSS problématique +EMLToPDF.troubleshootingTip3=Les éléments intégrés ne fonctionnent cependant pas avec les fichiers HTML home.MarkdownToPDF.title=Markdown en PDF home.MarkdownToPDF.desc=Convertissez n'importe quel fichier Markdown en PDF. @@ -806,12 +870,12 @@ login.oauth2invalidRequest=Requête invalide login.oauth2AccessDenied=Accès refusé login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide login.oauth2InvalidIdToken=Jeton d'identification invalide -login.relyingPartyRegistrationNotFound=No relying party registration found +login.relyingPartyRegistrationNotFound=Aucun enregistrement de partie de confiance trouvé login.userIsDisabled=L'utilisateur est désactivé, la connexion est actuellement bloquée avec ce nom d'utilisateur. Veuillez contacter l'administrateur. login.alreadyLoggedIn=Vous êtes déjà connecté sur login.alreadyLoggedIn2=appareils. Veuillez vous déconnecter des appareils et réessayer. login.toManySessions=Vous avez trop de sessions actives. -login.logoutMessage=You have been logged out. +login.logoutMessage=Vous avez été déconnecté. #auto-redact autoRedact.title=Caviarder automatiquement @@ -877,28 +941,28 @@ getPdfInfo.title=Récupérer les informations getPdfInfo.header=Récupérer les informations getPdfInfo.submit=Récupérer les informations getPdfInfo.downloadJson=Télécharger le JSON -getPdfInfo.summary=PDF Summary -getPdfInfo.summary.encrypted=This PDF is encrypted so may face issues with some applications -getPdfInfo.summary.permissions=This PDF has {0} restricted permissions which may limit what you can do with it -getPdfInfo.summary.compliance=This PDF complies with the {0} standard -getPdfInfo.summary.basicInfo=Basic Information -getPdfInfo.summary.docInfo=Document Information -getPdfInfo.summary.encrypted.alert=Encrypted PDF - This document is password protected -getPdfInfo.summary.not.encrypted.alert=Unencrypted PDF - No password protection -getPdfInfo.summary.permissions.alert=Restricted Permissions - {0} actions are not allowed -getPdfInfo.summary.all.permissions.alert=All Permissions Allowed -getPdfInfo.summary.compliance.alert={0} Compliant -getPdfInfo.summary.no.compliance.alert=No Compliance Standards -getPdfInfo.summary.security.section=Security Status -getPdfInfo.section.BasicInfo=Basic Information about the PDF document including file size, page count, and language -getPdfInfo.section.Metadata=Document metadata including title, author, creation date and other document properties -getPdfInfo.section.DocumentInfo=Technical details about the PDF document structure and version -getPdfInfo.section.Compliancy=PDF standards compliance information (PDF/A, PDF/X, etc.) -getPdfInfo.section.Encryption=Security and encryption details of the document -getPdfInfo.section.Permissions=Document permission settings that control what actions can be performed -getPdfInfo.section.Other=Additional document components like bookmarks, layers, and embedded files -getPdfInfo.section.FormFields=Interactive form fields present in the document -getPdfInfo.section.PerPageInfo=Detailed information about each page in the document +getPdfInfo.summary=Résumé du PDF +getPdfInfo.summary.encrypted=Ce PDF est chiffré et peut poser des problèmes avec certaines applications +getPdfInfo.summary.permissions=Ce PDF a {0} permissions restreintes, ce qui peut limiter les actions possibles +getPdfInfo.summary.compliance=Ce PDF est conforme à la norme {0} +getPdfInfo.summary.basicInfo=Informations de base +getPdfInfo.summary.docInfo=Informations sur le document +getPdfInfo.summary.encrypted.alert=PDF chiffré - Ce document est protégé par mot de passe +getPdfInfo.summary.not.encrypted.alert=PDF non chiffré - Aucune protection par mot de passe +getPdfInfo.summary.permissions.alert=Permissions restreintes - {0} actions ne sont pas autorisées +getPdfInfo.summary.all.permissions.alert=Toutes les permissions sont autorisées +getPdfInfo.summary.compliance.alert=Conforme à {0} +getPdfInfo.summary.no.compliance.alert=Non conforme à une norme +getPdfInfo.summary.security.section=État de la sécurité +getPdfInfo.section.BasicInfo=Informations de base sur le document PDF, y compris la taille du fichier, le nombre de pages et la langue +getPdfInfo.section.Metadata=Métadonnées du document, y compris le titre, l'auteur, la date de création et d'autres propriétés +getPdfInfo.section.DocumentInfo=Détails techniques sur la structure et la version du document PDF +getPdfInfo.section.Compliancy=Informations sur la conformité aux normes PDF (PDF/A, PDF/X, etc.) +getPdfInfo.section.Encryption=Détails sur la sécurité et le chiffrement du document +getPdfInfo.section.Permissions=Paramètres de permissions du document qui contrôlent les actions autorisées +getPdfInfo.section.Other=Composants supplémentaires du document comme les signets, calques et fichiers intégrés +getPdfInfo.section.FormFields=Champs de formulaire interactifs présents dans le document +getPdfInfo.section.PerPageInfo=Informations détaillées sur chaque page du document #markdown-to-pdf @@ -910,9 +974,9 @@ MarkdownToPDF.credit=Utilise WeasyPrint. #pdf-to-markdown -PDFToMarkdown.title=PDF To Markdown -PDFToMarkdown.header=PDF To Markdown -PDFToMarkdown.submit=Convert +PDFToMarkdown.title=PDF en Markdown +PDFToMarkdown.header=PDF en Markdown +PDFToMarkdown.submit=Convertir #url-to-pdf @@ -966,10 +1030,10 @@ sanitizePDF.title=Assainir sanitizePDF.header=Assainir sanitizePDF.selectText.1=Supprimer les actions JavaScript sanitizePDF.selectText.2=Supprimer les fichiers intégrés -sanitizePDF.selectText.3=Remove XMP metadata +sanitizePDF.selectText.3=Supprimer les métadonnées XMP sanitizePDF.selectText.4=Supprimer les liens sanitizePDF.selectText.5=Supprimer les polices -sanitizePDF.selectText.6=Remove Document Info Metadata +sanitizePDF.selectText.6=Supprimer les métadonnées d'information du document sanitizePDF.submit=Assainir @@ -1019,7 +1083,7 @@ autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Sti 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.duplexMode=Mode recto-verso -autoSplitPDF.dividerDownload2=Auto Splitter Divider (with instructions).pdf +autoSplitPDF.dividerDownload2=Feuille de séparation automatique (avec instructions).pdf autoSplitPDF.submit=Séparer @@ -1190,8 +1254,8 @@ compress.title=Compresser un PDF compress.header=Compresser un PDF (lorsque c'est possible!) compress.credit=Ce service utilise qpdf pour la compression et l'optimisation des PDF. compress.grayscale.label=Appliquer l'échelle de gris pour la compression -compress.selectText.1=Compression Settings -compress.selectText.1.1=1-3 PDF compression,
4-6 lite image compression,
7-9 intense image compression Will dramatically reduce image quality +compress.selectText.1=Paramètres de compression +compress.selectText.1.1=1-3 compression PDF,
4-6 compression d'image légère,
7-9 compression d'image intense qui réduira considérablement la qualité de l'image compress.selectText.2=Niveau d'optimisation compress.selectText.4=Mode automatique – ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte compress.selectText.5=Taille PDF attendue (par exemple, 25 MB, 10,8 MB, 25 KB) @@ -1205,6 +1269,12 @@ addImage.everyPage=Toutes les pages ? addImage.upload=Télécharger une image addImage.submit=Ajouter une image +#attachments +attachments.title=Ajouter des pièces jointes +attachments.header=Ajouter des pièces jointes +attachments.description=Permet d'ajouter des pièces jointes au PDF +attachments.descriptionPlaceholder=Entrez une description pour les pièces jointes... +attachments.addButton=Ajouter des pièces jointes #merge merge.title=Fusionner @@ -1212,7 +1282,7 @@ merge.header=Fusionner plusieurs PDF merge.sortByName=Trier par nom merge.sortByDate=Trier par date merge.removeCertSign=Supprimer la signature numérique dans le fichier fusionné ? -merge.generateToc=Generate table of contents in the merged file? +merge.generateToc=Générer une table des matières dans le fichier fusionné ? merge.submit=Fusionner @@ -1231,7 +1301,7 @@ pdfOrganiser.mode.7=Supprimer le premier pdfOrganiser.mode.8=Supprimer le dernier pdfOrganiser.mode.9=Supprimer le premier et le dernier pdfOrganiser.mode.10=Méger Impair-Pair -pdfOrganiser.mode.11=Duplicate all pages +pdfOrganiser.mode.11=Dupliquer toutes les pages pdfOrganiser.placeholder=(par exemple 1,3,2 ou 4-8,2,10-12 ou 2n-1) @@ -1257,8 +1327,8 @@ multiTool.moveLeft=Déplacer vers la gauche multiTool.moveRight=Déplacer vers la droite multiTool.delete=Supprimer multiTool.dragDropMessage=Page(s) sélectionnées -multiTool.undo=Undo -multiTool.redo=Redo +multiTool.undo=Annuler +multiTool.redo=Refaire #decrypt decrypt.passwordPrompt=Ce fichier est protégé par un mot de passe. Veuillez saisir le mot de passe : @@ -1274,7 +1344,7 @@ decrypt.success=Fichier déchiffré avec succès. multiTool-advert.message=Cette fonctionnalité est aussi disponible dans la page de l'outil multifonction. Allez-y pour une interface page par page améliorée et des fonctionnalités additionnelles ! #view pdf -viewPdf.title=View/Edit PDF +viewPdf.title=Afficher/modifier un PDF viewPdf.header=Visualiser un PDF #pageRemover @@ -1333,7 +1403,7 @@ pdfToImage.color=Couleur pdfToImage.grey=Niveaux de gris pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !) pdfToImage.submit=Convertir -pdfToImage.info=Python n’est pas installé. Nécessaire pour la conversion WebP. +pdfToImage.info=Python n'est pas installé. Nécessaire pour la conversion WebP. pdfToImage.placeholder=(par exemple : 1,2,8 ou 4,7,12-16 ou 2n-1) @@ -1422,9 +1492,9 @@ changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée changeMetadata.submit=Modifier #unlockPDFForms -unlockPDFForms.title=Remove Read-Only from Form Fields -unlockPDFForms.header=Unlock PDF Forms -unlockPDFForms.submit=Remove +unlockPDFForms.title=Supprimer la lecture seule des champs de formulaire +unlockPDFForms.header=Déverrouiller les formulaires PDF +unlockPDFForms.submit=Supprimer #pdfToPDFA pdfToPDFA.title=PDF en PDF/A @@ -1590,10 +1660,11 @@ splitByChapters.submit=Diviser le PDF fileChooser.click=Cliquez fileChooser.or=ou fileChooser.dragAndDrop=Glisser & Déposer -fileChooser.dragAndDropPDF=Drag & Drop PDF file -fileChooser.dragAndDropImage=Drag & Drop Image file +fileChooser.dragAndDropPDF=Glisser & Déposer un PDF +fileChooser.dragAndDropImage=Glisser & Déposer une image fileChooser.hoveredDragAndDrop=Glisser & Déposer le(s) fichier(s) ici fileChooser.extractPDF=Extraction en cours... +fileChooser.addAttachments=Glisser & Déposer les pièces jointes ici #release notes releases.footer=Versions @@ -1638,157 +1709,157 @@ validateSignature.cert.selfSigned=Auto-signé validateSignature.cert.bits=bits # Audit Dashboard -audit.dashboard.title=Audit Dashboard -audit.dashboard.systemStatus=Audit System Status -audit.dashboard.status=Status -audit.dashboard.enabled=Enabled -audit.dashboard.disabled=Disabled -audit.dashboard.currentLevel=Current Level -audit.dashboard.retentionPeriod=Retention Period -audit.dashboard.days=days -audit.dashboard.totalEvents=Total Events +audit.dashboard.title=Tableau de bord d'audit +audit.dashboard.systemStatus=État du système d'audit +audit.dashboard.status=Statut +audit.dashboard.enabled=Activé +audit.dashboard.disabled=Désactivé +audit.dashboard.currentLevel=Niveau actuel +audit.dashboard.retentionPeriod=Période de conservation +audit.dashboard.days=jours +audit.dashboard.totalEvents=Nombre total d'événements # Audit Dashboard Tabs -audit.dashboard.tab.dashboard=Dashboard -audit.dashboard.tab.events=Audit Events -audit.dashboard.tab.export=Export +audit.dashboard.tab.dashboard=Tableau de bord +audit.dashboard.tab.events=Événements d'audit +audit.dashboard.tab.export=Exportation # Dashboard Charts -audit.dashboard.eventsByType=Events by Type -audit.dashboard.eventsByUser=Events by User -audit.dashboard.eventsOverTime=Events Over Time -audit.dashboard.period.7days=7 Days -audit.dashboard.period.30days=30 Days -audit.dashboard.period.90days=90 Days +audit.dashboard.eventsByType=Événements par type +audit.dashboard.eventsByUser=Événements par utilisateur +audit.dashboard.eventsOverTime=Événements dans le temps +audit.dashboard.period.7days=7 jours +audit.dashboard.period.30days=30 jours +audit.dashboard.period.90days=90 jours # Events Tab -audit.dashboard.auditEvents=Audit Events -audit.dashboard.filter.eventType=Event Type -audit.dashboard.filter.allEventTypes=All event types -audit.dashboard.filter.user=User -audit.dashboard.filter.userPlaceholder=Filter by user -audit.dashboard.filter.startDate=Start Date -audit.dashboard.filter.endDate=End Date -audit.dashboard.filter.apply=Apply Filters -audit.dashboard.filter.reset=Reset Filters +audit.dashboard.auditEvents=Événements d'audit +audit.dashboard.filter.eventType=Type d'événement +audit.dashboard.filter.allEventTypes=Tous les types d'événements +audit.dashboard.filter.user=Utilisateur +audit.dashboard.filter.userPlaceholder=Filtrer par utilisateur +audit.dashboard.filter.startDate=Date de début +audit.dashboard.filter.endDate=Date de fin +audit.dashboard.filter.apply=Appliquer les filtres +audit.dashboard.filter.reset=Réinitialiser les filtres # Table Headers audit.dashboard.table.id=ID -audit.dashboard.table.time=Time -audit.dashboard.table.user=User +audit.dashboard.table.time=Heure +audit.dashboard.table.user=Utilisateur audit.dashboard.table.type=Type -audit.dashboard.table.details=Details -audit.dashboard.table.viewDetails=View Details +audit.dashboard.table.details=Détails +audit.dashboard.table.viewDetails=Voir les détails # Pagination -audit.dashboard.pagination.show=Show -audit.dashboard.pagination.entries=entries +audit.dashboard.pagination.show=Afficher +audit.dashboard.pagination.entries=entrées audit.dashboard.pagination.pageInfo1=Page -audit.dashboard.pagination.pageInfo2=of -audit.dashboard.pagination.totalRecords=Total records: +audit.dashboard.pagination.pageInfo2=de +audit.dashboard.pagination.totalRecords=Nombre total d'enregistrements : # Modal -audit.dashboard.modal.eventDetails=Event Details +audit.dashboard.modal.eventDetails=Détails de l'événement audit.dashboard.modal.id=ID -audit.dashboard.modal.user=User +audit.dashboard.modal.user=Utilisateur audit.dashboard.modal.type=Type -audit.dashboard.modal.time=Time -audit.dashboard.modal.data=Data +audit.dashboard.modal.time=Heure +audit.dashboard.modal.data=Données # Export Tab -audit.dashboard.export.title=Export Audit Data -audit.dashboard.export.format=Export Format -audit.dashboard.export.csv=CSV (Comma Separated Values) -audit.dashboard.export.json=JSON (JavaScript Object Notation) -audit.dashboard.export.button=Export Data -audit.dashboard.export.infoTitle=Export Information -audit.dashboard.export.infoDesc1=The export will include all audit events matching the selected filters. For large datasets, the export may take a few moments to generate. -audit.dashboard.export.infoDesc2=Exported data will include: -audit.dashboard.export.infoItem1=Event ID -audit.dashboard.export.infoItem2=User -audit.dashboard.export.infoItem3=Event Type -audit.dashboard.export.infoItem4=Timestamp -audit.dashboard.export.infoItem5=Event Data +audit.dashboard.export.title=Exporter les données d'audit +audit.dashboard.export.format=Format d'exportation +audit.dashboard.export.csv=CSV (valeurs séparées par des virgules) +audit.dashboard.export.json=JSON (notation objet JavaScript) +audit.dashboard.export.button=Exporter les données +audit.dashboard.export.infoTitle=Informations sur l'exportation +audit.dashboard.export.infoDesc1=L'exportation inclura tous les événements d'audit correspondant aux filtres sélectionnés. Pour les grands ensembles de données, l'exportation peut prendre quelques instants. +audit.dashboard.export.infoDesc2=Les données exportées incluront : +audit.dashboard.export.infoItem1=ID de l'événement +audit.dashboard.export.infoItem2=Utilisateur +audit.dashboard.export.infoItem3=Type d'événement +audit.dashboard.export.infoItem4=Horodatage +audit.dashboard.export.infoItem5=Données de l'événement # JavaScript i18n keys -audit.dashboard.js.noEventsFound=No audit events found matching the current filters -audit.dashboard.js.errorLoading=Error loading data: -audit.dashboard.js.errorRendering=Error rendering table: -audit.dashboard.js.loadingPage=Loading page +audit.dashboard.js.noEventsFound=Aucun événement d'audit trouvé correspondant aux filtres actuels +audit.dashboard.js.errorLoading=Erreur lors du chargement des données : +audit.dashboard.js.errorRendering=Erreur lors de l'affichage du tableau : +audit.dashboard.js.loadingPage=Chargement de la page #################### # Cookie banner # #################### -cookieBanner.popUp.title=How we use Cookies -cookieBanner.popUp.description.1=We use cookies and other technologies to make Stirling PDF work better for you—helping us improve our tools and keep building features you'll love. -cookieBanner.popUp.description.2=If you’d rather not, clicking 'No Thanks' will only enable the essential cookies needed to keep things running smoothly. -cookieBanner.popUp.acceptAllBtn=Okay -cookieBanner.popUp.acceptNecessaryBtn=No Thanks -cookieBanner.popUp.showPreferencesBtn=Manage preferences -cookieBanner.preferencesModal.title=Consent Preferences Center -cookieBanner.preferencesModal.acceptAllBtn=Accept all -cookieBanner.preferencesModal.acceptNecessaryBtn=Reject all -cookieBanner.preferencesModal.savePreferencesBtn=Save preferences -cookieBanner.preferencesModal.closeIconLabel=Close modal +cookieBanner.popUp.title=Comment nous utilisons les cookies +cookieBanner.popUp.description.1=Nous utilisons des cookies et d'autres technologies pour améliorer Stirling PDF pour vous — cela nous aide à perfectionner nos outils et à créer des fonctionnalités que vous allez adorer. +cookieBanner.popUp.description.2=Si vous préférez ne pas les utiliser, cliquer sur « Non merci » n'activera que les cookies essentiels nécessaires au bon fonctionnement du site. +cookieBanner.popUp.acceptAllBtn=D'accord +cookieBanner.popUp.acceptNecessaryBtn=Non merci +cookieBanner.popUp.showPreferencesBtn=Gérer les préférences +cookieBanner.preferencesModal.title=Centre de préférences de consentement +cookieBanner.preferencesModal.acceptAllBtn=Tout accepter +cookieBanner.preferencesModal.acceptNecessaryBtn=Tout refuser +cookieBanner.preferencesModal.savePreferencesBtn=Enregistrer les préférences +cookieBanner.preferencesModal.closeIconLabel=Fermer la fenêtre cookieBanner.preferencesModal.serviceCounterLabel=Service|Services -cookieBanner.preferencesModal.subtitle=Cookie Usage -cookieBanner.preferencesModal.description.1=Stirling PDF uses cookies and similar technologies to enhance your experience and understand how our tools are used. This helps us improve performance, develop the features you care about, and provide ongoing support to our users. -cookieBanner.preferencesModal.description.2=Stirling PDF cannot—and will never—track or access the content of the documents you use. -cookieBanner.preferencesModal.description.3=Your privacy and trust are at the core of what we do. -cookieBanner.preferencesModal.necessary.title.1=Strictly Necessary Cookies -cookieBanner.preferencesModal.necessary.title.2=Always Enabled -cookieBanner.preferencesModal.necessary.description=These cookies are essential for the website to function properly. They enable core features like setting your privacy preferences, logging in, and filling out forms—which is why they can’t be turned off. -cookieBanner.preferencesModal.analytics.title=Analytics -cookieBanner.preferencesModal.analytics.description=These cookies help us understand how our tools are being used, so we can focus on building the features our community values most. Rest assured—Stirling PDF cannot and will never track the content of the documents you work with. +cookieBanner.preferencesModal.subtitle=Utilisation des cookies +cookieBanner.preferencesModal.description.1=Stirling PDF utilise des cookies et des technologies similaires pour améliorer votre expérience et comprendre comment nos outils sont utilisés. Cela nous aide à améliorer les performances, développer les fonctionnalités qui vous tiennent à cœur et offrir un support continu. +cookieBanner.preferencesModal.description.2=Stirling PDF ne peut pas — et ne pourra jamais — suivre ou accéder au contenu des documents que vous utilisez. +cookieBanner.preferencesModal.description.3=Votre vie privée et votre confiance sont au cœur de notre démarche. +cookieBanner.preferencesModal.necessary.title.1=Cookies strictement nécessaires +cookieBanner.preferencesModal.necessary.title.2=Toujours activés +cookieBanner.preferencesModal.necessary.description=Ces cookies sont essentiels au bon fonctionnement du site. Ils permettent des fonctionnalités de base comme la gestion de vos préférences de confidentialité, la connexion et le remplissage de formulaires — c'est pourquoi ils ne peuvent pas être désactivés. +cookieBanner.preferencesModal.analytics.title=Analyse +cookieBanner.preferencesModal.analytics.description=Ces cookies nous aident à comprendre comment nos outils sont utilisés, afin que nous puissions nous concentrer sur les fonctionnalités les plus appréciées par notre communauté. Soyez rassuré — Stirling PDF ne peut pas et ne suivra jamais le contenu des documents que vous utilisez. #fakeScan -fakeScan.title=Fake Scan -fakeScan.header=Fake Scan -fakeScan.description=Create a PDF that looks like it was scanned -fakeScan.selectPDF=Select PDF: -fakeScan.quality=Scan Quality -fakeScan.quality.low=Low -fakeScan.quality.medium=Medium -fakeScan.quality.high=High -fakeScan.rotation=Rotation Angle -fakeScan.rotation.none=None -fakeScan.rotation.slight=Slight -fakeScan.rotation.moderate=Moderate -fakeScan.rotation.severe=Severe -fakeScan.submit=Create Fake Scan +fakeScan.title=Fausse numérisation +fakeScan.header=Fausse numérisation +fakeScan.description=Créer un PDF qui ressemble à une numérisation +fakeScan.selectPDF=Sélectionner un PDF : +fakeScan.quality=Qualité de numérisation +fakeScan.quality.low=Faible +fakeScan.quality.medium=Moyenne +fakeScan.quality.high=Élevée +fakeScan.rotation=Angle de rotation +fakeScan.rotation.none=Aucun +fakeScan.rotation.slight=Léger +fakeScan.rotation.moderate=Modéré +fakeScan.rotation.severe=Sévère +fakeScan.submit=Créer une fausse numérisation #home.fakeScan -home.fakeScan.title=Fake Scan -home.fakeScan.desc=Create a PDF that looks like it was scanned -fakeScan.tags=scan,simulate,realistic,convert +home.fakeScan.title=Fausse numérisation +home.fakeScan.desc=Créer un PDF qui ressemble à une numérisation +fakeScan.tags=numérisation,simuler,réaliste,convertir,scan,simulate,realistic,convert # FakeScan advanced settings (frontend) -fakeScan.advancedSettings=Enable Advanced Scan Settings -fakeScan.colorspace=Colorspace -fakeScan.colorspace.grayscale=Grayscale -fakeScan.colorspace.color=Color -fakeScan.border=Border (px) -fakeScan.rotate=Base Rotation (degrees) -fakeScan.rotateVariance=Rotation Variance (degrees) -fakeScan.brightness=Brightness -fakeScan.contrast=Contrast -fakeScan.blur=Blur -fakeScan.noise=Noise -fakeScan.yellowish=Yellowish (simulate old paper) -fakeScan.resolution=Resolution (DPI) +fakeScan.advancedSettings=Activer les paramètres de numérisation avancés +fakeScan.colorspace=Espace colorimétrique +fakeScan.colorspace.grayscale=Niveaux de gris +fakeScan.colorspace.color=Couleur +fakeScan.border=Bordure (px) +fakeScan.rotate=Rotation de base (degrés) +fakeScan.rotateVariance=Variance de rotation (degrés) +fakeScan.brightness=Luminosité +fakeScan.contrast=Contraste +fakeScan.blur=Flou +fakeScan.noise=Bruit +fakeScan.yellowish=Jaunâtre (simuler du vieux papier) +fakeScan.resolution=Résolution (DPI) # Table of Contents Feature -home.editTableOfContents.title=Edit Table of Contents -home.editTableOfContents.desc=Add or edit bookmarks and table of contents in PDF documents +home.editTableOfContents.title=Modifier la table des matières +home.editTableOfContents.desc=Ajouter ou modifier les signets et la table des matières dans les documents PDF -editTableOfContents.tags=bookmarks,toc,navigation,index,table of contents,chapters,sections,outline -editTableOfContents.title=Edit Table of Contents -editTableOfContents.header=Add or Edit PDF Table of Contents -editTableOfContents.replaceExisting=Replace existing bookmarks (uncheck to append to existing) -editTableOfContents.editorTitle=Bookmark Editor -editTableOfContents.editorDesc=Add and arrange bookmarks below. Click + to add child bookmarks. -editTableOfContents.addBookmark=Add New Bookmark -editTableOfContents.desc.1=This tool allows you to add or edit the table of contents (bookmarks) in a PDF document. -editTableOfContents.desc.2=You can create a hierarchical structure by adding child bookmarks to parent bookmarks. -editTableOfContents.desc.3=Each bookmark requires a title and target page number. -editTableOfContents.submit=Apply Table of Contents +editTableOfContents.tags=signets,tdm,table des matières,chapitres,sections,plan,bookmarks,toc,navigation,index,table of contents,chapters,sections,outline +editTableOfContents.title=Modifier la table des matières +editTableOfContents.header=Ajouter ou modifier la table des matières PDF +editTableOfContents.replaceExisting=Remplacer les signets existants (décocher pour ajouter aux existants) +editTableOfContents.editorTitle=Éditeur de signets +editTableOfContents.editorDesc=Ajoutez et organisez les signets ci-dessous. Cliquez sur + pour ajouter des signets enfants. +editTableOfContents.addBookmark=Ajouter un nouveau signet +editTableOfContents.desc.1=Cet outil vous permet d'ajouter ou de modifier la table des matières (signets) dans un document PDF. +editTableOfContents.desc.2=Vous pouvez créer une structure hiérarchique en ajoutant des signets enfants à des signets parents. +editTableOfContents.desc.3=Chaque signet nécessite un titre et un numéro de page cible. +editTableOfContents.submit=Appliquer la table des matières diff --git a/stirling-pdf/src/main/resources/messages_ga_IE.properties b/app/core/src/main/resources/messages_ga_IE.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_ga_IE.properties rename to app/core/src/main/resources/messages_ga_IE.properties index 09f61437c..332ac4e76 100644 --- a/stirling-pdf/src/main/resources/messages_ga_IE.properties +++ b/app/core/src/main/resources/messages_ga_IE.properties @@ -163,13 +163,74 @@ alphabet=Aibítir downloadPdf=Íoslódáil PDF text=Téacs font=Cló -selectFillter=-- Roghnaigh -- +selectFilter=-- Roghnaigh -- pageNum=Uimhir an Leathanaigh sizes.small=Beaga sizes.medium=Mheán sizes.large=Mór sizes.x-large=X-Mór error.pdfPassword=Tá pasfhocal ar an Doiciméad PDF agus níor soláthraíodh an pasfhocal nó bhí sé mícheart +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Scrios username=Ainm úsáideora password=Pasfhocal @@ -181,7 +242,6 @@ red=Dearg green=Glas blue=Gorm custom=Saincheaptha... -WorkInProgess=Obair idir lámha, B’fhéidir nach n-oibreoidh sí nó nach mbeidh bugaí ann, Tuairiscigh aon fhadhbanna le do thoil! poweredBy=Cumhachtaithe ag yes=Tá no=Níl @@ -525,6 +585,10 @@ home.addImage.title=Cuir íomhá leis home.addImage.desc=Cuireann sé íomhá ar shuíomh socraithe ar an PDF addImage.tags=img, jpg, pictiúr, grianghraf +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Cuir Uisce leis home.watermark.desc=Cuir comhartha uisce saincheaptha le do dhoiciméad PDF. watermark.tags=Téacs, athrá, lipéad, úinéireacht, cóipcheart, trádmharc, img, jpg, pictiúr, grianghraf @@ -1205,6 +1269,12 @@ addImage.everyPage=Gach Leathanach? addImage.upload=Cuir íomhá leis addImage.submit=Cuir íomhá leis +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Cumaisc @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Tarraing & Scaoil comhad PDF fileChooser.dragAndDropImage=Tarraing & Scaoil comhad Íomhá fileChooser.hoveredDragAndDrop=Tarraing agus scaoil comhad(í) anseo fileChooser.extractPDF=Ag Aistriú... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Eisiúintí diff --git a/stirling-pdf/src/main/resources/messages_hi_IN.properties b/app/core/src/main/resources/messages_hi_IN.properties similarity index 96% rename from stirling-pdf/src/main/resources/messages_hi_IN.properties rename to app/core/src/main/resources/messages_hi_IN.properties index 7ea02ae0f..29d1e1ee5 100644 --- a/stirling-pdf/src/main/resources/messages_hi_IN.properties +++ b/app/core/src/main/resources/messages_hi_IN.properties @@ -163,13 +163,74 @@ alphabet=वर्णमाला downloadPdf=पीडीएफ डाउनलोड करें text=टेक्स्ट font=फ़ॉन्ट -selectFillter=-- चुनें -- +selectFilter=-- चुनें -- pageNum=पृष्ठ संख्या sizes.small=छोटा sizes.medium=मध्यम sizes.large=बड़ा sizes.x-large=बहुत बड़ा error.pdfPassword=पीडीएफ दस्तावेज़ पासवर्ड से सुरक्षित है और या तो पासवर्ड नहीं दिया गया था या गलत था +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=हटाएं username=उपयोगकर्ता नाम password=पासवर्ड @@ -181,7 +242,6 @@ red=लाल green=हरा blue=नीला custom=कस्टम... -WorkInProgess=कार्य प्रगति पर है, काम नहीं कर सकता है या बग हो सकते हैं, कृपया किसी भी समस्या की रिपोर्ट करें! poweredBy=द्वारा संचालित yes=हाँ no=नहीं @@ -525,6 +585,10 @@ home.addImage.title=छवि जोड़ें home.addImage.desc=PDF पर एक निर्धारित स्थान पर छवि जोड़ें addImage.tags=img,jpg,चित्र,फोटो +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=वॉटरमार्क जोड़ें home.watermark.desc=अपने PDF दस्तावेज में कस्टम वॉटरमार्क जोड़ें। watermark.tags=टेक्स्ट,दोहराव,लेबल,स्वयं,कॉपीराइट,ट्रेडमार्क,img,jpg,चित्र,फोटो @@ -1205,6 +1269,12 @@ addImage.everyPage=हर पृष्ठ? addImage.upload=छवि जोड़ें addImage.submit=छवि जोड़ें +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=मर्ज करें @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=PDF फ़ाइल खींचें और छो fileChooser.dragAndDropImage=छवि फ़ाइल खींचें और छोड़ें fileChooser.hoveredDragAndDrop=फ़ाइल(ें) यहाँ खींचें और छोड़ें fileChooser.extractPDF=निकालना... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=रिलीज़ diff --git a/stirling-pdf/src/main/resources/messages_hr_HR.properties b/app/core/src/main/resources/messages_hr_HR.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_hr_HR.properties rename to app/core/src/main/resources/messages_hr_HR.properties index 49b2b36ad..321e1b141 100644 --- a/stirling-pdf/src/main/resources/messages_hr_HR.properties +++ b/app/core/src/main/resources/messages_hr_HR.properties @@ -163,13 +163,74 @@ alphabet=Abeceda downloadPdf=Preuzmi PDF text=Tekst font=Pismo -selectFillter=-- Odaberi -- +selectFilter=-- Odaberi -- pageNum=Broj stranice sizes.small=Malo sizes.medium=Srednje sizes.large=Veliko sizes.x-large=Jako veliko error.pdfPassword=PDF dokument je šifriran i zaporka nije dana ili je netočna +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Izbriši username=Korisničko ime password=Zaporka @@ -181,7 +242,6 @@ red=Crveno green=Zeleno blue=Plavo custom=Prilagođeno... -WorkInProgess=Radovi u tijeku, u slučaju grešaka molimo prijavite probleme! poweredBy=Pokreće yes=Da no=Ne @@ -525,6 +585,10 @@ home.addImage.title=Dodaj sliku home.addImage.desc=Dodaje sliku na zadano mjesto u PDF-u addImage.tags=img,jpg,slika,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Dodaj vodeni žig home.watermark.desc=DDodajte prilagođeni vodeni žig svom PDF dokumentu. watermark.tags=Tekst,ponavljanje,etiketa,vlastiti,autorsko pravo,zaštita, img,jpg,slika,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Na svakoj stranici? addImage.upload=Dodaj sliku addImage.submit=Dodaj sliku +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Spajanje @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_hu_HU.properties b/app/core/src/main/resources/messages_hu_HU.properties similarity index 93% rename from stirling-pdf/src/main/resources/messages_hu_HU.properties rename to app/core/src/main/resources/messages_hu_HU.properties index eee163a92..8c38c44c4 100644 --- a/stirling-pdf/src/main/resources/messages_hu_HU.properties +++ b/app/core/src/main/resources/messages_hu_HU.properties @@ -142,7 +142,7 @@ multiPdfPrompt=PDF-fájlok kiválasztása (2+) multiPdfDropPrompt=Válassza ki (vagy húzza ide) az összes szükséges PDF-fájlt imgPrompt=Kép kiválasztása genericSubmit=Küldés -uploadLimit=Maximum file size: +uploadLimit=Maximális fájlméret: uploadLimitExceededSingular=túl nagy. A maximálisan megengedett méret uploadLimitExceededPlural=túl nagyok. A maximálisan megengedett méretek processTimeWarning=Figyelmeztetés: A folyamat akár egy percig is eltarthat a fájlmérettől függően @@ -163,13 +163,74 @@ alphabet=ABC downloadPdf=PDF letöltése text=Szöveg font=Betűtípus -selectFillter=-- Válasszon -- +selectFilter=-- Válasszon -- pageNum=Oldalszám sizes.small=Kicsi sizes.medium=Közepes sizes.large=Nagy sizes.x-large=Extra nagy error.pdfPassword=A PDF-dokumentum jelszóval védett, és vagy nem adott meg jelszót, vagy helytelen jelszót adott meg +error.pdfCorrupted=A PDF-fájl sérültnek vagy hibásnak tűnik. Mielőtt folytatná ezt a műveletet, próbálja meg először a 'PDF javítása' funkcióval kijavítani a fájlt. +error.pdfCorruptedMultiple=Egy vagy több PDF-fájl sérültnek vagy hibásnak tűnik. Mielőtt megpróbálná egyesíteni őket, próbálja meg először a 'PDF javítása' funkciót használni minden fájlon. +error.pdfCorruptedDuring=Hiba {0}: A PDF-fájl sérültnek vagy hibásnak tűnik. Mielőtt folytatná ezt a műveletet, próbálja meg először a 'PDF javítása' funkcióval kijavítani a fájlt. + +# Frontend corruption error messages +error.pdfInvalid=A(z) "{0}" PDF-fájl sérültnek tűnik, vagy érvénytelen szerkezetű. Kérjük, a folytatás előtt próbálja meg a 'PDF javítása' funkcióval kijavítani a fájlt. +error.tryRepair=Próbálja meg a PDF javítása funkciót a sérült fájlok javításához. + +# Additional error messages +error.pdfEncryption=Úgy tűnik, a PDF titkosítási adatai sérültek. Ez akkor fordulhat elő, ha a PDF-et nem kompatibilis titkosítási módszerekkel hozták létre. Kérjük, először próbálja meg a 'PDF javítása' funkciót használni, vagy kérjen új másolatot a dokumentum készítőjétől. +error.fileProcessing=Hiba történt a fájl feldolgozása közben a(z) {0} művelet során: {1} + +# Generic error message templates +error.toolNotInstalled=A(z) {0} nincs telepítve +error.toolRequired=A(z) {0} szükséges a(z) {1} művelethez +error.conversionFailed=A(z) {0} konvertálása sikertelen +error.commandFailed=A(z) {0} parancs végrehajtása sikertelen +error.algorithmNotAvailable=A(z) {0} algoritmus nem érhető el +error.optionsNotSpecified=A(z) {0} beállítások nincsenek megadva +error.fileFormatRequired=A fájlnak {0} formátumúnak kell lennie +error.invalidFormat=Érvénytelen {0} formátum: {1} +error.endpointDisabled=Ezt a végpontot a rendszergazda letiltotta +error.urlNotReachable=Az URL nem érhető el, kérjük, adjon meg érvényes URL-t + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=A(z) {0} DPI érték meghaladja a(z) {1} biztonságos maximális határértéket. A magas DPI-értékek memóriaproblémákat és összeomlásokat okozhatnak. Kérjük, használjon alacsonyabb DPI-értéket. +error.pageTooBigForDpi=A(z) {0} PDF-oldal túl nagy a(z) {1} DPI-vel való megjelenítéshez. Kérjük, próbáljon meg alacsonyabb DPI-értéket (ajánlott: 150 vagy kevesebb). +error.pageTooBigExceedsArray=A(z) {0} PDF-oldal túl nagy a(z) {1} DPI-vel való megjelenítéshez. Az eredményül kapott kép meghaladná a Java maximális tömbméretét. Kérjük, próbáljon meg alacsonyabb DPI-értéket (ajánlott: 150 vagy kevesebb). +error.pageTooBigFor300Dpi=A(z) {0} PDF-oldal túl nagy a 300 DPI-vel való megjelenítéshez. Az eredményül kapott kép meghaladná a Java maximális tömbméretét. Kérjük, használjon alacsonyabb DPI-értéket a PDF-kép konverzióhoz. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=Az API-kulcs érvénytelen. +error.userNotFound=A felhasználó nem található. +error.passwordRequired=A jelszó nem lehet üres. +error.accountLocked=Fiókját zároltuk a túl sok sikertelen bejelentkezési kísérlet miatt. +error.invalidEmail=Érvénytelen e-mail címek. +error.emailAttachmentRequired=Az e-mail küldéséhez csatolmány szükséges. +error.signatureNotFound=Az aláírásfájl nem található. + +# File processing messages +error.fileNotFound=A fájl nem található azonosítóval: {0} + +# Database and configuration messages +error.noBackupScripts=Nem találhatóak biztonsági mentési szkriptek. +error.unsupportedProvider=A(z) {0} jelenleg nem támogatott. +error.pathTraversalDetected=Útvonal-bejárási kísérlet észlelve biztonsági okokból. + +# Validation messages +error.invalidArgument=Érvénytelen argumentum: {0} +error.argumentRequired=A(z) {0} nem lehet üres +error.operationFailed=A művelet sikertelen: {0} +error.angleNotMultipleOf90=A szögnek 90-nel oszthatónak kell lennie +error.pdfBookmarksNotFound=Nem található PDF-könyvjelző/vázlat a dokumentumban +error.fontLoadingFailed=Hiba a betűtípusfájl feldolgozása közben +error.fontDirectoryReadFailed=Nem sikerült beolvasni a betűtípus-könyvtárat delete=Törlés username=Felhasználónév password=Jelszó @@ -181,7 +242,6 @@ red=Piros green=Zöld blue=Kék custom=Egyéni... -WorkInProgess=Fejlesztés alatt álló funkció, hibák előfordulhatnak. Kérjük, jelezze a problémákat! poweredBy=Üzemelteti: yes=Igen no=Nem @@ -200,7 +260,7 @@ disabledCurrentUserMessage=A jelenlegi felhasználó nem tiltható le downgradeCurrentUserLongMessage=A jelenlegi felhasználó jogosultsági szintje nem csökkenthető. Ezért a jelenlegi felhasználó nem jelenik meg. userAlreadyExistsOAuthMessage=A felhasználó már létezik OAuth2 felhasználóként. userAlreadyExistsWebMessage=A felhasználó már létezik webes felhasználóként. -invalidRoleMessage=Invalid role. +invalidRoleMessage=Érvénytelen szerepkör. error=Hiba oops=Hoppá! help=Súgó @@ -213,7 +273,7 @@ color=Szín sponsor=Támogató info=Információ pro=Pro -proFeatures=Pro Features +proFeatures=Pro Funkciók page=Oldal pages=Oldal loading=Betöltés... @@ -267,7 +327,7 @@ enterpriseEdition.button=Váltás Pro verzióra enterpriseEdition.warning=Ez a funkció csak Pro felhasználók számára érhető el. enterpriseEdition.yamlAdvert=A Stirling PDF Pro támogatja a YAML konfigurációs fájlokat és egyéb SSO funkciókat. enterpriseEdition.ssoAdvert=Több felhasználókezelési funkcióra van szüksége? Tekintse meg a Stirling PDF Pro verzióját! -enterpriseEdition.proTeamFeatureDisabled=Team management features require a Pro licence or higher +enterpriseEdition.proTeamFeatureDisabled=A csapatkezelési funkciókhoz Pro licenc vagy magasabb szintű licenc szükséges ################# @@ -525,6 +585,10 @@ home.addImage.title=Kép hozzáadása home.addImage.desc=Kép hozzáadása a PDF megadott helyére addImage.tags=kép,jpg,fotó,fénykép +home.attachments.title=Csatolmányok hozzáadása a PDF-hez +home.attachments.desc=Csatolmányok (beágyazott fájlok) hozzáadása vagy eltávolítása a PDF-ből +attachments.tags=beágyazás,csatolás,fájl,csatolmány,csatolmányok + home.watermark.title=Vízjel hozzáadása home.watermark.desc=Egyedi vízjel hozzáadása PDF dokumentumhoz watermark.tags=Szöveg,ismétlődő,címke,egyedi,szerzői jog,védjegy,kép,jpg,fotó,fénykép @@ -676,7 +740,7 @@ home.HTMLToPDF.desc=HTML fájl vagy ZIP konvertálása PDF-be HTMLToPDF.tags=jelölőnyelv,webtartalom,átalakítás,konvertálás #eml-to-pdf -home.EMLToPDF.title=E-mail PDF-be +home.EMLToPDF.title=E-mail konvertálása PDF-be home.EMLToPDF.desc=E-mail (EML) fájlok konvertálása PDF formátumba, beleértve a fejléceket, törzset és beágyazott képeket EMLToPDF.tags=e-mail,konverzió,eml,üzenet,átalakítás,konvertálás,levél @@ -1205,6 +1269,12 @@ addImage.everyPage=Minden oldalra? addImage.upload=Kép hozzáadása addImage.submit=Kép hozzáadása +#attachments +attachments.title=Mellékletek hozzáadása +attachments.header=Mellékletek hozzáadása +attachments.description=Lehetővé teszi mellékletek hozzáadását a PDF-hez +attachments.descriptionPlaceholder=Adjon meg egy leírást a mellékletekhez... +attachments.addButton=Mellékletek hozzáadása #merge merge.title=Egyesítés @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Húzza ide a PDF fájlt fileChooser.dragAndDropImage=Húzza ide a képfájlt fileChooser.hoveredDragAndDrop=Húzza ide a fájl(oka)t fileChooser.extractPDF=Kinyerés... +fileChooser.addAttachments=Húzza ide a csatolmányokat #release notes releases.footer=Kiadási jegyzék diff --git a/stirling-pdf/src/main/resources/messages_id_ID.properties b/app/core/src/main/resources/messages_id_ID.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_id_ID.properties rename to app/core/src/main/resources/messages_id_ID.properties index d5a38442c..218a7275c 100644 --- a/stirling-pdf/src/main/resources/messages_id_ID.properties +++ b/app/core/src/main/resources/messages_id_ID.properties @@ -163,13 +163,74 @@ alphabet=Abjad downloadPdf=Unduh PDF text=Teks font=Jenis huruf -selectFillter=-- Pilih -- +selectFilter=-- Pilih -- pageNum=Nomor Halaman sizes.small=Kecil sizes.medium=Sedang sizes.large=Besar sizes.x-large=Sangat Besar error.pdfPassword=Dokumen PDF disandikan dan kata sandi tidak diberikan atau kata sandi salah +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Hapus username=Nama pengguna password=Kata sandi @@ -181,7 +242,6 @@ red=Merah green=Hijau blue=Biru custom=Kustom... -WorkInProgess=Pekerjaan sedang diproses, Mungkin tidak berfungsi atau terdapat kutu, Silakan laporkan masalah apa pun! poweredBy=Ditenagai oleh yes=Ya no=Tidak @@ -525,6 +585,10 @@ home.addImage.title=Tambahkan gambar home.addImage.desc=Menambahkan gambar ke lokasi yang ditentukan pada PDF addImage.tags=img,jpg,gambar,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Tambahkan watermark home.watermark.desc=Menambahkan watermark khusus ke dokumen PDF Anda. watermark.tags=Teks,berulang,label,sendiri,hak cipta,watermark,img,jpg,picture,photo @@ -1205,6 +1269,12 @@ addImage.everyPage=Setiap Halaman? addImage.upload=Tambahkan Gambar addImage.submit=Tambahkan Gambar +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Gabungkan @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_it_IT.properties b/app/core/src/main/resources/messages_it_IT.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_it_IT.properties rename to app/core/src/main/resources/messages_it_IT.properties index 06662dccc..2cce71c66 100644 --- a/stirling-pdf/src/main/resources/messages_it_IT.properties +++ b/app/core/src/main/resources/messages_it_IT.properties @@ -163,13 +163,74 @@ alphabet=Alfabeto downloadPdf=Scarica PDF text=Testo font=Font -selectFillter=-- Seleziona -- +selectFilter=-- Seleziona -- pageNum=Numero pagina sizes.small=Piccolo sizes.medium=Medio sizes.large=Grande sizes.x-large=Extra-Large error.pdfPassword=Il documento PDF è protetto da password e la password non è stata fornita oppure non era corretta +error.pdfCorrupted=Il file PDF sembra corrotto o danneggiato. Prova a utilizzare la funzione "Ripara PDF" per riparare il file prima di procedere con questa operazione. +error.pdfCorruptedMultiple=Uno o più file PDF sembrano corrotti o danneggiati. Prova a utilizzare la funzione 'Ripara PDF' su ciascun file prima di tentare di unirli. +error.pdfCorruptedDuring=Errore {0}: il file PDF sembra essere corrotto o danneggiato. Provare a utilizzare la funzione 'Ripara PDF' per riparare il file prima di procedere con questa operazione. + +# Frontend corruption error messages +error.pdfInvalid=Il file PDF "{0}" sembra essere danneggiato o ha una struttura non valida. Prova a utilizzare la funzione 'Ripara PDF' per correggere il file prima di procedere. +error.tryRepair=Prova a utilizzare la funzionalità Ripara PDF per riparare i file danneggiati. + +# Additional error messages +error.pdfEncryption=Il PDF sembra contenere dati di crittografia danneggiati. Questo può accadere quando il PDF è stato creato con metodi di crittografia incompatibili. Prova prima a utilizzare la funzione 'Ripara PDF' o contatta l'autore del documento per ottenere una nuova copia. +error.fileProcessing=Si è verificato un errore durante l'elaborazione del file durante l'operazione {0}: {1} + +# Generic error message templates +error.toolNotInstalled={0} non è installato +error.toolRequired={0} è richiesto per {1} +error.conversionFailed={0} conversione fallita +error.commandFailed={0} comando fallito +error.algorithmNotAvailable={0} algoritmo non disponibile +error.optionsNotSpecified={0} le opzioni non sono specificate +error.fileFormatRequired=Il file deve essere nel formato {0} +error.invalidFormat=Formato {0} non valido:{1} +error.endpointDisabled=Questo endpoint è stato disabilitato dall'amministratore +error.urlNotReachable=L'URL non è raggiungibile, inserisci un URL valido + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=Il valore DPI {0} supera il limite massimo di sicurezza di {1}. Valori DPI elevati possono causare problemi di memoria e arresti anomali. Utilizzare un valore DPI inferiore. +error.pageTooBigForDpi=La pagina PDF {0} è troppo grande per essere visualizzata a {1} DPI. Prova un valore DPI inferiore (consigliato: 150 o inferiore). +error.pageTooBigExceedsArray=La pagina PDF {0} è troppo grande per essere visualizzata a {1} DPI. L'immagine risultante supererebbe la dimensione massima dell'array Java. Prova un valore DPI inferiore (consigliato: 150 o inferiore). +error.pageTooBigFor300Dpi=La pagina PDF {0} è troppo grande per essere renderizzata a 300 DPI. L'immagine risultante supererebbe la dimensione massima dell'array Java. Utilizzare un valore DPI inferiore per la conversione da PDF a immagine. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=La chiave API non è valida. +error.userNotFound=Utente non trovato. +error.passwordRequired=La password non deve essere nulla. +error.accountLocked=Il tuo account è stato bloccato a causa di troppi tentativi di accesso non riusciti. +error.invalidEmail=Indirizzi email non validi forniti. +error.emailAttachmentRequired=Per inviare l'email è necessario un allegato. +error.signatureNotFound=File della firma non trovato. + +# File processing messages +error.fileNotFound=File non trovato con ID: {0} + +# Database and configuration messages +error.noBackupScripts=Non sono stati trovati script di backup. +error.unsupportedProvider={0} non è attualmente supportato. +error.pathTraversalDetected=Per motivi di sicurezza è stato rilevato un attraversamento del percorso. + +# Validation messages +error.invalidArgument=Argomento non valido: {0} +error.argumentRequired={0} non deve essere nullo +error.operationFailed=Operazione fallita: {0} +error.angleNotMultipleOf90=L'angolo deve essere un multiplo di 90 +error.pdfBookmarksNotFound=Nessun segnalibro/schema PDF trovato nel documento +error.fontLoadingFailed=Errore durante l'elaborazione del font file +error.fontDirectoryReadFailed=Impossibile leggere la directory dei font delete=Elimina username=Nome utente password=Password @@ -181,7 +242,6 @@ red=Rosso green=Verde blue=Blu custom=Personalizzato -WorkInProgess=Lavori in corso, potrebbe non funzionare o essere difettoso, segnalare eventuali problemi! poweredBy=Alimentato da yes=Si no=No @@ -525,6 +585,10 @@ home.addImage.title=Aggiungi Immagine home.addImage.desc=Aggiungi un'immagine in un punto specifico del PDF (Lavori in corso) addImage.tags=img,jpg,immagine,foto +home.attachments.title=Aggiungi allegati +home.attachments.desc=Aggiungere o rimuovere file incorporati (allegati) da/a un PDF +attachments.tags=incorporare,allegare,file,allegato,allegati + home.watermark.title=Aggiungi Filigrana home.watermark.desc=Aggiungi una filigrana al tuo PDF. watermark.tags=Testo,ripetizione,etichetta,proprio,copyright,marchio,img,jpg,immagine,foto @@ -1199,12 +1263,18 @@ compress.submit=Comprimi #Add image -addImage.title=Aggiungi Immagine +addImage.title=Aggiungere Immagine addImage.header=Aggiungi un'immagine ad un PDF addImage.everyPage=Ogni pagina? addImage.upload=Aggiungi immagine addImage.submit=Aggiungi immagine +#attachments +attachments.title=Aggiungere allegati +attachments.header=Aggiungi allegati +attachments.description=Consente di aggiungere allegati al PDF +attachments.descriptionPlaceholder=Inserisci una descrizione per gli allegati... +attachments.addButton=Aggiungi allegati #merge merge.title=Unisci @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Trascina & rilascia il file PDF fileChooser.dragAndDropImage=Trascina & rilascia il file immagine fileChooser.hoveredDragAndDrop=Trascina & rilascia i file qui fileChooser.extractPDF=Estraendo... +fileChooser.addAttachments=trascina & rilascia gli allegati qui #release notes releases.footer=Rilasci diff --git a/stirling-pdf/src/main/resources/messages_ja_JP.properties b/app/core/src/main/resources/messages_ja_JP.properties similarity index 69% rename from stirling-pdf/src/main/resources/messages_ja_JP.properties rename to app/core/src/main/resources/messages_ja_JP.properties index 6e2a8f6a3..b4a2bdbc0 100644 --- a/stirling-pdf/src/main/resources/messages_ja_JP.properties +++ b/app/core/src/main/resources/messages_ja_JP.properties @@ -5,149 +5,149 @@ language.direction=ltr # Language names for reuse throughout the application -lang.afr=Afrikaans -lang.amh=Amharic -lang.ara=Arabic -lang.asm=Assamese -lang.aze=Azerbaijani -lang.aze_cyrl=Azerbaijani (Cyrillic) -lang.bel=Belarusian -lang.ben=Bengali -lang.bod=Tibetan -lang.bos=Bosnian -lang.bre=Breton -lang.bul=Bulgarian -lang.cat=Catalan -lang.ceb=Cebuano -lang.ces=Czech -lang.chi_sim=Chinese (Simplified) -lang.chi_sim_vert=Chinese (Simplified, Vertical) -lang.chi_tra=Chinese (Traditional) -lang.chi_tra_vert=Chinese (Traditional, Vertical) -lang.chr=Cherokee -lang.cos=Corsican -lang.cym=Welsh -lang.dan=Danish -lang.dan_frak=Danish (Fraktur) -lang.deu=German -lang.deu_frak=German (Fraktur) -lang.div=Divehi -lang.dzo=Dzongkha -lang.ell=Greek -lang.eng=English -lang.enm=English, Middle (1100-1500) -lang.epo=Esperanto -lang.equ=Math / equation detection module -lang.est=Estonian -lang.eus=Basque -lang.fao=Faroese -lang.fas=Persian -lang.fil=Filipino -lang.fin=Finnish -lang.fra=French -lang.frk=Frankish -lang.frm=French, Middle (ca.1400-1600) -lang.fry=Western Frisian -lang.gla=Scottish Gaelic -lang.gle=Irish -lang.glg=Galician -lang.grc=Ancient Greek -lang.guj=Gujarati -lang.hat=Haitian, Haitian Creole -lang.heb=Hebrew -lang.hin=Hindi -lang.hrv=Croatian -lang.hun=Hungarian -lang.hye=Armenian -lang.iku=Inuktitut -lang.ind=Indonesian -lang.isl=Icelandic -lang.ita=Italian -lang.ita_old=Italian (Old) -lang.jav=Javanese -lang.jpn=Japanese -lang.jpn_vert=Japanese (Vertical) -lang.kan=Kannada -lang.kat=Georgian -lang.kat_old=Georgian (Old) -lang.kaz=Kazakh -lang.khm=Central Khmer -lang.kir=Kirghiz, Kyrgyz -lang.kmr=Northern Kurdish -lang.kor=Korean -lang.kor_vert=Korean (Vertical) -lang.lao=Lao -lang.lat=Latin -lang.lav=Latvian -lang.lit=Lithuanian -lang.ltz=Luxembourgish -lang.mal=Malayalam -lang.mar=Marathi -lang.mkd=Macedonian -lang.mlt=Maltese -lang.mon=Mongolian -lang.mri=Maori -lang.msa=Malay -lang.mya=Burmese -lang.nep=Nepali -lang.nld=Dutch; Flemish -lang.nor=Norwegian -lang.oci=Occitan (post 1500) -lang.ori=Oriya -lang.osd=Orientation and script detection module -lang.pan=Panjabi, Punjabi -lang.pol=Polish -lang.por=Portuguese -lang.pus=Pushto, Pashto -lang.que=Quechua -lang.ron=Romanian, Moldavian, Moldovan -lang.rus=Russian -lang.san=Sanskrit -lang.sin=Sinhala, Sinhalese -lang.slk=Slovak -lang.slk_frak=Slovak (Fraktur) -lang.slv=Slovenian -lang.snd=Sindhi -lang.spa=Spanish -lang.spa_old=Spanish (Old) -lang.sqi=Albanian -lang.srp=Serbian -lang.srp_latn=Serbian (Latin) -lang.sun=Sundanese -lang.swa=Swahili -lang.swe=Swedish -lang.syr=Syriac -lang.tam=Tamil -lang.tat=Tatar -lang.tel=Telugu -lang.tgk=Tajik -lang.tgl=Tagalog -lang.tha=Thai -lang.tir=Tigrinya -lang.ton=Tonga (Tonga Islands) -lang.tur=Turkish -lang.uig=Uighur, Uyghur -lang.ukr=Ukrainian -lang.urd=Urdu -lang.uzb=Uzbek -lang.uzb_cyrl=Uzbek (Cyrillic) -lang.vie=Vietnamese -lang.yid=Yiddish -lang.yor=Yoruba +lang.afr=アフリカーンス語 +lang.amh=アムハラ語 +lang.ara=アラビア語 +lang.asm=アッサム語 +lang.aze=アゼルバイジャン語 +lang.aze_cyrl=アゼルバイジャン語(キリル文字) +lang.bel=ベラルーシ語 +lang.ben=ベンガル語 +lang.bod=チベット語 +lang.bos=ボスニア語 +lang.bre=ブルトン語 +lang.bul=ブルガリア語 +lang.cat=カタロニア語 +lang.ceb=セブアノ語 +lang.ces=チェコ語 +lang.chi_sim=中国語(簡体字) +lang.chi_sim_vert=中国語(簡体字、 縦書き) +lang.chi_tra=中国語(繁体字) +lang.chi_tra_vert=中国語(繁体字、 縦書き) +lang.chr=チェロキー語 +lang.cos=コルシカ語 +lang.cym=ウェールズ語 +lang.dan=デンマーク語 +lang.dan_frak=デンマーク語(フラクトゥール) +lang.deu=ドイツ語 +lang.deu_frak=ドイツ語(フラクトゥール) +lang.div=ディベヒ語 +lang.dzo=ゾンカ語 +lang.ell=ギリシャ語 +lang.eng=英語 +lang.enm=中期英語 +lang.epo=エスペラント +lang.equ=数学 / 方程式検出モジュール +lang.est=エストニア語 +lang.eus=バスク語 +lang.fao=フェロー語 +lang.fas=ペルシア語 +lang.fil=フィリピン語 +lang.fin=フィンランド語 +lang.fra=フランス語 +lang.frk=フランク語 +lang.frm=中期フランス語 +lang.fry=西フリジア語 +lang.gla=スコットランド・ゲール語 +lang.gle=アイルランド語 +lang.glg=ガリシア語 +lang.grc=古代ギリシア語 +lang.guj=グジャラート語 +lang.hat=ハイチ語、ハイチ・クレオール語 +lang.heb=ヘブライ語 +lang.hin=ヒンディー語 +lang.hrv=クロアチア語 +lang.hun=ハンガリー語 +lang.hye=アルメニア語 +lang.iku=イヌクティトゥット語 +lang.ind=インドネシア語 +lang.isl=アイスランド語 +lang.ita=イタリア語 +lang.ita_old=イタリア語(旧) +lang.jav=ジャワ語 +lang.jpn=日本語 +lang.jpn_vert=日本語(縦書き) +lang.kan=カンナダ語 +lang.kat=ジョージア語 +lang.kat_old=ジョージア語(旧) +lang.kaz=カザフ語 +lang.khm=クメール語 +lang.kir=キルギス語 +lang.kmr=クルマンジー +lang.kor=韓国語 +lang.kor_vert=韓国語(縦書き) +lang.lao=ラオ語 +lang.lat=ラテン語 +lang.lav=ラトビア語 +lang.lit=リトアニア語 +lang.ltz=ルクセンブルク語 +lang.mal=マラヤーラム語 +lang.mar=マラーティー語 +lang.mkd=マケドニア語 +lang.mlt=マルタ語 +lang.mon=モンゴル語 +lang.mri=マオリ語 +lang.msa=マレー語 +lang.mya=ミャンマー語 +lang.nep=ネパール語 +lang.nld=オランダ語 +lang.nor=ノルウェー語 +lang.oci=オック語 +lang.ori=オリヤー語 +lang.osd=向きとスクリプトの検出モジュール +lang.pan=パンジャーブ語 +lang.pol=ポーランド語 +lang.por=ポルトガル語 +lang.pus=パシュトゥー語 +lang.que=ケチュア語 +lang.ron=ルーマニア語、モルドバ語 +lang.rus=ロシア語 +lang.san=サンスクリット +lang.sin=シンハラ語 +lang.slk=スロバキア語 +lang.slk_frak=スロバキア語(フラクトゥール) +lang.slv=スロベニア語 +lang.snd=シンド語 +lang.spa=スペイン語 +lang.spa_old=スペイン語(旧) +lang.sqi=アルバニア語 +lang.srp=セルビア語 +lang.srp_latn=セルビア語(ラテン文字) +lang.sun=スンダ語 +lang.swa=スワヒリ語 +lang.swe=スウェーデン語 +lang.syr=シリア語 +lang.tam=タミル語 +lang.tat=タタール語 +lang.tel=テルグ語 +lang.tgk=タジク語 +lang.tgl=タガログ語 +lang.tha=タイ語 +lang.tir=ティグリニア語 +lang.ton=トンガ語(トンガ諸島) +lang.tur=トルコ語 +lang.uig=ウイグル語 +lang.ukr=ウクライナ語 +lang.urd=ウルドゥー語 +lang.uzb=ウズベク語 +lang.uzb_cyrl=ウズベク語(キリル文字) +lang.vie=ベトナム語 +lang.yid=イディッシュ語 +lang.yor=ヨルバ語 addPageNumbers.fontSize=フォントサイズ addPageNumbers.fontName=フォント名 pdfPrompt=PDFを選択 -multiPdfPrompt=PDFを選択 (2つ以上) -multiPdfDropPrompt=PDFを選択 (又はドラッグ&ドロップ) +multiPdfPrompt=PDFを選択(2つ以上) +multiPdfDropPrompt=PDFを選択(又はドラッグ&ドロップ) imgPrompt=画像を選択 genericSubmit=送信 uploadLimit=最大ファイルサイズ: uploadLimitExceededSingular=のサイズが大きすぎます。許可された最大サイズは uploadLimitExceededPlural=のサイズが大きすぎます。許可された最大サイズは processTimeWarning=警告:この処理はファイルサイズによって1分程度かかることがあります -pageOrderPrompt=ページ順序 (ページ番号をカンマ区切り又は2n+1のような関数で入力): -pageSelectionPrompt=カスタムページ選択(ページ番号1、5、6または2n + 1などの関数のコンマ区切りリストを入力します): +pageOrderPrompt=ページ順序(ページ番号をカンマ区切り又は2n+1のような関数で入力): +pageSelectionPrompt=カスタムページ選択(ページ番号1、5、6または2n + 1などの関数のコンマ区切りリストを入力します): goToPage=移動 true=真 false=偽 @@ -163,13 +163,74 @@ alphabet=アルファベット downloadPdf=PDFをダウンロード text=テキスト font=フォント -selectFillter=-- 選択 -- +selectFilter=-- 選択 -- pageNum=ページ番号 sizes.small=小 sizes.medium=中 sizes.large=大 sizes.x-large=特大 error.pdfPassword=PDFにパスワードが設定されてますが、パスワードが入力されてないか間違ってます。 +error.pdfCorrupted=PDFファイルが破損しているようです。この操作を続行する前に「PDFの修復」機能を使用してファイルを修復してください。 +error.pdfCorruptedMultiple=1つ以上のPDFファイルが破損または損傷しているようです。結合する前に、各ファイルで「PDFの修復」機能を試してください。 +error.pdfCorruptedDuring=エラー{0}: PDFファイルが破損または損傷しているようです。この操作を続行する前に「PDFの修復」機能を使用してファイルを修復してください。 + +# Frontend corruption error messages +error.pdfInvalid=PDFファイル「{0}」は破損しているか構造が無効です。続行する前に「PDFの修復」機能を使用してファイルを修復してください。 +error.tryRepair=破損したファイルを修復するには、PDFの修復機能を使用してみてください。 + +# Additional error messages +error.pdfEncryption=PDFの暗号化データが破損しているようです。これはPDFが互換性のない暗号化方式で作成された場合に発生する可能性があります。まずは「PDFの修復」機能をお試しください。または、ドキュメントの作成者に連絡して新しいコピーを入手してください。 +error.fileProcessing={0}操作中にファイルの処理中にエラーが発生しました: {1} + +# Generic error message templates +error.toolNotInstalled={0}がインストールされていません +error.toolRequired={1}には{0}が必要です +error.conversionFailed={0}の変換に失敗しました +error.commandFailed={0}コマンドが失敗しました +error.algorithmNotAvailable={0}アルゴリズムは利用できません +error.optionsNotSpecified={0}オプションが指定されていません +error.fileFormatRequired=ファイルは{0}形式である必要があります +error.invalidFormat=無効な{0}形式: {1} +error.endpointDisabled=このエンドポイントは管理者によって無効になっています +error.urlNotReachable=URLにアクセスできません。有効なURLを入力してください + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI値{0}は安全上限値{1}を超えています。DPI値が高いとメモリ不足やクラッシュが発生する可能性があります。DPI値を低くしてください。 +error.pageTooBigForDpi=PDFページ{0}は大きすぎて{1}DPIではレンダリングできません。DPI値を下げて試してください(推奨: 150以下)。 +error.pageTooBigExceedsArray=PDFページ{0}は大きすぎて{1}DPIではレンダリングできません。結果の画像はJavaの最大配列サイズを超えます。DPI値を下げて試してください(推奨: 150以下)。 +error.pageTooBigFor300Dpi=PDFページ{0}は大きすぎて300DPIでレンダリングできません。結果の画像はJavaの最大配列サイズを超えます。PDFから画像への変換にはより低いDPI値を使用してください。 + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=APIキーは無効です。 +error.userNotFound=ユーザーが見つかりません。 +error.passwordRequired=パスワードはなしにできません。 +error.accountLocked=ログイン試行回数が多すぎるため、アカウントがロックされました。 +error.invalidEmail=無効なメールアドレスが指定されました。 +error.emailAttachmentRequired=メールを送信するには添付ファイルが必要です。 +error.signatureNotFound=署名ファイルが見つかりません。 + +# File processing messages +error.fileNotFound=ID:{0}のファイルが見つかりません + +# Database and configuration messages +error.noBackupScripts=バックアップスクリプトが見つかりませんでした。 +error.unsupportedProvider={0}は現在サポートされていません。 +error.pathTraversalDetected=セキュリティ上の理由によりパストラバーサルが検出されました。 + +# Validation messages +error.invalidArgument=無効な引数: {0} +error.argumentRequired={0}はなしにできません +error.operationFailed=操作に失敗しました: {0} +error.angleNotMultipleOf90=角度は90の倍数にしてください +error.pdfBookmarksNotFound=ドキュメント内にしおり/アウトラインが見つかりません +error.fontLoadingFailed=フォントファイルの処理中にエラーが発生しました +error.fontDirectoryReadFailed=フォントディレクトリの読み取りに失敗しました delete=削除 username=ユーザー名 password=パスワード @@ -181,7 +242,6 @@ red=赤 green=緑 blue=青 custom=カスタム... -WorkInProgess=作業中です。動作しないまたはバグがある可能性があります。問題があれば報告してください! poweredBy=Powered by yes=はい no=いいえ @@ -195,12 +255,12 @@ invalidPasswordMessage=パスワードは空にすることはできません。 confirmPasswordErrorMessage=新しいパスワードと新しいパスワードの確認は一致する必要があります。 deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。 deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。 -downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません +downgradeCurrentUserMessage=現在のユーザーのロールをダウングレードできません disabledCurrentUserMessage=現在のユーザーを無効にすることはできません -downgradeCurrentUserLongMessage=現在のユーザーの役割をダウングレードできません。したがって、現在のユーザーは表示されません。 +downgradeCurrentUserLongMessage=現在のユーザーのロールをダウングレードできません。したがって、現在のユーザーは表示されません。 userAlreadyExistsOAuthMessage=ユーザーは既にOAuth2ユーザーとして存在します。 userAlreadyExistsWebMessage=ユーザーは既にWebユーザーとして存在します。 -invalidRoleMessage=Invalid role. +invalidRoleMessage=無効なロールです。 error=エラー oops=おっと! help=ヘルプ @@ -213,27 +273,27 @@ color=色 sponsor=スポンサー info=情報 pro=Pro -proFeatures=Pro Features +proFeatures=Proの機能です page=ページ pages=ページ loading=読込中... addToDoc=ドキュメントに追加 reset=リセット apply=適用 -noFileSelected=No file selected. Please upload one. -view=View -cancel=Cancel +noFileSelected=ファイルが選択されていません。アップロードしてください。 +view=ビュー +cancel=キャンセル -back.toSettings=Back to Settings -back.toHome=Back to Home -back.toAdmin=Back to Admin +back.toSettings=設定に戻る +back.toHome=ホームに戻る +back.toAdmin=管理に戻る legal.privacy=プライバシーポリシー legal.terms=利用規約 legal.accessibility=アクセシビリティ legal.cookie=Cookieポリシー legal.impressum=著作権利者情報 -legal.showCookieBanner=Cookie Preferences +legal.showCookieBanner=クッキーの設定 ############### # Pipeline # @@ -267,7 +327,7 @@ enterpriseEdition.button=Proにアップグレード enterpriseEdition.warning=この機能はProユーザーのみが利用できます。 enterpriseEdition.yamlAdvert=Stirling PDF Proは、YAML構成ファイルやその他のSSO機能をサポートしています。 enterpriseEdition.ssoAdvert=より多くのユーザー管理機能をお探しですか? Stirling PDF Proをご覧ください -enterpriseEdition.proTeamFeatureDisabled=Team management features require a Pro licence or higher +enterpriseEdition.proTeamFeatureDisabled=チーム管理機能には、Proライセンス以上が必要です ################# @@ -307,7 +367,7 @@ settings.title=設定 settings.update=利用可能なアップデート settings.updateAvailable=バージョン {0} がインストールされています。 新しいバージョン ({1}) が利用可能です。 settings.appVersion=Appバージョン: -settings.downloadOption.title=ダウンロードオプション (zip以外の単一ファイル): +settings.downloadOption.title=ダウンロードオプション(zip以外の単一ファイル): settings.downloadOption.1=同じウィンドウで開く settings.downloadOption.2=新しいウィンドウで開く settings.downloadOption.3=ファイルをダウンロード @@ -348,8 +408,8 @@ account.property=プロパティ account.webBrowserSettings=Webブラウザ設定 account.syncToBrowser=アカウントの同期 -> ブラウザ account.syncToAccount=アカウントの同期 <- ブラウザ -account.adminTitle=Administrator Tools -account.adminNotif=You have admin privileges. Access system settings and user management. +account.adminTitle=管理者ツール +account.adminNotif=管理者権限があります。システム設定とユーザー管理にアクセスできます。 adminUserSettings.title=ユーザー制御設定 @@ -361,7 +421,7 @@ adminUserSettings.deleteUser=ユーザの削除 adminUserSettings.confirmDeleteUser=ユーザを本当に削除しますか? adminUserSettings.confirmChangeUserStatus=ユーザーを無効/有効にする必要がありますか? adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。 -adminUserSettings.role=役割 +adminUserSettings.role=ロール adminUserSettings.actions=アクション adminUserSettings.apiUser=限定されたAPIユーザー adminUserSettings.extraApiUser=追加の制限付きAPIユーザー @@ -370,7 +430,7 @@ adminUserSettings.demoUser=デモユーザー (カスタム設定なし) adminUserSettings.internalApiUser=内部APIユーザー adminUserSettings.forceChange=ログイン時にユーザー名/パスワードを強制的に変更する adminUserSettings.submit=ユーザーの保存 -adminUserSettings.changeUserRole=ユーザーの役割を変更する +adminUserSettings.changeUserRole=ユーザーのロールを変更する adminUserSettings.authenticated=認証済 adminUserSettings.editOwnProfil=プロフィールの編集 adminUserSettings.enabledUser=有効なユーザー @@ -380,48 +440,48 @@ adminUserSettings.disabledUsers=無効なユーザー: adminUserSettings.totalUsers=ユーザー合計: adminUserSettings.lastRequest=最後のリクエスト adminUserSettings.usage=使用状況を表示 -adminUserSettings.teams=View/Edit Teams -adminUserSettings.team=Team -adminUserSettings.manageTeams=Manage Teams -adminUserSettings.createTeam=Create Team -adminUserSettings.viewTeam=View Team -adminUserSettings.deleteTeam=Delete Team -adminUserSettings.teamName=Team Name -adminUserSettings.teamExists=Team already exists -adminUserSettings.teamCreated=Team created successfully -adminUserSettings.teamChanged=User's team was updated -adminUserSettings.teamHidden=Hidden -adminUserSettings.totalMembers=Total Members -adminUserSettings.confirmDeleteTeam=Are you sure you want to delete this team? +adminUserSettings.teams=チームの表示/編集 +adminUserSettings.team=チーム +adminUserSettings.manageTeams=チームの管理 +adminUserSettings.createTeam=チームの作成 +adminUserSettings.viewTeam=チームの表示 +adminUserSettings.deleteTeam=チームの削除 +adminUserSettings.teamName=チーム名 +adminUserSettings.teamExists=チームはすでに存在しています +adminUserSettings.teamCreated=チームが正常に作成されました +adminUserSettings.teamChanged=ユーザーのチームが更新されました +adminUserSettings.teamHidden=隠す +adminUserSettings.totalMembers=メンバー合計 +adminUserSettings.confirmDeleteTeam=このチームを削除してもよろしいですか? -teamCreated=Team created successfully -teamExists=A team with that name already exists -teamNameExists=Another team with that name already exists -teamNotFound=Team not found -teamDeleted=Team deleted -teamHasUsers=Cannot delete a team with users assigned -teamRenamed=Team renamed successfully +teamCreated=チームが正常に作成されました +teamExists=その名前のチームはすでに存在しています +teamNameExists=その名前の別チームがすでに存在しています +teamNotFound=チームが見つかりません +teamDeleted=チームが削除されました +teamHasUsers=ユーザーが割り当てられているチームは削除できません +teamRenamed=チーム名が正常に変更されました # Team user management -team.addUser=Add User to Team -team.selectUser=Select User -team.warning.moveUser=Warning: This will move the user from "{0}" team to "{1}" team. Are you sure? -team.confirm.moveUser=Are you sure you want to move this user from "{0}" team to "{1}" team? -team.userAdded=User successfully added to team -team.back=Back to Teams -team.internal=Internal Team -team.internalTeamNotAccessible=The Internal team is a system team and cannot be accessed -team.cannotMoveInternalUsers=Users in the Internal team cannot be moved to other teams -team.hidden=Hidden -team.name=Team Name -team.totalMembers=Total Members -team.members=Members -team.username=Username -team.role=Role -team.status=Status -team.enabled=Enabled -team.disabled=Disabled -team.noMembers=This team has no members yet. +team.addUser=チームにユーザーを追加する +team.selectUser=ユーザーを選択 +team.warning.moveUser=警告: これによりユーザーは「{0}」チームから「{1}」チームに移動します。よろしいですか? +team.confirm.moveUser=このユーザーを「{0}」チームから「{1}」チームに移動しますか? +team.userAdded=ユーザーはチームに正常に追加されました +team.back=チームに戻る +team.internal=内部チーム +team.internalTeamNotAccessible=内部チームはシステムチームなのでアクセスできません +team.cannotMoveInternalUsers=内部チームのユーザーは他のチームに移動できません +team.hidden=隠す +team.name=リーム名 +team.totalMembers=メンバー合計 +team.members=メンバー +team.username=ユーザー名 +team.role=ロール +team.status=ステータス +team.enabled=有効 +team.disabled=無効 +team.noMembers=このチームにはまだメンバーがいません。 @@ -446,7 +506,7 @@ endpointStatistics.home=ホーム endpointStatistics.login=ログイン endpointStatistics.top=トップ endpointStatistics.numberOfVisits=訪問回数 -endpointStatistics.visitsTooltip=訪問数: {0} (合計の{1}%) +endpointStatistics.visitsTooltip=訪問数: {0}(合計の{1}%) endpointStatistics.retry=再試行 database.title=データベースのインポート/エクスポート @@ -458,13 +518,13 @@ database.deleteBackupFile=バックアップファイルの削除 database.importBackupFile=バックアップファイルをインポート database.createBackupFile=バックアップファイルの作成 database.downloadBackupFile=バックアップファイルをダウンロード -database.info_1=データをインポートする際には、正しい構造を確保することが極めて重要です。不明な点がある場合は、専門家のアドバイスやサポートを受けてください。構造上のエラーは、アプリケーションの誤動作を引き起こす可能性があります。 +database.info_1=データをインポートする際には正しい構造を確保することが重要です。不明な点がある場合は専門家のアドバイスやサポートを受けてください。構造上のエラーはアプリケーションの誤動作を引き起こし、最悪の場合は全く動作しなくなる可能性があります。 database.info_2=ファイル名はアップロード時には関係ありません。アップロード後にbackup_user_yyyyMMddHHmm.sqlという形式にリネームされ、一貫した命名規則が保証されます。 database.submit=バックアップをインポート database.importIntoDatabaseSuccessed=データベースへのインポートに成功 database.backupCreated=データベースのバックアップに成功しました database.fileNotFound=ファイルが見つかりません -database.fileNullOrEmpty=ファイルはnullまたは空であってはなりません +database.fileNullOrEmpty=ファイルはなしまたは空にできません database.failedImportFile=ファイルのインポートに失敗 database.notSupported=この機能はデータベース接続では使用できません。 @@ -480,7 +540,7 @@ home.searchBar=機能検索... home.viewPdf.title=PDFの表示/編集 home.viewPdf.desc=表示、注釈、テキストや画像の追加 -viewPdf.tags=view,read,annotate,text,image +viewPdf.tags=view,read,annotate,text,image,highlight,edit home.setFavorites=お気に入りを設定 home.hideFavorites=お気に入りを隠す @@ -525,6 +585,10 @@ home.addImage.title=画像の追加 home.addImage.desc=PDF上の任意の場所に画像を追加します。 addImage.tags=img,jpg,picture,photo +home.attachments.title=添付ファイルの追加 +home.attachments.desc=PDFに埋め込みファイル(添付ファイル)を追加または削除します +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=透かしの追加 home.watermark.desc=PDFに独自の透かしを追加します。 watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo @@ -550,8 +614,8 @@ home.compressPdfs.title=圧縮 home.compressPdfs.desc=PDFを圧縮してファイルサイズを小さくします。 compressPdfs.tags=squish,small,tiny -home.unlockPDFForms.title=Unlock PDF Forms -home.unlockPDFForms.desc=Remove read-only property of form fields in a PDF document. +home.unlockPDFForms.title=PDFフォームのロックを解除 +home.unlockPDFForms.desc=PDFドキュメント内のフォームフィールドの読み取り専用プロパティを削除します。 unlockPDFForms.tags=remove,delete,form,field,readonly home.changeMetadata.title=メタデータの変更 @@ -653,10 +717,10 @@ auto-rename.tags=auto-detect,header-based,organize,relabel home.adjust-contrast.title=色/コントラストの調整 home.adjust-contrast.desc=PDFのコントラスト、彩度、明るさを調整します。 -adjust-contrast.tags=color-correction,tune,modify,enhance +adjust-contrast.tags=color-correction,tune,modify,enhance,colour-correction home.crop.title=PDFのトリミング -home.crop.desc=PDFをトリミングしてサイズを縮小します (テキストは維持します!)。 +home.crop.desc=PDFをトリミングしてサイズを縮小します(テキストは維持します!)。 crop.tags=trim,shrink,edit,shape home.autoSplitPDF.title=ページの自動分割 @@ -676,25 +740,25 @@ home.HTMLToPDF.desc=HTMLファイルまたはzipをPDFに変換します。 HTMLToPDF.tags=markup,web-content,transformation,convert #eml-to-pdf -home.EMLToPDF.title=Email to PDF -home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images +home.EMLToPDF.title=メールをPDFに変換 +home.EMLToPDF.desc=メール(EML)ファイルをヘッダー、本文、インライン画像を含むPDF形式に変換します EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail -EMLToPDF.title=Email To PDF -EMLToPDF.header=Email To PDF -EMLToPDF.submit=Convert -EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF -EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues -EMLToPDF.includeAttachments=Include attachments in PDF -EMLToPDF.maxAttachmentSize=Maximum attachment size (MB) -EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images -EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both -EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code. -EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs +EMLToPDF.title=メールをPDFに変換 +EMLToPDF.header=メールをPDFに変換 +EMLToPDF.submit=変換 +EMLToPDF.downloadHtml=PDFの代わりにHTML中間ファイルをダウンロードする +EMLToPDF.downloadHtmlHelp=これによりPDF変換の前にHTMLバージョンを見ることができ、フォーマットの問題をデバッグするのに役立ちます +EMLToPDF.includeAttachments=PDFに添付ファイルを含める +EMLToPDF.maxAttachmentSize=添付ファイルの最大サイズ(MB) +EMLToPDF.help=メール(EML)ファイルをヘッダー、本文、インライン画像を含むPDF形式に変換します +EMLToPDF.troubleshootingTip1=メールからHTMLへの変換はより信頼性の高いプロセスなため、バッチ処理では両方を保存することを推奨します +EMLToPDF.troubleshootingTip2=少数の電子メールでは、PDFが不正な形式の場合HTMLをダウンロードして問題のあるHTML/CSSコードの一部を上書きできます。 +EMLToPDF.troubleshootingTip3=ただし、埋め込みはHTMLでは動作しません home.MarkdownToPDF.title=MarkdownをPDFに変換 home.MarkdownToPDF.desc=あらゆるMarkdownファイルをPDFに変換します。 -MarkdownToPDF.tags=markup,web-content,transformation,convert +MarkdownToPDF.tags=markup,web-content,transformation,convert,md home.PDFToMarkdown.title=PDFをMarkdownに変換 home.PDFToMarkdown.desc=あらゆるPDFをMarkdownに変換します。 @@ -770,9 +834,9 @@ home.replaceColorPdf.title=色の置換と反転 home.replaceColorPdf.desc=PDF内のテキストと背景の色を置き換え、PDFのフルカラーを反転してファイルサイズを縮小します。 replaceColorPdf.tags=色の置き換え、ページ操作、バックエンド、サーバー側 replace-color.selectText.1=色の置換または反転オプション -replace-color.selectText.2=デフォルト(デフォルトの高コントラスト色) +replace-color.selectText.2=デフォルト(デフォルトの高コントラスト色) replace-color.selectText.3=カスタム(カスタマイズされた色) -replace-color.selectText.4=フル反転(すべての色を反転) +replace-color.selectText.4=フル反転(すべての色を反転) replace-color.selectText.5=高コントラストカラーオプション replace-color.selectText.6=黒背景に白文字 replace-color.selectText.7=白背景に黒文字 @@ -811,7 +875,7 @@ login.userIsDisabled=ユーザーは非アクティブ化されており、現 login.alreadyLoggedIn=すでにログインしています login.alreadyLoggedIn2=デバイスからログアウトしてもう一度お試しください。 login.toManySessions=アクティブなセッションが多すぎます -login.logoutMessage=You have been logged out. +login.logoutMessage=ログアウトしました #auto-redact autoRedact.title=自動墨消し @@ -822,7 +886,7 @@ autoRedact.textsToRedactPlaceholder=例: \n機密 \n極秘 autoRedact.useRegexLabel=正規表現を使用する autoRedact.wholeWordSearchLabel=単語単位の検索 autoRedact.customPaddingLabel=追加の余白 -autoRedact.convertPDFToImageLabel=PDFをPDF画像に変換 (墨消しの後ろのテキストを削除するために使用) +autoRedact.convertPDFToImageLabel=PDFをPDF画像に変換(墨消しの後ろのテキストを削除するために使用) autoRedact.submitButton=送信 #redact @@ -831,9 +895,9 @@ redact.header=手動墨消し redact.submit=編集 redact.textBasedRedaction=テキストベースの墨消し redact.pageBasedRedaction=ページベースの墨消し -redact.convertPDFToImageLabel=PDFをPDF画像に変換します (ボックスの背後のテキストを削除するために使用します) +redact.convertPDFToImageLabel=PDFをPDF画像に変換します(ボックスの背後のテキストを削除するために使用します) redact.pageRedactionNumbers.title=ページ -redact.pageRedactionNumbers.placeholder=(例:1,2,8、4,7,12-16、2n-1) +redact.pageRedactionNumbers.placeholder=(例:1,2,8、4,7,12-16、2n-1) redact.redactionColor.title=編集色 redact.export=出力 redact.upload=アップロード @@ -845,7 +909,7 @@ redact.nextPage=次のページ redact.previousPage=前のページ redact.toggleSidebar=サイドバーを切替え redact.showThumbnails=サムネイルを表示 -redact.showDocumentOutline=ドキュメントのアウトラインを表示 (ダブルクリックするとすべての項目を展開/折りたたむことができます) +redact.showDocumentOutline=ドキュメントのアウトラインを表示(ダブルクリックするとすべての項目を展開/折りたたむことができます) redact.showAttatchments=添付ファイルを表示 redact.showLayers=レイヤーを表示(ダブルクリックするとすべてのレイヤーがデフォルトの状態にリセットされます) redact.colourPicker=カラー選択 @@ -869,7 +933,7 @@ pdfToSinglePage.submit=単一ページに変換 pageExtracter.title=ページの抽出 pageExtracter.header=ページの抽出 pageExtracter.submit=抽出 -pageExtracter.placeholder=(例:1,2,8、4,7,12-16、2n-1) +pageExtracter.placeholder=(例:1,2,8、4,7,12-16、2n-1) #getPdfInfo @@ -877,28 +941,28 @@ getPdfInfo.title=PDFの情報を入手 getPdfInfo.header=PDFの情報を入手 getPdfInfo.submit=情報を入手 getPdfInfo.downloadJson=JSONでダウンロード -getPdfInfo.summary=PDF Summary -getPdfInfo.summary.encrypted=This PDF is encrypted so may face issues with some applications -getPdfInfo.summary.permissions=This PDF has {0} restricted permissions which may limit what you can do with it -getPdfInfo.summary.compliance=This PDF complies with the {0} standard -getPdfInfo.summary.basicInfo=Basic Information -getPdfInfo.summary.docInfo=Document Information -getPdfInfo.summary.encrypted.alert=Encrypted PDF - This document is password protected -getPdfInfo.summary.not.encrypted.alert=Unencrypted PDF - No password protection -getPdfInfo.summary.permissions.alert=Restricted Permissions - {0} actions are not allowed -getPdfInfo.summary.all.permissions.alert=All Permissions Allowed -getPdfInfo.summary.compliance.alert={0} Compliant -getPdfInfo.summary.no.compliance.alert=No Compliance Standards -getPdfInfo.summary.security.section=Security Status -getPdfInfo.section.BasicInfo=Basic Information about the PDF document including file size, page count, and language -getPdfInfo.section.Metadata=Document metadata including title, author, creation date and other document properties -getPdfInfo.section.DocumentInfo=Technical details about the PDF document structure and version -getPdfInfo.section.Compliancy=PDF standards compliance information (PDF/A, PDF/X, etc.) -getPdfInfo.section.Encryption=Security and encryption details of the document -getPdfInfo.section.Permissions=Document permission settings that control what actions can be performed -getPdfInfo.section.Other=Additional document components like bookmarks, layers, and embedded files -getPdfInfo.section.FormFields=Interactive form fields present in the document -getPdfInfo.section.PerPageInfo=Detailed information about each page in the document +getPdfInfo.summary=PDFの概要 +getPdfInfo.summary.encrypted=このPDFは暗号化されているため、一部のアプリケーションで問題が発生する可能性があります +getPdfInfo.summary.permissions=このPDFには{0}の権限の制限があり、操作内容が制限される可能性があります +getPdfInfo.summary.compliance=このPDFは{0}標準に準拠しています +getPdfInfo.summary.basicInfo=基本情報 +getPdfInfo.summary.docInfo=ドキュメント情報 +getPdfInfo.summary.encrypted.alert=暗号化されたPDF - このドキュメントはパスワードで保護されています +getPdfInfo.summary.not.encrypted.alert=暗号化されていないPDF - パスワードで保護されていません +getPdfInfo.summary.permissions.alert=制限された権限 - {0}アクションは許可されていません +getPdfInfo.summary.all.permissions.alert=すべての権限が許可されています +getPdfInfo.summary.compliance.alert={0}準拠 +getPdfInfo.summary.no.compliance.alert=コンプライアンス基準はありません +getPdfInfo.summary.security.section=セキュリティステータス +getPdfInfo.section.BasicInfo=ファイルサイズ、ページ数、言語などのPDFドキュメントの基本情報 +getPdfInfo.section.Metadata=タイトル、作成者、作成日、その他のドキュメントプロパティを含むメタデータ +getPdfInfo.section.DocumentInfo=PDFドキュメントの構造とバージョンに関する技術的な詳細 +getPdfInfo.section.Compliancy=PDF標準コンプライアンス情報(PDF/A、PDF/Xなど) +getPdfInfo.section.Encryption=ドキュメントのセキュリティと暗号化の詳細 +getPdfInfo.section.Permissions=実行できるアクションを制御するドキュメント権限の設定 +getPdfInfo.section.Other=しおり、レイヤー、埋め込みファイルなどの追加のドキュメントコンポーネント +getPdfInfo.section.FormFields=ドキュメントに存在するインタラクティブなフォームフィールド +getPdfInfo.section.PerPageInfo=ドキュメント内の各ページに関する詳細情報 #markdown-to-pdf @@ -929,14 +993,14 @@ HTMLToPDF.help=HTMLファイルと必要なhtml/css/画像などを含むZIPを HTMLToPDF.submit=変換 HTMLToPDF.credit=WeasyPrintを使用 HTMLToPDF.zoom=Webサイトを表示するためのズームレベル。 -HTMLToPDF.pageWidth=ページ幅 (cm)。 (デフォルトでは空白) -HTMLToPDF.pageHeight=ページ高さ (cm)。 (デフォルトでは空白) -HTMLToPDF.marginTop=ページ上の余白 (mm)。 (デフォルトでは空白) -HTMLToPDF.marginBottom=ページ下の余白 (mm)。 (デフォルトでは空白) -HTMLToPDF.marginLeft=ページ左の余白 (mm)。 (デフォルトでは空白) -HTMLToPDF.marginRight=ページ右の余白 (mm)。 (デフォルトでは空白) +HTMLToPDF.pageWidth=ページ幅 (cm)。(デフォルトでは空白) +HTMLToPDF.pageHeight=ページ高さ (cm)。(デフォルトでは空白) +HTMLToPDF.marginTop=ページ上の余白 (mm)。(デフォルトでは空白) +HTMLToPDF.marginBottom=ページ下の余白 (mm)。(デフォルトでは空白) +HTMLToPDF.marginLeft=ページ左の余白 (mm)。(デフォルトでは空白) +HTMLToPDF.marginRight=ページ右の余白 (mm)。(デフォルトでは空白) HTMLToPDF.printBackground=Webサイトの背景をレンダリングします。 -HTMLToPDF.defaultHeader=デフォルトのヘッダー (名前とページ番号) を有効にする +HTMLToPDF.defaultHeader=デフォルトのヘッダー(名前とページ番号)を有効にする HTMLToPDF.cssMediaType=ページのCSSメディアタイプを変更します。 HTMLToPDF.none=なし HTMLToPDF.print=印刷 @@ -1013,12 +1077,12 @@ crop.submit=送信 autoSplitPDF.title=PDFの自動分割 autoSplitPDF.header=PDFの自動分割 autoSplitPDF.description=印刷、挿入、スキャン、アップロード、およびドキュメントを自動分離します。手動での仕分けの必要ありません。 -autoSplitPDF.selectText.1=下から仕切り用紙を印刷します(白黒で問題ありません)。 +autoSplitPDF.selectText.1=下から仕切り用紙を印刷します(白黒で問題ありません)。 autoSplitPDF.selectText.2=原稿の間に仕切り用紙を挿入し、すべての原稿をまとめてスキャンします。 autoSplitPDF.selectText.3=スキャンしたPDFファイルをアップロードしStirling PDFに任せます。 autoSplitPDF.selectText.4=仕切りページは自動的に検出、削除されるので、最終的な文書はきれいに仕上がります。 autoSplitPDF.formPrompt=Stirling-PDF仕切り用紙を含むPDFを送信: -autoSplitPDF.duplexMode=両面モード (表裏スキャン) +autoSplitPDF.duplexMode=両面モード(表裏スキャン) autoSplitPDF.dividerDownload2=ダウンロード '自動仕切り用紙 (手順書付き).pdf' autoSplitPDF.submit=送信 @@ -1040,21 +1104,21 @@ scalePages.title=ページの縮尺の調整 scalePages.header=ページの縮尺の調整 scalePages.pageSize=1ページのサイズ scalePages.keepPageSize=元のサイズ -scalePages.scaleFactor=1ページの拡大レベル (トリミング)。 +scalePages.scaleFactor=1ページの拡大レベル(トリミング)。 scalePages.submit=送信 #certSign certSign.title=証明書による署名 -certSign.header=証明書を使用してPDFに署名します。 (制作中) +certSign.header=証明書を使用してPDFに署名します。(制作中) certSign.selectPDF=署名するPDFファイルを選択: certSign.jksNote=注: 証明書のタイプが以下にリストされていない場合は、keytoolコマンドラインツールを使用して証明書をJavaキーストア(.jks)ファイルに変換してください。次に以下の.jksファイル オプションを選択します。 -certSign.selectKey=秘密キーファイルを選択 (PKCS#8形式、.pemまたは.der) : -certSign.selectCert=証明書ファイルを選択 (X.509形式、.pemまたは.der) : +certSign.selectKey=秘密キーファイルを選択(PKCS#8形式、.pemまたは.der): +certSign.selectCert=証明書ファイルを選択(X.509形式、.pemまたは.der): certSign.selectP12=PKCS#12キーストアファイルを選択 (.p12または.pfx) (オプション。指定する場合は秘密キーと証明書が含まれている必要があります。): certSign.selectJKS=Javaキーストアファイルを選択 (.jks or .keystore): certSign.certType=証明書の種類 -certSign.password=キーストアまたは秘密キーのパスワードを入力 (ある場合) : +certSign.password=キーストアまたは秘密キーのパスワードを入力(ある場合): certSign.showSig=署名を表示 certSign.reason=理由 certSign.location=場所 @@ -1136,33 +1200,33 @@ flatten.submit=平坦化 #ScannerImageSplit ScannerImageSplit.selectText.1=角度のしきい値: -ScannerImageSplit.selectText.2=画像を回転させるために必要な絶対角度の最小値を設定 (初期値:10)。 +ScannerImageSplit.selectText.2=画像を回転させるために必要な絶対角度の最小値を設定(初期値:10)。 ScannerImageSplit.selectText.3=許容範囲: -ScannerImageSplit.selectText.4=推定された背景色周辺のカラーバリエーションの範囲を決定 (初期値:30)。 +ScannerImageSplit.selectText.4=推定された背景色周辺のカラーバリエーションの範囲を決定(初期値:30)。 ScannerImageSplit.selectText.5=最小面積: -ScannerImageSplit.selectText.6=画像の最小面積のしきい値を設定 (初期値:10000)。 +ScannerImageSplit.selectText.6=画像の最小面積のしきい値を設定(初期値:10000)。 ScannerImageSplit.selectText.7=最小輪郭面積: ScannerImageSplit.selectText.8=画像の最小の輪郭面積のしきい値を設定。 ScannerImageSplit.selectText.9=境界線サイズ: -ScannerImageSplit.selectText.10=出力に白い縁取りが出ないように追加・削除される境界線の大きさを設定 (初期値:1)。 +ScannerImageSplit.selectText.10=出力に白い縁取りが出ないように追加・削除される境界線の大きさを設定(初期値:1)。 ScannerImageSplit.info=Pythonがインストールされていません。実行する必要があります。 #OCR ocr.title=OCR / クリーンアップ -ocr.header=クリーンアップ / OCR (光学式文字認識) -ocr.selectText.1=PDF内で検出される言語を選択 (リストされているものは現在検出されているものです): +ocr.header=クリーンアップ / OCR(光学式文字認識) +ocr.selectText.1=PDF内で検出される言語を選択(リストされているものは現在検出されているものです): ocr.selectText.2=OCR処理されたPDFと一緒に、OCRしたテキストを含むテキストファイルを作成する ocr.selectText.3=斜めにスキャンされたページを回転させて修正する -ocr.selectText.4=ページをきれいにして背景ノイズの中からテキストを検出しにくくする。(出力は変わりません) +ocr.selectText.4=ページをきれいにして背景ノイズの中からテキストを検出しにくくする。(出力は変わりません) ocr.selectText.5=ページをきれいにして背景ノイズの中からテキストを検出しにくくし、出力はクリーンアップを維持する。 ocr.selectText.6=インタラクティブなテキストを含むページを無視し、画像ページのみをOCRする ocr.selectText.7=強制OCR、全てのページで元のテキスト要素を全て削除してOCRする -ocr.selectText.8=ノーマル (PDFにテキストが含まれている場合はエラーになります。) +ocr.selectText.8=ノーマル(PDFにテキストが含まれている場合はエラーになります。) ocr.selectText.9=追加設定 ocr.selectText.10=OCRモード -ocr.selectText.11=OCR後に画像を削除する (すべての画像を削除します。変換ステップの一部である場合にのみ有効です)。 -ocr.selectText.12=レンダリングタイプ (高度) +ocr.selectText.11=OCR後に画像を削除する(すべての画像を削除します。変換ステップの一部である場合にのみ有効です)。 +ocr.selectText.12=レンダリングタイプ(高度) ocr.help=他の言語でこれを使用する方法やDocker以外で使用する方法についてはこのドキュメントをお読みください。 ocr.credit=本サービスにはOCRにqpdfとTesseractを使用しています。 ocr.submit=OCRでPDFを処理する @@ -1201,18 +1265,24 @@ compress.submit=圧縮 #Add image addImage.title=画像の追加 addImage.header=PDFに画像を追加 -addImage.everyPage=全ページ? +addImage.everyPage=すべてのページ? addImage.upload=画像の追加 addImage.submit=画像の追加 +#attachments +attachments.title=添付ファイルの追加 +attachments.header=添付ファイルの追加 +attachments.description=PDFに添付ファイルを追加します +attachments.descriptionPlaceholder=添付ファイルの説明を入力してください... +attachments.addButton=添付ファイルの追加 #merge merge.title=結合 -merge.header=複数のPDFを結合 (2ファイル以上) +merge.header=複数のPDFを結合(2ファイル以上) merge.sortByName=名前で並べ替え merge.sortByDate=日付で並べ替え merge.removeCertSign=結合されたファイル内のデジタル署名を削除しますか? -merge.generateToc=Generate table of contents in the merged file? +merge.generateToc=結合されたファイルに目次を生成しますか? merge.submit=結合 @@ -1232,7 +1302,7 @@ pdfOrganiser.mode.8=最後を削除 pdfOrganiser.mode.9=最初と最後を削除 pdfOrganiser.mode.10=奇数-偶数の結合 pdfOrganiser.mode.11=すべてのページを複製 -pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1) +pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1) #multiTool @@ -1280,15 +1350,15 @@ viewPdf.header=PDFを表示 #pageRemover pageRemover.title=ページ削除 pageRemover.header=PDFページ削除 -pageRemover.pagesToDelete=削除するページ (ページ番号のカンマ区切りリストを入力してください): +pageRemover.pagesToDelete=削除するページ(ページ番号のカンマ区切りリストを入力してください): pageRemover.submit=ページ削除 -pageRemover.placeholder=(例:1,2,6または1-10,15-30) +pageRemover.placeholder=(例:1,2,6または1-10,15-30) #rotate rotate.title=PDFの回転 rotate.header=PDFの回転 -rotate.selectAngle=回転角度を選択 (90度の倍数): +rotate.selectAngle=回転角度を選択(90度の倍数): rotate.submit=回転 @@ -1316,7 +1386,7 @@ imageToPDF.fillPage=フルページ imageToPDF.fitDocumentToImage=ページを画像に合わせる imageToPDF.maintainAspectRatio=アスペクト比を維持する imageToPDF.selectText.2=PDFの自動回転 -imageToPDF.selectText.3=マルチファイルの処理 (複数の画像を操作する場合に有効になります) +imageToPDF.selectText.3=マルチファイルの処理(複数の画像を操作する場合に有効になります) imageToPDF.selectText.4=1つのPDFに結合 imageToPDF.selectText.5=個別のPDFに変換 @@ -1331,7 +1401,7 @@ pdfToImage.multi=複数の画像 pdfToImage.colorType=カラーモード pdfToImage.color=カラー pdfToImage.grey=グレースケール -pdfToImage.blackwhite=白黒 (データが失われる可能性があります!) +pdfToImage.blackwhite=白黒(データが失われる可能性があります!) pdfToImage.submit=変換 pdfToImage.info=Pythonがインストールされていません。WebPの変換に必要です。 pdfToImage.placeholder=(例:1,2,8、4,7,12-16、2n-1) @@ -1339,12 +1409,12 @@ pdfToImage.placeholder=(例:1,2,8、4,7,12-16、2n-1) #addPassword addPassword.title=パスワードの追加 -addPassword.header=パスワードの追加 (暗号化) +addPassword.header=パスワードの追加(暗号化) addPassword.selectText.1=暗号化するPDFを選択 addPassword.selectText.2=ユーザーパスワード addPassword.selectText.3=暗号化キーの長さ addPassword.selectText.4=値が大きいほど強力ですが、値が小さいほど互換性が高くなります。 -addPassword.selectText.5=権限の設定 (所有者パスワードとの併用をおすすめします) +addPassword.selectText.5=権限の設定(所有者パスワードとの併用をおすすめします) addPassword.selectText.6=ドキュメントの組立を禁止 addPassword.selectText.7=コンテンツの抽出を禁止 addPassword.selectText.8=アクセシビリティのための抽出を禁止 @@ -1354,7 +1424,7 @@ addPassword.selectText.11=注釈の変更を禁止 addPassword.selectText.12=印刷を禁止 addPassword.selectText.13=異なる形式の印刷を禁止 addPassword.selectText.14=所有者パスワード -addPassword.selectText.15=ドキュメントを開いた後に実行できる操作を制限します (すべてのリーダーでサポートされているわけではありません) +addPassword.selectText.15=ドキュメントを開いた後に実行できる操作を制限します(すべてのリーダーでサポートされているわけではありません) addPassword.selectText.16=ドキュメントを開くことを制限します addPassword.submit=暗号化 @@ -1367,8 +1437,8 @@ watermark.selectText.1=透かしを追加するPDFを選択: watermark.selectText.2=透かしのテキスト: watermark.selectText.3=文字サイズ: watermark.selectText.4=回転 (0-360): -watermark.selectText.5=幅スペース (各透かし間の水平方向のスペース): -watermark.selectText.6=高さスペース (各透かし間の垂直方向のスペース): +watermark.selectText.5=幅スペース(各透かし間の水平方向のスペース): +watermark.selectText.6=高さスペース(各透かし間の垂直方向のスペース): watermark.selectText.7=不透明度 (0% - 100%): watermark.selectText.8=透かしの種類: watermark.selectText.9=透かしの画像: @@ -1397,7 +1467,7 @@ permissions.submit=変更 #remove password removePassword.title=パスワードの削除 -removePassword.header=パスワードの削除 (復号化) +removePassword.header=パスワードの削除(復号化) removePassword.selectText.1=復号化するPDFを選択 removePassword.selectText.2=パスワード removePassword.submit=削除 @@ -1422,9 +1492,9 @@ changeMetadata.selectText.5=カスタムメタデータの追加 changeMetadata.submit=変更 #unlockPDFForms -unlockPDFForms.title=Remove Read-Only from Form Fields -unlockPDFForms.header=Unlock PDF Forms -unlockPDFForms.submit=Remove +unlockPDFForms.title=フォームフィールドから読み取り専用を削除 +unlockPDFForms.header=PDFフォームのロックを解除 +unlockPDFForms.submit=削除 #pdfToPDFA pdfToPDFA.title=PDFをPDF/Aに変換 @@ -1499,7 +1569,7 @@ overlay-pdfs.mode.label=オーバーレイモードの選択 overlay-pdfs.mode.sequential=シーケンシャル・オーバーレイ overlay-pdfs.mode.interleaved=インターリーブ・オーバーレイ overlay-pdfs.mode.fixedRepeat=固定リピート・オーバーレイ -overlay-pdfs.counts.label=オーバーレイ回数 (固定リピートモード用) +overlay-pdfs.counts.label=オーバーレイ回数(固定リピートモード用) overlay-pdfs.counts.placeholder=カンマ区切りでカウントを入力 (例:2,3,1) overlay-pdfs.position.label=重ね位置の選択 overlay-pdfs.position.foreground=前面 @@ -1551,7 +1621,7 @@ survey.meeting.4=パフォーマンス、エッジケース、機能のギャッ survey.meeting.5=Stirling PDFを企業で実際に使用できるように改良にご協力ください survey.meeting.6=興味がありましたら、弊社のチームに直接ご予約ください。(英語のみ) survey.meeting.7=皆さんのユースケースを掘り下げてStirling PDFをさらに改善することを楽しみにしています。 -survey.meeting.notInterested=ビジネスではない、または会議に興味がありませんか? +survey.meeting.notInterested=ビジネスではなくまた会議に興味がありませんか? survey.meeting.button=ブックミーティング #error @@ -1577,13 +1647,13 @@ removeImage.submit=画像を削除 splitByChapters.title=PDFをチャプターごとに分割 splitByChapters.header=PDFをチャプターごとに分割 -splitByChapters.bookmarkLevel=ブックマークレベル +splitByChapters.bookmarkLevel=しおりレベル splitByChapters.includeMetadata=メタデータを含める splitByChapters.allowDuplicates=重複を許可する splitByChapters.desc.1=このツールは、チャプター構造に基づいてPDFファイルを複数のPDFに分割します。 -splitByChapters.desc.2=ブックマークレベル:分割に使用するブックマークのレベルを選択します(最上位レベルの場合は0、第2レベルの場合は1など)。 +splitByChapters.desc.2=しおりレベル:分割に使用するしおりのレベルを選択します(最上位レベルの場合は0、第2レベルの場合は1など)。 splitByChapters.desc.3=メタデータを含める:チェックすると、元のPDFのメタデータが各分割PDFに含まれます。 -splitByChapters.desc.4=重複を許可:チェックすると同じページ上の複数のブックマークから個別のPDFを作成できます。 +splitByChapters.desc.4=重複を許可:チェックすると同じページ上の複数のしおりから個別のPDFを作成できます。 splitByChapters.submit=PDFを分割 #File Chooser @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=PDFファイルをドラッグ&ドロップ fileChooser.dragAndDropImage=画像ファイルをドラッグ&ドロップ fileChooser.hoveredDragAndDrop=ファイルをここにドラッグ&ドロップ fileChooser.extractPDF=抽出中... +fileChooser.addAttachments=ここに添付ファイルをドラッグアンドドロップしてください #release notes releases.footer=リリース @@ -1623,7 +1694,7 @@ validateSignature.cert.revoked=証明書は取り消されました validateSignature.signature.info=署名情報 validateSignature.signature=署名 validateSignature.signature.mathValid=署名は数学的には有効ですが: -validateSignature.selectCustomCert=カスタム証明書ファイル X.509 (オプション) +validateSignature.selectCustomCert=カスタム証明書ファイル X.509(オプション) validateSignature.cert.info=証明書の詳細 validateSignature.cert.issuer=発行者 validateSignature.cert.subject=主題 @@ -1638,82 +1709,82 @@ validateSignature.cert.selfSigned=自己署名 validateSignature.cert.bits=ビット # Audit Dashboard -audit.dashboard.title=Audit Dashboard -audit.dashboard.systemStatus=Audit System Status -audit.dashboard.status=Status -audit.dashboard.enabled=Enabled -audit.dashboard.disabled=Disabled -audit.dashboard.currentLevel=Current Level -audit.dashboard.retentionPeriod=Retention Period -audit.dashboard.days=days -audit.dashboard.totalEvents=Total Events +audit.dashboard.title=監査ダッシュボード +audit.dashboard.systemStatus=監査システムの状態 +audit.dashboard.status=ステータス +audit.dashboard.enabled=有効 +audit.dashboard.disabled=無効 +audit.dashboard.currentLevel=現在のレベル +audit.dashboard.retentionPeriod=保存期間 +audit.dashboard.days=日数 +audit.dashboard.totalEvents=イベント合計 # Audit Dashboard Tabs -audit.dashboard.tab.dashboard=Dashboard -audit.dashboard.tab.events=Audit Events -audit.dashboard.tab.export=Export +audit.dashboard.tab.dashboard=ダッシュボード +audit.dashboard.tab.events=監査イベント +audit.dashboard.tab.export=エクスポート # Dashboard Charts -audit.dashboard.eventsByType=Events by Type -audit.dashboard.eventsByUser=Events by User -audit.dashboard.eventsOverTime=Events Over Time -audit.dashboard.period.7days=7 Days -audit.dashboard.period.30days=30 Days -audit.dashboard.period.90days=90 Days +audit.dashboard.eventsByType=タイプ別イベント +audit.dashboard.eventsByUser=ユーザー別イベント +audit.dashboard.eventsOverTime=時系列でのイベント +audit.dashboard.period.7days=7日 +audit.dashboard.period.30days=30日 +audit.dashboard.period.90days=90日 # Events Tab -audit.dashboard.auditEvents=Audit Events -audit.dashboard.filter.eventType=Event Type -audit.dashboard.filter.allEventTypes=All event types -audit.dashboard.filter.user=User -audit.dashboard.filter.userPlaceholder=Filter by user -audit.dashboard.filter.startDate=Start Date -audit.dashboard.filter.endDate=End Date -audit.dashboard.filter.apply=Apply Filters -audit.dashboard.filter.reset=Reset Filters +audit.dashboard.auditEvents=監査イベント +audit.dashboard.filter.eventType=イベントタイプ +audit.dashboard.filter.allEventTypes=すべてのイベントタイプ +audit.dashboard.filter.user=ユーザー +audit.dashboard.filter.userPlaceholder=ユーザーでフィルター +audit.dashboard.filter.startDate=開始日 +audit.dashboard.filter.endDate=終了日 +audit.dashboard.filter.apply=フィルターを適用 +audit.dashboard.filter.reset=フィルターをリセット # Table Headers audit.dashboard.table.id=ID -audit.dashboard.table.time=Time -audit.dashboard.table.user=User -audit.dashboard.table.type=Type -audit.dashboard.table.details=Details -audit.dashboard.table.viewDetails=View Details +audit.dashboard.table.time=時間 +audit.dashboard.table.user=ユーザー +audit.dashboard.table.type=タイプ +audit.dashboard.table.details=詳細 +audit.dashboard.table.viewDetails=詳細を表示 # Pagination -audit.dashboard.pagination.show=Show -audit.dashboard.pagination.entries=entries -audit.dashboard.pagination.pageInfo1=Page -audit.dashboard.pagination.pageInfo2=of -audit.dashboard.pagination.totalRecords=Total records: +audit.dashboard.pagination.show=表示 +audit.dashboard.pagination.entries=エントリ +audit.dashboard.pagination.pageInfo1=ページ +audit.dashboard.pagination.pageInfo2=の +audit.dashboard.pagination.totalRecords=総記録: # Modal -audit.dashboard.modal.eventDetails=Event Details +audit.dashboard.modal.eventDetails=イベント詳細 audit.dashboard.modal.id=ID -audit.dashboard.modal.user=User -audit.dashboard.modal.type=Type -audit.dashboard.modal.time=Time -audit.dashboard.modal.data=Data +audit.dashboard.modal.user=ユーザー +audit.dashboard.modal.type=タイプ +audit.dashboard.modal.time=時間 +audit.dashboard.modal.data=日時 # Export Tab -audit.dashboard.export.title=Export Audit Data -audit.dashboard.export.format=Export Format -audit.dashboard.export.csv=CSV (Comma Separated Values) -audit.dashboard.export.json=JSON (JavaScript Object Notation) -audit.dashboard.export.button=Export Data -audit.dashboard.export.infoTitle=Export Information -audit.dashboard.export.infoDesc1=The export will include all audit events matching the selected filters. For large datasets, the export may take a few moments to generate. -audit.dashboard.export.infoDesc2=Exported data will include: -audit.dashboard.export.infoItem1=Event ID -audit.dashboard.export.infoItem2=User -audit.dashboard.export.infoItem3=Event Type -audit.dashboard.export.infoItem4=Timestamp -audit.dashboard.export.infoItem5=Event Data +audit.dashboard.export.title=監査データのエクスポート +audit.dashboard.export.format=エクスポート形式 +audit.dashboard.export.csv=CSV(コンマ区切り) +audit.dashboard.export.json=JSON(JavaScriptオブジェクト表記) +audit.dashboard.export.button=エクスポートデータ +audit.dashboard.export.infoTitle=エクスポート情報 +audit.dashboard.export.infoDesc1=エクスポートには選択したフィルターに一致するすべての監査イベントが含まれます。大規模なデータセットの場合エクスポートは生成に時間がかかる場合があります。 +audit.dashboard.export.infoDesc2=エクスポートされたデータには以下含まれます: +audit.dashboard.export.infoItem1=イベントID +audit.dashboard.export.infoItem2=ユーザー +audit.dashboard.export.infoItem3=イベントタイプ +audit.dashboard.export.infoItem4=タイムスタンプ +audit.dashboard.export.infoItem5=イベントデータ # JavaScript i18n keys -audit.dashboard.js.noEventsFound=No audit events found matching the current filters -audit.dashboard.js.errorLoading=Error loading data: -audit.dashboard.js.errorRendering=Error rendering table: -audit.dashboard.js.loadingPage=Loading page +audit.dashboard.js.noEventsFound=現在のフィルタと一致する監査イベントは見つかりませんでした +audit.dashboard.js.errorLoading=データの読み込みエラー: +audit.dashboard.js.errorRendering=エラーレンダリングテーブル: +audit.dashboard.js.loadingPage=ページを読み込んでいます #################### # Cookie banner # @@ -1741,54 +1812,54 @@ cookieBanner.preferencesModal.analytics.title=分析 cookieBanner.preferencesModal.analytics.description=これらのCookieはツールがどのように使用されているかを把握するのに役立ちます。これによりコミュニティが最も重視する機能の開発に集中することができます。ご安心ください。Stirling PDFはお客様が操作するドキュメントの内容を追跡することは決してありません。 #fakeScan -fakeScan.title=Fake Scan -fakeScan.header=Fake Scan -fakeScan.description=Create a PDF that looks like it was scanned -fakeScan.selectPDF=Select PDF: -fakeScan.quality=Scan Quality -fakeScan.quality.low=Low -fakeScan.quality.medium=Medium -fakeScan.quality.high=High -fakeScan.rotation=Rotation Angle -fakeScan.rotation.none=None -fakeScan.rotation.slight=Slight -fakeScan.rotation.moderate=Moderate -fakeScan.rotation.severe=Severe -fakeScan.submit=Create Fake Scan +fakeScan.title=フェイクスキャン +fakeScan.header=フェイクスキャン +fakeScan.description=スキャンされたように見えるPDFを作成します +fakeScan.selectPDF=PDFを選択: +fakeScan.quality=スキャン品質 +fakeScan.quality.low=低 +fakeScan.quality.medium=中 +fakeScan.quality.high=高 +fakeScan.rotation=回転角度 +fakeScan.rotation.none=なし +fakeScan.rotation.slight=微少 +fakeScan.rotation.moderate=適度 +fakeScan.rotation.severe=多大 +fakeScan.submit=フェイクスキャンの生成 #home.fakeScan -home.fakeScan.title=Fake Scan -home.fakeScan.desc=Create a PDF that looks like it was scanned +home.fakeScan.title=フェイクスキャン +home.fakeScan.desc=スキャンされたように見えるPDFを作成します fakeScan.tags=scan,simulate,realistic,convert # FakeScan advanced settings (frontend) -fakeScan.advancedSettings=Enable Advanced Scan Settings -fakeScan.colorspace=Colorspace -fakeScan.colorspace.grayscale=Grayscale -fakeScan.colorspace.color=Color -fakeScan.border=Border (px) -fakeScan.rotate=Base Rotation (degrees) -fakeScan.rotateVariance=Rotation Variance (degrees) -fakeScan.brightness=Brightness -fakeScan.contrast=Contrast -fakeScan.blur=Blur -fakeScan.noise=Noise -fakeScan.yellowish=Yellowish (simulate old paper) -fakeScan.resolution=Resolution (DPI) +fakeScan.advancedSettings=高度なスキャン設定を有効にする +fakeScan.colorspace=色空間 +fakeScan.colorspace.grayscale=グレースケール +fakeScan.colorspace.color=カラー +fakeScan.border=縁 (px) +fakeScan.rotate=ベースの回転(度) +fakeScan.rotateVariance=回転分散(度) +fakeScan.brightness=輝度 +fakeScan.contrast=コントラスト +fakeScan.blur=ぼかし +fakeScan.noise=ノイズ +fakeScan.yellowish=黄色がかった(古い紙をシミュレート) +fakeScan.resolution=解像度 (DPI) # Table of Contents Feature -home.editTableOfContents.title=Edit Table of Contents -home.editTableOfContents.desc=Add or edit bookmarks and table of contents in PDF documents +home.editTableOfContents.title=目次の編集 +home.editTableOfContents.desc=PDFドキュメントにしおりと目次を追加または編集します editTableOfContents.tags=bookmarks,toc,navigation,index,table of contents,chapters,sections,outline -editTableOfContents.title=Edit Table of Contents -editTableOfContents.header=Add or Edit PDF Table of Contents -editTableOfContents.replaceExisting=Replace existing bookmarks (uncheck to append to existing) -editTableOfContents.editorTitle=Bookmark Editor -editTableOfContents.editorDesc=Add and arrange bookmarks below. Click + to add child bookmarks. -editTableOfContents.addBookmark=Add New Bookmark -editTableOfContents.desc.1=This tool allows you to add or edit the table of contents (bookmarks) in a PDF document. -editTableOfContents.desc.2=You can create a hierarchical structure by adding child bookmarks to parent bookmarks. -editTableOfContents.desc.3=Each bookmark requires a title and target page number. -editTableOfContents.submit=Apply Table of Contents +editTableOfContents.title=目次を編集 +editTableOfContents.header=PDFに目次を追加または編集 +editTableOfContents.replaceExisting=既存のしおりを置き換える(既存のものに追加するにはチェックを外します) +editTableOfContents.editorTitle=しおりエディター +editTableOfContents.editorDesc=以下にしおりを追加して配置します。+をクリックして、子のしおりを追加します。 +editTableOfContents.addBookmark=新しいしおりを追加 +editTableOfContents.desc.1=このツールを使用すると、PDFドキュメントに目次(しおり)を追加または編集できます。 +editTableOfContents.desc.2=親しおりに子しおりを追加することで階層構造を作成できます。 +editTableOfContents.desc.3=各しおりにはタイトルと対象のページ番号が必要です。 +editTableOfContents.submit=目次を適用 diff --git a/stirling-pdf/src/main/resources/messages_ko_KR.properties b/app/core/src/main/resources/messages_ko_KR.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_ko_KR.properties rename to app/core/src/main/resources/messages_ko_KR.properties index fded2a16a..224e84ce0 100644 --- a/stirling-pdf/src/main/resources/messages_ko_KR.properties +++ b/app/core/src/main/resources/messages_ko_KR.properties @@ -163,13 +163,74 @@ alphabet=알파벳 downloadPdf=PDF 다운로드 text=텍스트 font=글꼴 -selectFillter=-- 선택 -- +selectFilter=-- 선택 -- pageNum=페이지 번호 sizes.small=작게 sizes.medium=중간 sizes.large=크게 sizes.x-large=매우 크게 error.pdfPassword=PDF 문서가 비밀번호로 보호되어 있으며, 비밀번호가 제공되지 않았거나 올바르지 않습니다 +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=삭제 username=사용자 이름 password=비밀번호 @@ -181,7 +242,6 @@ red=빨강 green=초록 blue=파랑 custom=사용자 지정... -WorkInProgess=작업 진행 중, 작동하지 않거나 버그가 있을 수 있습니다. 문제가 있으면 신고해 주세요! poweredBy=제공 yes=예 no=아니오 @@ -525,6 +585,10 @@ home.addImage.title=이미지 추가 home.addImage.desc=PDF의 지정된 위치에 이미지 추가 addImage.tags=이미지,jpg,사진 +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=워터마크 추가 home.watermark.desc=PDF 문서에 사용자 지정 워터마크를 추가합니다. watermark.tags=텍스트,반복,레이블,소유,저작권,상표,이미지,jpg,사진 @@ -1205,6 +1269,12 @@ addImage.everyPage=모든 페이지? addImage.upload=이미지 추가 addImage.submit=이미지 추가 +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=병합 @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=PDF 파일을 드래그 앤 드롭 fileChooser.dragAndDropImage=이미지 파일을 드래그 앤 드롭 fileChooser.hoveredDragAndDrop=여기에 파일을 드래그 앤 드롭하세요 fileChooser.extractPDF=추출 중... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=릴리스 diff --git a/stirling-pdf/src/main/resources/messages_ml_IN.properties b/app/core/src/main/resources/messages_ml_IN.properties similarity index 97% rename from stirling-pdf/src/main/resources/messages_ml_IN.properties rename to app/core/src/main/resources/messages_ml_IN.properties index af974ce76..418cfe100 100644 --- a/stirling-pdf/src/main/resources/messages_ml_IN.properties +++ b/app/core/src/main/resources/messages_ml_IN.properties @@ -163,13 +163,74 @@ alphabet=അക്ഷരമാല downloadPdf=PDF ഡൗൺലോഡ് ചെയ്യുക text=ടെക്സ്റ്റ് font=അക്ഷരം -selectFillter=-- തിരഞ്ഞെടുക്കുക -- +selectFilter=-- തിരഞ്ഞെടുക്കുക -- pageNum=പേജ് നമ്പർ sizes.small=ചെറുത് sizes.medium=ഇടത്തരം sizes.large=വലുത് sizes.x-large=കൂടുതൽ വലുത് error.pdfPassword=PDF ഡോക്യുമെന്റ് പാസ്വേഡ് ഉപയോഗിച്ച് സംരക്ഷിച്ചിരിക്കുന്നു, പാസ്വേഡ് നൽകിയിട്ടില്ല അല്ലെങ്കിൽ തെറ്റായിരുന്നു +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=മായ്ക്കുക username=ഉപയോക്തൃനാമം password=പാസ്വേഡ് @@ -181,7 +242,6 @@ red=ചുവപ്പ് green=പച്ച blue=നീല custom=ഇഷ്ടാനുസൃതം... -WorkInProgess=നിർമ്മാണത്തിലിരിക്കുന്നു, ശരിയായി പ്രവർത്തിച്ചേക്കില്ല അല്ലെങ്കിൽ ബഗ്ഗുകൾ ഉണ്ടാകാം, ദയവായി പ്രശ്നങ്ങൾ അറിയിക്കുക! poweredBy=സഹായത്തോടെ yes=അതെ no=ഇല്ല @@ -525,6 +585,10 @@ home.addImage.title=ചിത്രം ചേർക്കുക home.addImage.desc=PDF-ൽ ഒരു നിശ്ചിത സ്ഥാനത്ത് ഒരു ചിത്രം ചേർക്കുന്നു addImage.tags=img,jpg,ചിത്രം,ഫോട്ടോ +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=വാട്ടർമാർക്ക് ചേർക്കുക home.watermark.desc=നിങ്ങളുടെ PDF പ്രമാണത്തിലേക്ക് ഒരു ഇഷ്ടാനുസൃത വാട്ടർമാർക്ക് ചേർക്കുക. watermark.tags=ടെക്സ്റ്റ്,ആവർത്തിക്കുന്ന,ലേബൽ,സ്വന്തം,പകർപ്പവകാശം,വ്യാപാരമുദ്ര,img,jpg,ചിത്രം,ഫോട്ടോ @@ -1205,6 +1269,12 @@ addImage.everyPage=എല്ലാ പേജിലും? addImage.upload=ചിത്രം ചേർക്കുക addImage.submit=ചിത്രം ചേർക്കുക +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=ലയിപ്പിക്കുക @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=PDF ഫയൽ വലിച്ചിടുക fileChooser.dragAndDropImage=ചിത്ര ഫയൽ വലിച്ചിടുക fileChooser.hoveredDragAndDrop=ഫയൽ(കൾ) ഇവിടെ വലിച്ചിടുക fileChooser.extractPDF=വേർതിരിച്ചെടുക്കുന്നു... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=റിലീസുകൾ diff --git a/stirling-pdf/src/main/resources/messages_nl_NL.properties b/app/core/src/main/resources/messages_nl_NL.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_nl_NL.properties rename to app/core/src/main/resources/messages_nl_NL.properties index b465d82fb..eb6f132af 100644 --- a/stirling-pdf/src/main/resources/messages_nl_NL.properties +++ b/app/core/src/main/resources/messages_nl_NL.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=PDF downloaden text=Tekst font=Lettertype -selectFillter=-- Selecteer -- +selectFilter=-- Selecteer -- pageNum=Paginanummer sizes.small=Klein sizes.medium=Gemiddeld sizes.large=Groot sizes.x-large=Extra groot error.pdfPassword=Het PDF document is beveiligd met een wachtwoord en het wachtwoord is niet ingevoerd of is onjuist +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Verwijderen username=Gebruikersnaam password=Wachtwoord @@ -181,7 +242,6 @@ red=Rood green=Groen blue=Blauw custom=Aangepast... -WorkInProgess=Werk in uitvoering. Werkt mogelijk niet of bevat fouten. Meld eventuele problemen! poweredBy=Mogelijk gemaakt door yes=Ja no=Nee @@ -525,6 +585,10 @@ home.addImage.title=Afbeelding toevoegen home.addImage.desc=Voegt een afbeelding toe op een specifieke locatie in de PDF addImage.tags=img,jpg,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Watermerk toevoegen home.watermark.desc=Voeg een aangepast watermerk toe aan je PDF-document. watermark.tags=Tekst,herhalend,label,eigen,copyright,handelsmerk,img,jpg,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Elke pagina? addImage.upload=Afbeelding toevoegen addImage.submit=Afbeelding toevoegen +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Samenvoegen @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_no_NB.properties b/app/core/src/main/resources/messages_no_NB.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_no_NB.properties rename to app/core/src/main/resources/messages_no_NB.properties index 393f5575e..fa99d5ac9 100644 --- a/stirling-pdf/src/main/resources/messages_no_NB.properties +++ b/app/core/src/main/resources/messages_no_NB.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=Last ned PDF text=Tekst font=Skrifttype -selectFillter=-- Velg -- +selectFilter=-- Velg -- pageNum=Sidenummer sizes.small=Liten sizes.medium=Middels sizes.large=Stor sizes.x-large=Ekstra Stor error.pdfPassword=PDF-dokumentet er passordbeskyttet og enten ble passordet ikke oppgitt eller var feil +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Slett username=Brukernavn password=Passord @@ -181,7 +242,6 @@ red=Rød green=Grønn blue=Blå custom=Tilpasset... -WorkInProgess=Arbeid pågår, Kan være feil eller buggy, Vennligst rapporter eventuelle problemer! poweredBy=Drevet av yes=Ja no=Nei @@ -525,6 +585,10 @@ home.addImage.title=Legg til bilde home.addImage.desc=Legger til et bilde på en angitt plassering i PDF-en addImage.tags=bilde,jpg,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Legg til Vannmerke home.watermark.desc=Legg til et tilpasset vannmerke i din PDF-dokument. watermark.tags=tekst,gjentakende,etikett,egen,opphavsrett,varemerke,bilde,jpg,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=På hver side? addImage.upload=Legg til bilde addImage.submit=Legg til bilde +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Slå sammen @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Versjoner diff --git a/stirling-pdf/src/main/resources/messages_pl_PL.properties b/app/core/src/main/resources/messages_pl_PL.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_pl_PL.properties rename to app/core/src/main/resources/messages_pl_PL.properties index 912d49222..c08fda43d 100644 --- a/stirling-pdf/src/main/resources/messages_pl_PL.properties +++ b/app/core/src/main/resources/messages_pl_PL.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=Pobierz PDF text=Tekst font=Czcionka -selectFillter=-- Wybierz -- +selectFilter=-- Wybierz -- pageNum=Numer strony sizes.small=mniejszy sizes.medium=średni sizes.large=duży sizes.x-large=bardzo duży error.pdfPassword=Dokument PDF jest zabezpieczony hasłem, musisz podać prawidłowe hasło. +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=usuń username=nazwa użytkownika password=hasło @@ -181,7 +242,6 @@ red=czerwony green=zielony blue=niebieski custom=Własny... -WorkInProgess=Praca w toku, proszę zgłaszać błędy! poweredBy=Zasilany yes=tak no=nie @@ -525,6 +585,10 @@ home.addImage.title=Dodaj obraz home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF addImage.tags=img,jpg,obraz,zdjęcie +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Dodaj znak wodny home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF. watermark.tags=Tekst,powtarzanie,etykieta,własne,prawa autorskie,znak wodny,img,jpg,obraz,zdjęcie @@ -1205,6 +1269,12 @@ addImage.everyPage=Każda strona? addImage.upload=Dodaj obraz addImage.submit=Dodaj obraz +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Połącz @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Przeciągnij i upuść plik PDF fileChooser.dragAndDropImage=Przeciągnij i upuść plik obrazu fileChooser.hoveredDragAndDrop=Przeciągnij i upuść plik(i) tutaj fileChooser.extractPDF=Trwa wyodrębnianie... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Wydania diff --git a/stirling-pdf/src/main/resources/messages_pt_BR.properties b/app/core/src/main/resources/messages_pt_BR.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_pt_BR.properties rename to app/core/src/main/resources/messages_pt_BR.properties index b38a9a817..ef570453c 100644 --- a/stirling-pdf/src/main/resources/messages_pt_BR.properties +++ b/app/core/src/main/resources/messages_pt_BR.properties @@ -163,13 +163,74 @@ alphabet=Alfabeto downloadPdf=Baixar PDF text=Texto font=Fonte -selectFillter=-- Selecione -- +selectFilter=-- Selecione -- pageNum=Número da Página sizes.small=Pequeno sizes.medium=Médio sizes.large=Grande sizes.x-large=Extra grande error.pdfPassword=O PDF está protegido por senha e a senha não foi fornecida ou está incorreta +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Apagar username=Usuário password=Senha @@ -181,7 +242,6 @@ red=Vermelho green=Verde blue=Azul custom=Personalizado... -WorkInProgess=Trabalho em progresso, talvez não funcione ou apresente erros, Por favor, reporte qualquer problema! poweredBy=Distribuído por yes=Sim no=Não @@ -525,6 +585,10 @@ home.addImage.title=Adicionar Imagem home.addImage.desc=Adicionar imagens em um local definido no PDF. addImage.tags=img,jpg,imagem,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Adicionar Marca d'água home.watermark.desc=Adicionar uma marca d'água personalizada ao seu PDF. watermark.tags=Texto,repetindo,rótulo,próprio,direitos autorais,marca registrada,img,jpg,imagem,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Para cada página? addImage.upload=Carregar imagem addImage.submit=Adicionar imagem +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Mesclar @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Arraste & Solte PDF(s) fileChooser.dragAndDropImage=Arraste & Solte Imagem(ns) fileChooser.hoveredDragAndDrop=Arraste & Solte arquivo(s) aqui fileChooser.extractPDF=Extraindo... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Versões diff --git a/stirling-pdf/src/main/resources/messages_pt_PT.properties b/app/core/src/main/resources/messages_pt_PT.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_pt_PT.properties rename to app/core/src/main/resources/messages_pt_PT.properties index 598e4e6cf..fd6c34b90 100644 --- a/stirling-pdf/src/main/resources/messages_pt_PT.properties +++ b/app/core/src/main/resources/messages_pt_PT.properties @@ -163,13 +163,74 @@ alphabet=Alfabeto downloadPdf=Transferir PDF text=Texto font=Tipo de letra -selectFillter=-- Selecionar -- +selectFilter=-- Selecionar -- pageNum=Número da Página sizes.small=Pequeno sizes.medium=Médio sizes.large=Grande sizes.x-large=Extra Grande error.pdfPassword=O documento PDF está protegido por palavra-passe e ou não foi fornecida ou está incorreta +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Eliminar username=Nome de utilizador password=Palavra-passe @@ -181,7 +242,6 @@ red=Vermelho green=Verde blue=Azul custom=Personalizar... -WorkInProgess=Trabalho em progresso, pode não funcionar ou ter erros, Por favor reporte quaisquer problemas! poweredBy=Desenvolvido por yes=Sim no=Não @@ -525,6 +585,10 @@ home.addImage.title=Adicionar imagem home.addImage.desc=Adiciona uma imagem numa localização definida no PDF addImage.tags=img,jpg,imagem,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Adicionar Marca de Água home.watermark.desc=Adicionar uma marca de água personalizada ao seu documento PDF. watermark.tags=Texto,repetindo,etiqueta,próprio,copyright,marca registada,img,jpg,imagem,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Todas as Páginas? addImage.upload=Adicionar imagem addImage.submit=Adicionar imagem +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Juntar @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Arrastar e Largar ficheiro PDF fileChooser.dragAndDropImage=Arrastar e Largar ficheiro de Imagem fileChooser.hoveredDragAndDrop=Arrastar e Largar ficheiro(s) aqui fileChooser.extractPDF=Extraindo... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Lançamentos diff --git a/stirling-pdf/src/main/resources/messages_ro_RO.properties b/app/core/src/main/resources/messages_ro_RO.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_ro_RO.properties rename to app/core/src/main/resources/messages_ro_RO.properties index 65139a90a..da8f7eaf2 100644 --- a/stirling-pdf/src/main/resources/messages_ro_RO.properties +++ b/app/core/src/main/resources/messages_ro_RO.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=Descarcă PDF text=Text font=Font -selectFillter=-- Selectează -- +selectFilter=-- Selectează -- pageNum=Numărul paginii sizes.small=Mic sizes.medium=Mediu sizes.large=Mare sizes.x-large=Foarte Mare error.pdfPassword=Documentul PDF este protejat cu parolă și fie parola nu a fost furnizată, fie a fost incorectă +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Șterge username=Nume de utilizator password=Parolă @@ -181,7 +242,6 @@ red=Roșu green=Verde blue=Albastru custom=Personalizat... -WorkInProgess=Lucru în curs, S-ar putea să nu funcționeze sau să aibă erori, Vă rugăm să raportați orice probleme! poweredBy=Propulsat de yes=Da no=Nu @@ -525,6 +585,10 @@ home.addImage.title=Adaugă imagine home.addImage.desc=Adaugă o imagine într-o locație specifică pe PDF (în curs de dezvoltare) addImage.tags=img,jpg,poză,fotografie +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Adaugă Filigran home.watermark.desc=Adaugă un filigran personalizat la documentul PDF. watermark.tags=Text,repetitiv,etichetă,propriu,drepturi de autor,marcă comercială,img,jpg,poză,fotografie @@ -1205,6 +1269,12 @@ addImage.everyPage=Pe fiecare pagină? addImage.upload=Adăugare imagine addImage.submit=Adăugare imagine +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Unire @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_ru_RU.properties b/app/core/src/main/resources/messages_ru_RU.properties similarity index 85% rename from stirling-pdf/src/main/resources/messages_ru_RU.properties rename to app/core/src/main/resources/messages_ru_RU.properties index acd741705..66a1bc93d 100644 --- a/stirling-pdf/src/main/resources/messages_ru_RU.properties +++ b/app/core/src/main/resources/messages_ru_RU.properties @@ -142,9 +142,9 @@ multiPdfPrompt=Выберите PDF-файлы (2+) multiPdfDropPrompt=Выберите (или перетащите) все необходимые PDF-файлы imgPrompt=Выберите изображение(я) genericSubmit=Отправить -uploadLimit=Maximum file size: -uploadLimitExceededSingular=is too large. Maximum allowed size is -uploadLimitExceededPlural=are too large. Maximum allowed size is +uploadLimit=Максимальный размер файла: +uploadLimitExceededSingular=слишком большой. Максимально допустимый размер +uploadLimitExceededPlural=слишком большой. Максимально допустимый размер processTimeWarning=Внимание: Данный процесс может занять до минуты в зависимости от размера файла pageOrderPrompt=Пользовательский порядок страниц (Введите список номеров страниц через запятую или функции типа 2n+1): pageSelectionPrompt=Выбор страниц (Введите список номеров страниц через запятую 1,5,6 или функции типа 2n+1): @@ -163,13 +163,74 @@ alphabet=Алфавит downloadPdf=Скачать PDF text=Текст font=Шрифт -selectFillter=-- Выбрать -- +selectFilter=-- Выбрать -- pageNum=Номер страницы sizes.small=Малый sizes.medium=Средний sizes.large=Большой sizes.x-large=Очень большой error.pdfPassword=PDF-документ защищен паролем, и пароль не был предоставлен или был неверным +error.pdfCorrupted=Файл PDF, по-видимому, поврежден. Пожалуйста, попробуйте сначала воспользоваться функцией "Восстановить PDF", чтобы исправить файл, прежде чем приступать к этой операции. +error.pdfCorruptedMultiple=Один или несколько PDF-файлов, по-видимому, повреждены. Пожалуйста, попробуйте сначала использовать функцию "Восстановить PDF" для каждого файла, прежде чем пытаться объединить их. +error.pdfCorruptedDuring=Ошибка {0}: Файл PDF, по-видимому, поврежден. Пожалуйста, попробуйте сначала воспользоваться функцией "Восстановить PDF", чтобы исправить файл, прежде чем приступать к этой операции. + +# Frontend corruption error messages +error.pdfInvalid=Файл PDF "{0}", по-видимому, поврежден или имеет неправильную структуру. Пожалуйста, попробуйте использовать функцию "Восстановить PDF", чтобы исправить файл, прежде чем продолжить. +error.tryRepair=Попробуйте использовать функцию восстановления PDF для исправления поврежденных файлов. + +# Additional error messages +error.pdfEncryption=Похоже, что в PDF-файле повреждены данные для шифрования. Это может произойти, если PDF-файл был создан с использованием несовместимых методов шифрования. Пожалуйста, сначала попробуйте воспользоваться функцией "Восстановить PDF" или обратитесь к создателю документа за новой копией. +error.fileProcessing=При обработке файла во время операции {0} произошла ошибка: {1} + +# Generic error message templates +error.toolNotInstalled={0} не установлен +error.toolRequired={0} требуется для {1} +error.conversionFailed={0} не удалось выполнить преобразование +error.commandFailed={0} команда не выполнена +error.algorithmNotAvailable={0} алгоритм недоступен +error.optionsNotSpecified={0} параметры не указаны +error.fileFormatRequired=Файл должен быть в формате {0} +error.invalidFormat=Недопустимый формат {0}: {1} +error.endpointDisabled=Эта конечная точка была отключена администратором +error.urlNotReachable=URL-адрес недоступен, пожалуйста, укажите действительный URL-адрес + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=Значение DPI {0} превышает максимально допустимое значение {1}. Высокие значения DPI могут вызвать проблемы с памятью и сбои в работе. Пожалуйста, используйте меньшее значение DPI. +error.pageTooBigForDpi=Размер PDF-страницы {0} слишком велик для отображения с разрешением {1}. Пожалуйста, попробуйте использовать более низкое значение разрешения (рекомендуется 150 или меньше). +error.pageTooBigExceedsArray=Размер страницы PDF {0} слишком велик для отображения с разрешением {1} DPI. Результирующее изображение превысит максимальный размер массива, поддерживаемый Java. Пожалуйста, попробуйте использовать более низкое значение DPI (рекомендуется 150 или меньше). +error.pageTooBigFor300Dpi=Размер страницы PDF {0} слишком велик для отображения с разрешением 300 точек на дюйм. Результирующее изображение превысит максимальный размер массива, поддерживаемый Java. Пожалуйста, используйте меньшее значение разрешения для преобразования PDF в изображение. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=Ключ API недействителен. +error.userNotFound=Пользователь не найден. +error.passwordRequired=Пароль не должен быть пустым. +error.accountLocked=Ваша учетная запись была заблокирована из-за слишком большого количества неудачных попыток входа в систему. +error.invalidEmail=Указанный адрес электронной почты неверный. +error.emailAttachmentRequired=Для отправки электронного письма требуется вложение. +error.signatureNotFound=Файл подписи не найден. + +# File processing messages +error.fileNotFound=Файл с идентификатором: {0} не найден + +# Database and configuration messages +error.noBackupScripts=Сценарий резервного копирования не найден +error.unsupportedProvider={0} в настоящее время не поддерживается. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Недопустимый аргумент: {0} +error.argumentRequired={0} не должно быть null +error.operationFailed=Операция завершилась неудачей: {0} +error.angleNotMultipleOf90=Угол наклона должен быть кратным 90 +error.pdfBookmarksNotFound=В PDF-документе не найдены закладки/сноски +error.fontLoadingFailed=Ошибка при обработке файла шрифта +error.fontDirectoryReadFailed=Не удалось прочитать каталог шрифтов delete=Удалить username=Имя пользователя password=Пароль @@ -181,7 +242,6 @@ red=Красный green=Зеленый blue=Синий custom=Пользовательский... -WorkInProgess=В разработке, возможны ошибки и сбои, пожалуйста, сообщайте о любых проблемах! poweredBy=Работает на yes=Да no=Нет @@ -200,7 +260,7 @@ disabledCurrentUserMessage=Текущий пользователь не може downgradeCurrentUserLongMessage=Невозможно понизить роль текущего пользователя. Следовательно, текущий пользователь не будет отображаться. userAlreadyExistsOAuthMessage=Пользователь уже существует как пользователь OAuth2. userAlreadyExistsWebMessage=Пользователь уже существует как веб-пользователь. -invalidRoleMessage=Invalid role. +invalidRoleMessage=Недопустимая роль. error=Ошибка oops=Упс! help=Помощь @@ -213,27 +273,27 @@ color=Цвет sponsor=Спонсор info=Информация pro=Pro -proFeatures=Pro Features +proFeatures=Pro-функции page=Страница pages=Страницы loading=Загрузка... addToDoc=Добавить в документ reset=Сбросить apply=Применить -noFileSelected=No file selected. Please upload one. -view=View -cancel=Cancel +noFileSelected=Файл не выбран. Пожалуйста, загрузите его. +view=Смотреть +cancel=Закрыть -back.toSettings=Back to Settings -back.toHome=Back to Home -back.toAdmin=Back to Admin +back.toSettings=Вернуться к настройкам +back.toHome=Вернуться на главную +back.toAdmin=Вернуться в админку legal.privacy=Политика конфиденциальности legal.terms=Условия использования legal.accessibility=Доступность legal.cookie=Политика использования файлов cookie legal.impressum=Выходные данные -legal.showCookieBanner=Cookie Preferences +legal.showCookieBanner=Настройки файлов cookie ############### # Pipeline # @@ -267,7 +327,7 @@ enterpriseEdition.button=Перейти на Pro enterpriseEdition.warning=Эта функция доступна только для пользователей Pro. enterpriseEdition.yamlAdvert=Stirling PDF Pro поддерживает файлы конфигурации YAML и другие функции SSO. enterpriseEdition.ssoAdvert=Ищете больше возможностей управления пользователями? Посмотрите Stirling PDF Pro -enterpriseEdition.proTeamFeatureDisabled=Team management features require a Pro licence or higher +enterpriseEdition.proTeamFeatureDisabled=Для функций управления группой требуется лицензия Pro или выше ################# @@ -348,8 +408,8 @@ account.property=Свойство account.webBrowserSettings=Настройки веб-браузера account.syncToBrowser=Синхронизировать Аккаунт -> Браузер account.syncToAccount=Синхронизировать Аккаунт <- Браузер -account.adminTitle=Administrator Tools -account.adminNotif=You have admin privileges. Access system settings and user management. +account.adminTitle=Инструменты администратора +account.adminNotif=У вас есть права администратора. Вам доступны системные настройки и управление пользователями. adminUserSettings.title=Настройки управления пользователями @@ -381,18 +441,18 @@ adminUserSettings.totalUsers=Всего пользователей: adminUserSettings.lastRequest=Последний запрос adminUserSettings.usage=View Usage adminUserSettings.teams=View/Edit Teams -adminUserSettings.team=Team -adminUserSettings.manageTeams=Manage Teams -adminUserSettings.createTeam=Create Team -adminUserSettings.viewTeam=View Team -adminUserSettings.deleteTeam=Delete Team -adminUserSettings.teamName=Team Name -adminUserSettings.teamExists=Team already exists -adminUserSettings.teamCreated=Team created successfully -adminUserSettings.teamChanged=User's team was updated -adminUserSettings.teamHidden=Hidden -adminUserSettings.totalMembers=Total Members -adminUserSettings.confirmDeleteTeam=Are you sure you want to delete this team? +adminUserSettings.team=Группа +adminUserSettings.manageTeams=Управление группами +adminUserSettings.createTeam=Создать группу +adminUserSettings.viewTeam=Смотреть группу +adminUserSettings.deleteTeam=Удалить группу +adminUserSettings.teamName=Имя группы +adminUserSettings.teamExists=Группа уже существует +adminUserSettings.teamCreated=Группа успешно создана +adminUserSettings.teamChanged=Группа пользователей была обновлена +adminUserSettings.teamHidden=Скрытая +adminUserSettings.totalMembers=Общее количество участников +adminUserSettings.confirmDeleteTeam=Вы уверены, что хотите удалить эту группу? teamCreated=Team created successfully teamExists=A team with that name already exists @@ -478,18 +538,18 @@ home.desc=Ваше локальное решение для всех потре home.searchBar=Поиск функций... -home.viewPdf.title=View/Edit PDF +home.viewPdf.title=Смотреть/Редактировать PDF home.viewPdf.desc=Просмотр, аннотирование, добавление текста или изображений viewPdf.tags=просмотр,чтение,аннотации,текст,изображение -home.setFavorites=Set Favourites -home.hideFavorites=Hide Favourites -home.showFavorites=Show Favourites -home.legacyHomepage=Old homepage -home.newHomePage=Try our new homepage! -home.alphabetical=Alphabetical -home.globalPopularity=Global Popularity -home.sortBy=Sort by: +home.setFavorites=Добавить в избранное +home.hideFavorites=Скрыть из избранного +home.showFavorites=Показать избранное +home.legacyHomepage=Старый вид главной страницы +home.newHomePage=Попробуйте нашу новую главную страницу! +home.alphabetical=Алфавиту +home.globalPopularity=Популярности +home.sortBy=Сортировать по: home.multiTool.title=Мультиинструмент PDF home.multiTool.desc=Объединение, поворот, переупорядочивание и удаление страниц @@ -525,6 +585,10 @@ home.addImage.title=Добавить изображение home.addImage.desc=Добавляет изображение в указанное место PDF addImage.tags=изображение,jpg,картинка,фото +home.attachments.title=Добавлять вложения +home.attachments.desc=Добавление или удаление встроенных файлов (вложений) в PDF-файл или из него +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Добавить водяной знак home.watermark.desc=Добавьте собственный водяной знак в ваш PDF-документ. watermark.tags=текст,повторяющийся,метка,собственный,авторское право,торговая марка,изображение,jpg,картинка,фото @@ -550,8 +614,8 @@ home.compressPdfs.title=Сжать home.compressPdfs.desc=Сжимайте PDF-файлы для уменьшения их размера. compressPdfs.tags=сжатие,маленький,крошечный -home.unlockPDFForms.title=Unlock PDF Forms -home.unlockPDFForms.desc=Remove read-only property of form fields in a PDF document. +home.unlockPDFForms.title=Разблокировать PDF-формы +home.unlockPDFForms.desc=Удалите свойство "только для чтения" для полей формы в PDF-документа. unlockPDFForms.tags=remove,delete,form,field,readonly home.changeMetadata.title=Изменить метаданные @@ -676,20 +740,20 @@ home.HTMLToPDF.desc=Преобразует любой HTML-файл или zip HTMLToPDF.tags=разметка,веб-контент,преобразование,конвертация #eml-to-pdf -home.EMLToPDF.title=Email to PDF -home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images +home.EMLToPDF.title=Email в PDF +home.EMLToPDF.desc=Преобразует файлы электронной почты (EML) в формат PDF, включая заголовки, основную часть и встроенные изображения EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail -EMLToPDF.title=Email To PDF -EMLToPDF.header=Email To PDF -EMLToPDF.submit=Convert -EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF -EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues -EMLToPDF.includeAttachments=Include attachments in PDF -EMLToPDF.maxAttachmentSize=Maximum attachment size (MB) -EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images -EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both -EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code. +EMLToPDF.title=Email в PDF +EMLToPDF.header=Email в PDF +EMLToPDF.submit=Преобразовать +EMLToPDF.downloadHtml=Загрузить промежуточный файл HTML вместо PDF +EMLToPDF.downloadHtmlHelp=Это позволит вам просмотреть HTML-версию перед преобразованием в PDF и поможет устранить проблемы с форматированием +EMLToPDF.includeAttachments=Включать вложения в формате PDF +EMLToPDF.maxAttachmentSize=Максимальный размер вложения (MB) +EMLToPDF.help=Преобразует файлы электронной почты (EML) в формат PDF, включая заголовки, основную часть и встроенные изображения +EMLToPDF.troubleshootingTip1=Электронная почта в формате HTML является более надежным процессом, поэтому при пакетной обработке рекомендуется сохранять оба +EMLToPDF.troubleshootingTip2=При небольшом количестве электронных писем, если формат PDF искажен, вы можете загрузить HTML и переопределить часть проблемного HTML/CSS-кода. EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs home.MarkdownToPDF.title=Markdown в PDF @@ -697,7 +761,7 @@ home.MarkdownToPDF.desc=Преобразует любой файл Markdown в P MarkdownToPDF.tags=разметка,веб-контент,преобразование,конвертация home.PDFToMarkdown.title=PDF to Markdown -home.PDFToMarkdown.desc=Converts any PDF to Markdown +home.PDFToMarkdown.desc=Преобразует любой PDF-файл в формат Markdown PDFToMarkdown.tags=markup,web-content,transformation,convert,md home.getPdfInfo.title=Получить ВСЮ информацию о PDF @@ -811,7 +875,7 @@ login.userIsDisabled=Пользователь деактивирован, вхо login.alreadyLoggedIn=Вы уже вошли в login.alreadyLoggedIn2=устройств(а). Пожалуйста, выйдите из этих устройств и попробуйте снова. login.toManySessions=У вас слишком много активных сессий -login.logoutMessage=You have been logged out. +login.logoutMessage=Вы вышли из системы. #auto-redact autoRedact.title=Автоматическое редактирование @@ -850,7 +914,7 @@ redact.showAttatchments=Показать вложения redact.showLayers=Показать слои (двойной щелчок для сброса всех слоев к состоянию по умолчанию) redact.colourPicker=Выбор цвета redact.findCurrentOutlineItem=Найти текущий элемент структуры -redact.applyChanges=Apply Changes +redact.applyChanges=Применить изменения #showJS showJS.title=Показать Javascript @@ -878,15 +942,15 @@ getPdfInfo.header=Получить информацию о PDF getPdfInfo.submit=Получить информацию getPdfInfo.downloadJson=Скачать JSON getPdfInfo.summary=PDF Summary -getPdfInfo.summary.encrypted=This PDF is encrypted so may face issues with some applications -getPdfInfo.summary.permissions=This PDF has {0} restricted permissions which may limit what you can do with it -getPdfInfo.summary.compliance=This PDF complies with the {0} standard -getPdfInfo.summary.basicInfo=Basic Information -getPdfInfo.summary.docInfo=Document Information -getPdfInfo.summary.encrypted.alert=Encrypted PDF - This document is password protected -getPdfInfo.summary.not.encrypted.alert=Unencrypted PDF - No password protection -getPdfInfo.summary.permissions.alert=Restricted Permissions - {0} actions are not allowed -getPdfInfo.summary.all.permissions.alert=All Permissions Allowed +getPdfInfo.summary.encrypted=Этот PDF-файл зашифрован, поэтому с некоторыми приложениями могут возникнуть проблемы +getPdfInfo.summary.permissions=Этот PDF-файл имеет {0} ограниченные права доступа, которые могут ограничить то, что вы можете с ним делать +getPdfInfo.summary.compliance=Этот PDF-файл соответствует стандарту {0} +getPdfInfo.summary.basicInfo=Основная информация +getPdfInfo.summary.docInfo=Информация о документе +getPdfInfo.summary.encrypted.alert=Зашифрованный PDF-файл - этот документ защищен паролем +getPdfInfo.summary.not.encrypted.alert=Незашифрованный PDF-файл - без защиты паролем +getPdfInfo.summary.permissions.alert=Права доступа ограничены - {0} действия запрещены +getPdfInfo.summary.all.permissions.alert=Полные права доступа getPdfInfo.summary.compliance.alert={0} Compliant getPdfInfo.summary.no.compliance.alert=No Compliance Standards getPdfInfo.summary.security.section=Security Status @@ -910,9 +974,9 @@ MarkdownToPDF.credit=Использует WeasyPrint #pdf-to-markdown -PDFToMarkdown.title=PDF To Markdown -PDFToMarkdown.header=PDF To Markdown -PDFToMarkdown.submit=Convert +PDFToMarkdown.title=PDF в Markdown +PDFToMarkdown.header=PDF в Markdown +PDFToMarkdown.submit=Преобразовать #url-to-pdf @@ -966,10 +1030,10 @@ sanitizePDF.title=Очистить PDF sanitizePDF.header=Очистить PDF-файл sanitizePDF.selectText.1=Удалить JavaScript-действия sanitizePDF.selectText.2=Удалить встроенные файлы -sanitizePDF.selectText.3=Remove XMP metadata +sanitizePDF.selectText.3=Удалить XMP метаданные sanitizePDF.selectText.4=Удалить ссылки sanitizePDF.selectText.5=Удалить шрифты -sanitizePDF.selectText.6=Remove Document Info Metadata +sanitizePDF.selectText.6=Удалить метаданные с информацией о документе sanitizePDF.submit=Очистить PDF @@ -1118,8 +1182,8 @@ sign.last=Последняя страница sign.next=Следующая страница sign.previous=Предыдущая страница sign.maintainRatio=Переключить сохранение пропорций -sign.undo=Undo -sign.redo=Redo +sign.undo=Отменить +sign.redo=Повторить #repair repair.title=Восстановление @@ -1190,8 +1254,8 @@ compress.title=Сжать compress.header=Сжать PDF compress.credit=Этот сервис использует qpdf для сжатия/оптимизации PDF. compress.grayscale.label=Применить шкалу серого для сжатия -compress.selectText.1=Compression Settings -compress.selectText.1.1=1-3 PDF compression,
4-6 lite image compression,
7-9 intense image compression Will dramatically reduce image quality +compress.selectText.1=Параметры сжатия +compress.selectText.1.1=1-3 сжатие PDF,
4-6 лёгкое сжатие изображений,
7-9 интенсивное сжатие изображений (значительно снижает качество изображений) compress.selectText.2=Уровень оптимизации: compress.selectText.4=Автоматический режим - автоматически настраивает качество для получения точного размера PDF compress.selectText.5=Ожидаемый размер PDF (например, 25MB, 10.8MB, 25KB) @@ -1205,6 +1269,12 @@ addImage.everyPage=Каждая страница? addImage.upload=Добавить изображение addImage.submit=Добавить изображение +#attachments +attachments.title=Добавлять вложения +attachments.header=Добавлять вложения +attachments.description=Позволяет добавлять вложения в PDF-файл +attachments.descriptionPlaceholder=Введите описание для вложений... +attachments.addButton=Добавлять вложения #merge merge.title=Объединить @@ -1212,7 +1282,7 @@ merge.header=Объединение нескольких PDF (2+) merge.sortByName=Сортировать по имени merge.sortByDate=Сортировать по дате merge.removeCertSign=Удалить цифровую подпись в объединенном файле? -merge.generateToc=Generate table of contents in the merged file? +merge.generateToc=Сгенерировать оглавление в объединенном файле? merge.submit=Объединить @@ -1231,7 +1301,7 @@ pdfOrganiser.mode.7=Удалить первую pdfOrganiser.mode.8=Удалить последнюю pdfOrganiser.mode.9=Удалить первую и последнюю pdfOrganiser.mode.10=Объединение четных-нечетных -pdfOrganiser.mode.11=Duplicate all pages +pdfOrganiser.mode.11=Дублировать все страницы pdfOrganiser.placeholder=(например, 1,3,2 или 4-8,2,10-12 или 2n-1) @@ -1274,7 +1344,7 @@ decrypt.success=Файл успешно расшифрован. multiTool-advert.message=Эта функция также доступна на нашей странице мультиинструмента. Попробуйте её для улучшенного постраничного интерфейса и дополнительных возможностей! #view pdf -viewPdf.title=View/Edit PDF +viewPdf.title=Смотреть/Редактировать PDF viewPdf.header=Просмотр PDF #pageRemover @@ -1422,9 +1492,9 @@ changeMetadata.selectText.5=Добавить пользовательскую з changeMetadata.submit=Изменить #unlockPDFForms -unlockPDFForms.title=Remove Read-Only from Form Fields -unlockPDFForms.header=Unlock PDF Forms -unlockPDFForms.submit=Remove +unlockPDFForms.title=Удалить поля формы, доступные только для чтения +unlockPDFForms.header=Разблокировать PDF-формы +unlockPDFForms.submit=Удалить #pdfToPDFA pdfToPDFA.title=PDF в PDF/A @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Перетащите PDF-файл fileChooser.dragAndDropImage=Перетащите файл изображения fileChooser.hoveredDragAndDrop=Перетащите файл(ы) сюда fileChooser.extractPDF=Извлечение... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Релизы @@ -1653,12 +1724,12 @@ audit.dashboard.tab.dashboard=Dashboard audit.dashboard.tab.events=Audit Events audit.dashboard.tab.export=Export # Dashboard Charts -audit.dashboard.eventsByType=Events by Type -audit.dashboard.eventsByUser=Events by User -audit.dashboard.eventsOverTime=Events Over Time -audit.dashboard.period.7days=7 Days -audit.dashboard.period.30days=30 Days -audit.dashboard.period.90days=90 Days +audit.dashboard.eventsByType=События по типу +audit.dashboard.eventsByUser=События по пользователю +audit.dashboard.eventsOverTime=События за всё время +audit.dashboard.period.7days=7 дней +audit.dashboard.period.30days=30 дней +audit.dashboard.period.90days=90 дней # Events Tab audit.dashboard.auditEvents=Audit Events @@ -1741,49 +1812,49 @@ cookieBanner.preferencesModal.analytics.title=Analytics cookieBanner.preferencesModal.analytics.description=These cookies help us understand how our tools are being used, so we can focus on building the features our community values most. Rest assured—Stirling PDF cannot and will never track the content of the documents you work with. #fakeScan -fakeScan.title=Fake Scan -fakeScan.header=Fake Scan -fakeScan.description=Create a PDF that looks like it was scanned -fakeScan.selectPDF=Select PDF: -fakeScan.quality=Scan Quality -fakeScan.quality.low=Low -fakeScan.quality.medium=Medium -fakeScan.quality.high=High -fakeScan.rotation=Rotation Angle -fakeScan.rotation.none=None -fakeScan.rotation.slight=Slight -fakeScan.rotation.moderate=Moderate -fakeScan.rotation.severe=Severe -fakeScan.submit=Create Fake Scan +fakeScan.title=Поддельное сканирование +fakeScan.header=Поддельное сканирование +fakeScan.description=Создайте PDF-файл, который выглядит так, как будто он был отсканирован +fakeScan.selectPDF=Выбрать PDF: +fakeScan.quality=Качество сканирования +fakeScan.quality.low=Низкое +fakeScan.quality.medium=Среднее +fakeScan.quality.high=Хорошее +fakeScan.rotation=Угол поворота +fakeScan.rotation.none=Нет +fakeScan.rotation.slight=Незначительный +fakeScan.rotation.moderate=Умеренный +fakeScan.rotation.severe=Сильный +fakeScan.submit=Создать поддельное сканирование #home.fakeScan -home.fakeScan.title=Fake Scan -home.fakeScan.desc=Create a PDF that looks like it was scanned +home.fakeScan.title=Поддельное сканирование +home.fakeScan.desc=Создайте PDF-файл, который выглядит так, как будто он был отсканирован fakeScan.tags=scan,simulate,realistic,convert # FakeScan advanced settings (frontend) -fakeScan.advancedSettings=Enable Advanced Scan Settings -fakeScan.colorspace=Colorspace -fakeScan.colorspace.grayscale=Grayscale -fakeScan.colorspace.color=Color -fakeScan.border=Border (px) -fakeScan.rotate=Base Rotation (degrees) -fakeScan.rotateVariance=Rotation Variance (degrees) -fakeScan.brightness=Brightness -fakeScan.contrast=Contrast -fakeScan.blur=Blur -fakeScan.noise=Noise -fakeScan.yellowish=Yellowish (simulate old paper) -fakeScan.resolution=Resolution (DPI) +fakeScan.advancedSettings=Включите расширенные параметры сканирования +fakeScan.colorspace=Цветовое пространство +fakeScan.colorspace.grayscale=Оттенки серого +fakeScan.colorspace.color=Цветное +fakeScan.border=Рамка (px) +fakeScan.rotate=Базовый наклон (degrees) +fakeScan.rotateVariance=Скорость вращения (degrees) +fakeScan.brightness=Яркость +fakeScan.contrast=Контраст +fakeScan.blur=Размытие +fakeScan.noise=Шум +fakeScan.yellowish=Желтоватый оттенок (имитация старой бумаги) +fakeScan.resolution=Разрешение (DPI) # Table of Contents Feature -home.editTableOfContents.title=Edit Table of Contents -home.editTableOfContents.desc=Add or edit bookmarks and table of contents in PDF documents +home.editTableOfContents.title=Редактировать оглавление +home.editTableOfContents.desc=Добавление или редактирование закладок и оглавления в PDF-документах editTableOfContents.tags=bookmarks,toc,navigation,index,table of contents,chapters,sections,outline -editTableOfContents.title=Edit Table of Contents -editTableOfContents.header=Add or Edit PDF Table of Contents +editTableOfContents.title=Редактировать оглавление +editTableOfContents.header=Добавление или редактирование закладок и оглавления в PDF-документах editTableOfContents.replaceExisting=Replace existing bookmarks (uncheck to append to existing) editTableOfContents.editorTitle=Bookmark Editor editTableOfContents.editorDesc=Add and arrange bookmarks below. Click + to add child bookmarks. diff --git a/stirling-pdf/src/main/resources/messages_sk_SK.properties b/app/core/src/main/resources/messages_sk_SK.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_sk_SK.properties rename to app/core/src/main/resources/messages_sk_SK.properties index 398c4d06b..0b77464ad 100644 --- a/stirling-pdf/src/main/resources/messages_sk_SK.properties +++ b/app/core/src/main/resources/messages_sk_SK.properties @@ -163,13 +163,74 @@ alphabet=Abeceda downloadPdf=Stiahnuť PDF text=Text font=Font -selectFillter=-- Vyberte -- +selectFilter=-- Vyberte -- pageNum=Číslo stránky sizes.small=Malé sizes.medium=Stredné sizes.large=Veľké sizes.x-large=Veľmi veľké error.pdfPassword=PDF dokument je chránený heslom a buď heslo nebolo zadané, alebo bolo nesprávne +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Vymazať username=Používateľské meno password=Heslo @@ -181,7 +242,6 @@ red=Červená green=Zelená blue=Modrá custom=Vlastné... -WorkInProgess=Práca prebieha, nemusí fungovať alebo môže byť chybová, prosím nahláste akékoľvek problémy! poweredBy=Poskytované yes=Áno no=Nie @@ -525,6 +585,10 @@ home.addImage.title=Pridať obrázok home.addImage.desc=Pridať obrázok na zadané miesto v PDF addImage.tags=img,jpg,obrázok,fotografia +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Pridať vodotlač home.watermark.desc=Pridať vlastnú vodotlač do vášho PDF dokumentu. watermark.tags=Text,opakujúci sa,označenie,vlastné,autorské práva,ochranná známka,img,jpg,obrázok,fotografia @@ -1205,6 +1269,12 @@ addImage.everyPage=Každá stránka? addImage.upload=Pridať obrázok addImage.submit=Pridať obrázok +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Zlúčiť @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_sl_SI.properties b/app/core/src/main/resources/messages_sl_SI.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_sl_SI.properties rename to app/core/src/main/resources/messages_sl_SI.properties index ba9ce39cf..de27dccc4 100644 --- a/stirling-pdf/src/main/resources/messages_sl_SI.properties +++ b/app/core/src/main/resources/messages_sl_SI.properties @@ -163,13 +163,74 @@ alphabet=Abeceda downloadPdf=Prenesi PDF text=Besedilo font=Pisava -selectFillter=-- Izberite -- +selectFilter=-- Izberite -- pageNum=Številka strani sizes.small=Majhen sizes.medium=Srednje sizes.large=Veliko sizes.x-large=X-Velik error.pdfPassword=Dokument PDF je zaščiten z geslom in geslo ni bilo vneseno ali pa je bilo napačno +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Izbriši username=Uporabniško ime password=Geslo @@ -181,7 +242,6 @@ red=rdeča green=zelena blue=modra custom=Po meri... -WorkInProgess=Delo je v teku, morda ne bo delovalo ali bo hroščalo, prosimo, prijavite morebitne težave! poweredBy=Poganja yes=Da no=Ne @@ -525,6 +585,10 @@ home.addImage.title=Dodaj sliko home.addImage.desc=Doda sliko na določeno mesto v PDF-ju addImage.tags=img,jpg,slika,fotografija +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Dodaj vodni žig home.watermark.desc=V dokument PDF dodajte vodni žig po meri. watermark.tags=Besedilo, ponavljajoče se, oznaka, lastno, avtorske pravice, blagovna znamka, img, jpg, slika, fotografija @@ -1205,6 +1269,12 @@ addImage.everyPage=Vsaka stran? addImage.upload=Dodaj sliko addImage.submit=Dodaj sliko +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Združi @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Povleci in spusti datoteko PDF fileChooser.dragAndDropImage=Povleci in spusti slikovno datoteko fileChooser.hoveredDragAndDrop=Povleci in spusti datoteko(e) sem fileChooser.extractPDF=Izvlečenje... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Izdaje diff --git a/app/core/src/main/resources/messages_sr_LATN_RS.properties b/app/core/src/main/resources/messages_sr_LATN_RS.properties new file mode 100644 index 000000000..12f8f9abd --- /dev/null +++ b/app/core/src/main/resources/messages_sr_LATN_RS.properties @@ -0,0 +1,1865 @@ +########### +# Generic # +########### +# the direction that the language is written (ltr = left to right, rtl = right to left) +language.direction=ltr + +# Language names for reuse throughout the application +lang.afr=Afrički +lang.amh=Amharski +lang.ara=Arapski +lang.asm=Asamski +lang.aze=Azerbejdžanski +lang.aze_cyrl=Azerbejdžanski (ćirilica) +lang.bel=Beloruski +lang.ben=Bengalski +lang.bod=Tibetanski +lang.bos=Bosanski +lang.bre=Bretonski +lang.bul=Bugarski +lang.cat=Katalonski +lang.ceb=Sebuano +lang.ces=Češki +lang.chi_sim=Kineski (pojednostavljeni) +lang.chi_sim_vert=Kineski (pojednostavljeni, vertikalno) +lang.chi_tra=Kineski (tradicionalni) +lang.chi_tra_vert=Kineski (tradicionalni, vertikalno) +lang.chr=Čiroki +lang.cos=Korzikanski +lang.cym=Velški +lang.dan=Danski +lang.dan_frak=Danski (Fraktur) +lang.deu=Nemački +lang.deu_frak=Nemački (Fraktur) +lang.div=Divehi +lang.dzo=Dzonka +lang.ell=Grčki +lang.eng=Engleski +lang.enm=Engleski, srednji (1100-1500) +lang.epo=Esperanto +lang.equ=Modul za prepoznavanje matematike/jednačina +lang.est=Estonski +lang.eus=Baskijski +lang.fao=Farski +lang.fas=Persijski +lang.fil=Filipinski +lang.fin=Finski +lang.fra=Francuski +lang.frk=Frankski +lang.frm=Francuski, srednji (oko 1400-1600) +lang.fry=Zapadnofriziski +lang.gla=Škotski galski +lang.gle=Irski +lang.glg=Galicijski +lang.grc=Starogrčki +lang.guj=Gužarati +lang.hat=Haićanski, Haićanski kreolski +lang.heb=Hebrejski +lang.hin=Hindi +lang.hrv=Hrvatski +lang.hun=Mađarski +lang.hye=Jermenski +lang.iku=Inuktitut +lang.ind=Indonežanski +lang.isl=Islandski +lang.ita=Italijanski +lang.ita_old=Italijanski (stari) +lang.jav=Javanski +lang.jpn=Japanski +lang.jpn_vert=Japanski (vertikalno) +lang.kan=Kanada +lang.kat=Gruzijski +lang.kat_old=Gruzijski (stari) +lang.kaz=Kazaški +lang.khm=Kmerski +lang.kir=Kirgiski +lang.kmr=Servernokurdski +lang.kor=Korejski +lang.kor_vert=Korejski(vertikalno) +lang.lao=Laoški +lang.lat=Latinski +lang.lav=Latvijski +lang.lit=Litvanski +lang.ltz=Luksemburški +lang.mal=Malajam +lang.mar=Marathi +lang.mkd=Makedonski +lang.mlt=Malteški +lang.mon=Mongolski +lang.mri=Maorski +lang.msa=Malajski +lang.mya=Birmanski +lang.nep=Nepalski +lang.nld=Holandski; Flamanski +lang.nor=Norveški +lang.oci=Oksitanski (posle 1500) +lang.ori=Orija +lang.osd=Modul za detekciju i orijentaciju pisma +lang.pan=Pandžapski +lang.pol=Poljski +lang.por=Portugalski +lang.pus=Puštu +lang.que=Kečua +lang.ron=Rumunski, Moldavski +lang.rus=Ruski +lang.san=Sanskrit +lang.sin=Singalski +lang.slk=Slovački +lang.slk_frak=Slovački (Fraktur) +lang.slv=Slovenački +lang.snd=Sindhi +lang.spa=Španski +lang.spa_old=Španski (stari) +lang.sqi=Albanski +lang.srp=Srpski +lang.srp_latn=Srpski (latinica) +lang.sun=Sundanski +lang.swa=Svahili +lang.swe=Švedski +lang.syr=Sirijski +lang.tam=Tamilski +lang.tat=Tatarski +lang.tel=Telugu +lang.tgk=Tadžički +lang.tgl=Tagalog +lang.tha=Tajlandski +lang.tir=Tigrinja +lang.ton=Tonga +lang.tur=Turski +lang.uig=Ujgurski +lang.ukr=Ukrajinski +lang.urd=Urdu +lang.uzb=Uzbekski +lang.uzb_cyrl=Uzbekski (ćirilica) +lang.vie=Vijetnamski +lang.yid=Jidiš +lang.yor=Joruba + +addPageNumbers.fontSize=Veličina fonta +addPageNumbers.fontName=Naziv fonta +pdfPrompt=Odaberi PDF(ove) +multiPdfPrompt=Odaberi PDF-ove (2+) +multiPdfDropPrompt=Odaberi (ili prevuci i pusti) sve PDF-ove koji su ti potrebni +imgPrompt=Odaberi sliku (slike) +genericSubmit=Potvrdi +uploadLimit=Maksimalna veličina datoteke: +uploadLimitExceededSingular=je prevelik. Maksimalna dozvoljena veličina je +uploadLimitExceededPlural=su preveliki. Maksimalna dozvoljena veličina je +processTimeWarning=Upozorenje: Ovaj proces može trajati i do minut, u zavisnosti od veličine datoteke +pageOrderPrompt=Prilagođeni redosled stranica (unesi listu brojeva stranica ili funkcija, kao što je 2n+1, razdvojenih zarezima) : +pageSelectionPrompt=Prilagođeni redosled stranica (unesi listu brojeva stranica 1,5,6 ili funkcija, kao što je 2n+1, razdvojenih zarezima) : +goToPage=Idi +true=Tačno +false=Netačno +unknown=Nepoznato +save=Sačuvaj +saveToBrowser=Sačuvaj u pregledaču +close=Zatvori +filesSelected=odabrani fajlovi +noFavourites=Nema dodatih favorita +downloadComplete=Preuzimanje završeno +bored=Da li ti je dosadno dok čekaš? +alphabet=Abeceda +downloadPdf=Preuzmi PDF +text=Tekst +font=Font +selectFilter=-- Izaberi -- +pageNum=Broj strane +sizes.small=Malo +sizes.medium=Srednje +sizes.large=Veliko +sizes.x-large=X-Veliko +error.pdfPassword=PDF dokument je šifrovan i lozinka nije data ili je netačna +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory +delete=Obriši +username=Korisničko ime +password=Lozinka +welcome=Dobrodošli +property=Svojstvo +black=Crno +white=Belo +red=Crveno +green=Zeleno +blue=Plavo +custom=Prilagođeno... +poweredBy=Omogućeno od strane +yes=Da +no=Ne +changedCredsMessage=Podaci za prijavu uspešno promenjeni! +notAuthenticatedMessage=Korisnik nije autentifikovan. +userNotFoundMessage=Korisnik nije pronađen. +incorrectPasswordMessage=Trenutna lozinka je netačna. +usernameExistsMessage=Novi korisnik već postoji +invalidUsernameMessage=Pogrešno korisničko ime, korisničko ime može sadržati samo slova, brojeve i specijalne karaktere @._+- ili mora biti validna email adresa. +invalidPasswordMessage=Lozinka ne sme biti prazna i ne sme imati razmake na početku ili kraju. +confirmPasswordErrorMessage=Nova lozinka i potvrda lozinke se moraju slagati. +deleteCurrentUserMessage=Ne mogu obrisati trenutno prijavljenog korisnika. +deleteUsernameExistsMessage=Korisničko ime ne postoji i ne može biti obrisano. +downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika +disabledCurrentUserMessage=Trenutno korisnik ne može biti onemogućen +downgradeCurrentUserLongMessage=Nije moguće degradirati ulogu trenutnog korisnika. Dakle, trenutni korisnik neće biti prikazan. +userAlreadyExistsOAuthMessage=Korisnik već postoji kao OAuth2 korisnik. +userAlreadyExistsWebMessage=Korisnik već postoji kao web korisnik. +invalidRoleMessage=Nevažeća uloga. +error=Greška +oops=Opa! +help=Pomoć +goHomepage=Idi na početnu stranu +joinDiscord=Pridružite se našem Discord serveru +seeDockerHub=Pogledaj Docker Hub +visitGithub=Poseti Github repozitorijum +donate=Doniraj +color=Boja +sponsor=Sponzor +info=Info +pro=Pro +proFeatures=Napredne funkcije +page=Strana +pages=Strane +loading=Učitavam... +addToDoc=Dodaj u dokument +reset=Resetuj +apply=Primeni +noFileSelected=Datoteka nije izabrana. Otpremi jednu. +view=Pogledaj +cancel=Otkaži + +back.toSettings=Povratak na podešavanja +back.toHome=Povratak na početak +back.toAdmin=Povratak u admin sekciju + +legal.privacy=Politika privatnosti +legal.terms=Uslovi i odredbe +legal.accessibility=Pristupačnost +legal.cookie=Politika kolačića +legal.impressum=Impresum +legal.showCookieBanner=Podešavanje kolačića + +############### +# Pipeline # +############### +pipeline.header=Tok rada (Beta) +pipeline.uploadButton=Otpremi sopstveno +pipeline.configureButton=Konfiguriši +pipeline.defaultOption=Prilagođeno +pipeline.submitButton=Pošalji +pipeline.help=Pomoć za tok rada (pipeline) +pipeline.scanHelp=Pomoć za pretragu foldera +pipeline.deletePrompt=Jesi li siguran da želiš da obrišeš tok rada + +###################### +# Pipeline Options # +###################### +pipelineOptions.header=Konfiguracija toka rada +pipelineOptions.pipelineNameLabel=Ime toka rada: +pipelineOptions.saveSettings=Sačuvaj podešavanja +pipelineOptions.pipelineNamePrompt=Unesi ime toka rada ovde +pipelineOptions.selectOperation=Izaberi operaciju: +pipelineOptions.addOperationButton=Dodaj operaciju +pipelineOptions.pipelineHeader=Tok rada: +pipelineOptions.saveButton=Preuzmi +pipelineOptions.validateButton=Proveri + +######################## +# ENTERPRISE EDITION # +######################## +enterpriseEdition.button=Nadogradi na Pro verziju +enterpriseEdition.warning=Ova funkcija je dostupna samo Pro korisnicima. +enterpriseEdition.yamlAdvert=Stirling PDF Pro podržava YAML konfiguracione datoteke i druge SSO funkcionalnosti. +enterpriseEdition.ssoAdvert=Tražiš još funkcija za upravljanje korisnicima? Razmotri Stirling PDF Pro +enterpriseEdition.proTeamFeatureDisabled=Funkcije upravljanja timom zahtevaju Pro ili višu licencu + + +################# +# Analytics # +################# +analytics.title=Želiš li da učiniš Stirling PDF boljim? +analytics.paragraph1=Stirling PDF ima opcioni sistem analitike koji nam pomaže da unapredimo proizvod. Ne pratimo nikakve lične podatke niti sadržaj fajlova. +analytics.paragraph2=Molimo te da razmotriš uključivanje analitike kako bi pomogao Stirling PDF-u da raste i omogućio nam bolje razumevanje naših korisnika. +analytics.enable=Omogući analitiku +analytics.disable=Onemogući analitiku +analytics.settings=Možeš da promeniš podešavanja za analitiku u config/settings.yml datoteci + + +############# +# NAVBAR # +############# +navbar.favorite=Omiljeno +navbar.recent=Novo i nedavno ažurirano +navbar.darkmode=Tamni režim +navbar.language=Jezici +navbar.settings=Podešavanja +navbar.allTools=Alati +navbar.multiTool=Višefunkcijski alati +navbar.search=Pretraga +navbar.sections.organize=Organizacija +navbar.sections.convertTo=Konvertuj u PDF +navbar.sections.convertFrom=Konvertuj iz PDF +navbar.sections.security=Potpis i bezbednost +navbar.sections.advance=Napredno +navbar.sections.edit=Pregled i uređivanje +navbar.sections.popular=Popularno + +############# +# SETTINGS # +############# +settings.title=Podešavanja +settings.update=Dostupno ažuriranje +settings.updateAvailable={0} je trenutno instalirana verzija. Nova verzija ({1}) je dostupna. +settings.appVersion=Verzija aplikacije: +settings.downloadOption.title=Odaberi opciju preuzimanja (Za preuzimanje pojedinačnih fajlova bez zip formata): +settings.downloadOption.1=Otvori u istom prozoru +settings.downloadOption.2=Otvori u novom prozoru +settings.downloadOption.3=Preuzmi datoteku +settings.zipThreshold=Zipuj datoteke kada je broj datoteka za preuzimanje veći od +settings.signOut=Odjava +settings.accountSettings=Podešavanja naloga +settings.bored.help=Omogućava skrivenu igru +settings.cacheInputs.name=Sačuvaj unete podatke +settings.cacheInputs.help=Omogući prethodno unete podatke za buduće korišćenje + +changeCreds.title=Promeni pristupne podatke +changeCreds.header=Ažuriraj detalje svog naloga +changeCreds.changePassword=Koristiš podrazumevane pristupne podatke. Molim te unesi novu lozinku +changeCreds.newUsername=Novo korisničko ime +changeCreds.oldPassword=Trenutna lozinka +changeCreds.newPassword=Nova lozinka +changeCreds.confirmNewPassword=Potvrdi novu lozinku +changeCreds.submit=Potvrdi promene + + + +account.title=Podešavanja naloga +account.accountSettings=Podešavanja naloga +account.adminSettings=Admin podešavanja - Pregled i dodavanje korisnika +account.userControlSettings=Podešavanja kontrole korisnika +account.changeUsername=Promeni korisničko ime +account.newUsername=Novo korisničko ime +account.password=Potvrda lozinke +account.oldPassword=Stara lozinka +account.newPassword=Nova lozinka +account.changePassword=Promeni lozinku +account.confirmNewPassword=Potvrdi novu lozinku +account.signOut=Odjava +account.yourApiKey=Tvoj API ključ +account.syncTitle=Sinhronizacija podešavanja pregledača sa nalogom +account.settingsCompare=Upoređivanje podešavanja: +account.property=Svojstvo +account.webBrowserSettings=Podešavanja web pregledača +account.syncToBrowser=Sinhronizacija naloga -> pregledač +account.syncToAccount=Sinhronizacija naloga <- pregledač +account.adminTitle=Administratorski alati +account.adminNotif=Imaš administratorske privilegije. Pristupi sistemskim podešavanjima i upravljanju korisnicima. + + +adminUserSettings.title=Podešavanja kontrole korisnika +adminUserSettings.header=Podešavanja kontrole korisnika za administratora +adminUserSettings.admin=Administrator +adminUserSettings.user=Korisnik +adminUserSettings.addUser=Dodaj novog korisnika +adminUserSettings.deleteUser=Izbriši korisnika +adminUserSettings.confirmDeleteUser=Da obrišem korisnika? +adminUserSettings.confirmChangeUserStatus=Da onemogućim/omogućim korisnika? +adminUserSettings.usernameInfo=Korisničko ime može sadržati samo slova, brojeve i specijalne karaktere @._+- ili mora biti validna email adresa. +adminUserSettings.role=Uloga +adminUserSettings.actions=Akcije +adminUserSettings.apiUser=Korisnik s ograničenim API pristupom +adminUserSettings.extraApiUser=Dodatni ograničeni API korisnik +adminUserSettings.webOnlyUser=Korisnik samo za web +adminUserSettings.demoUser=Demo korisnik (Bez prilagođenih podešavanja) +adminUserSettings.internalApiUser=Interni API korisnik +adminUserSettings.forceChange=Prisili korisnika da promeni korisničko ime/lozinku pri prijavi +adminUserSettings.submit=Sačuvaj korisnika +adminUserSettings.changeUserRole=Promenite ulogu korisnika +adminUserSettings.authenticated=Prijavljen +adminUserSettings.editOwnProfil=Izmeni sopstveni profil +adminUserSettings.enabledUser=omogućen korisnik +adminUserSettings.disabledUser=onemogućen korisnik +adminUserSettings.activeUsers=Aktivni korisnici: +adminUserSettings.disabledUsers=Onemogućeni korisnici: +adminUserSettings.totalUsers=Totalno korisnika: +adminUserSettings.lastRequest=Poslednji zahtev +adminUserSettings.usage=Prikaži upotrebu +adminUserSettings.teams=Prikaži/izmeni timove +adminUserSettings.team=Tim +adminUserSettings.manageTeams=Upravljaj timovima +adminUserSettings.createTeam=Kreiraj tim +adminUserSettings.viewTeam=Pogledaj tim +adminUserSettings.deleteTeam=Obriši tim +adminUserSettings.teamName=Naziv tima +adminUserSettings.teamExists=Tim već postoji +adminUserSettings.teamCreated=Tim uspešno kreiran +adminUserSettings.teamChanged=Korisnički tim uspešno ažuriran +adminUserSettings.teamHidden=Skriven +adminUserSettings.totalMembers=Ukupno članova +adminUserSettings.confirmDeleteTeam=Jesi li siguran da želiš da obrišeš ovaj tim? + +teamCreated=Tim uspešno kreiran +teamExists=Tim sa tim imenom već postoji +teamNameExists=Drugi tim sa tim imenom već postoji +teamNotFound=Tim nije pronađen +teamDeleted=Tim obrisan +teamHasUsers=Nije moguće obrisati tim kom su dodeljni korisnici +teamRenamed=Tim uspešno preimenovan + +# Team user management +team.addUser=Dodaj korisnika timu +team.selectUser=Izaberi korisnika +team.warning.moveUser=Upozorenje: Ovo će prebaciti korisnika iz "{0}" tima u "{1}" tim. Jesi li siguran? +team.confirm.moveUser=Jesi li siguran da želiš da prebaciš ovog korisnika iz "{0}" tima u "{1}" tim? +team.userAdded=Korisnik uspešno pridružen timu +team.back=Povratak na timove +team.internal=Interni tim +team.internalTeamNotAccessible=Interni tim je sistemski tim i ne može mu se pristupiti +team.cannotMoveInternalUsers=Korisnici iz internog tima ne mogu biti premešteni u drugi tim +team.hidden=Skriven +team.name=Naziv tima +team.totalMembers=Ukupno članova +team.members=Članovi +team.username=Korisničko ime +team.role=Uloga +team.status=Status +team.enabled=Omogućen +team.disabled=Onemogućen +team.noMembers=Ovaj tim još uvek nema članova + + + +endpointStatistics.title=Statistika krajnjih tačaka +endpointStatistics.header=Statistika krajnjih tačaka +endpointStatistics.top10=Top 10 +endpointStatistics.top20=Top 20 +endpointStatistics.all=Svi +endpointStatistics.refresh=Osveži +endpointStatistics.includeHomepage=Uključi početnu stranu ('/') +endpointStatistics.includeLoginPage=Uključi stranu za prijavu ('/login') +endpointStatistics.totalEndpoints=Ukupno krajnjih tačaka +endpointStatistics.totalVisits=Ukupno poseta +endpointStatistics.showing=Prikaz +endpointStatistics.selectedVisits=Izabrane posete +endpointStatistics.endpoint=Krajnja tačka +endpointStatistics.visits=Poseta +endpointStatistics.percentage=Procenat +endpointStatistics.loading=Učitavam... +endpointStatistics.failedToLoad=Neuspešno učitavanje podataka o krajnjoj tačci. Pokušaj da osvežiš. +endpointStatistics.home=Početna strana +endpointStatistics.login=Prijava +endpointStatistics.top=Top +endpointStatistics.numberOfVisits=Broj poseta +endpointStatistics.visitsTooltip=Poseta: {0} ({1}% od ukupno) +endpointStatistics.retry=Pokušaj ponovo + +database.title=Uvoz/izvoz baze +database.header=Uvoz/izvoz baze +database.fileName=Ime datoteke +database.creationDate=Datum kreiranja +database.fileSize=Veličina datoteke +database.deleteBackupFile=Obriši rezervnu kopiju +database.importBackupFile=Uvezi rezervnu kopiju +database.createBackupFile=Kreiraj rezervnu kopiju +database.downloadBackupFile=Preuzmi rezervnu kopiju +database.info_1=Prilikom uvoza podataka, od suštinskog je značaja obezbediti ispravnu strukturu. Ako nisi siguran u ono što radiš, potraži savet i podršku stručnog lica. Greška u strukturi može izazvati neispravno funkcionisanje aplikacije, pa čak i potpunu nemogućnost njenog pokretanja. +database.info_2=Naziv fajla prilikom otpremanja nije bitan. Fajl će kasnije biti preimenovan u format backup_user_yyyyMMddHHmm.sql, kako bi se obezbedila dosledna konvencija imenovanja. +database.submit=Uvezi rezervnu kopiju +database.importIntoDatabaseSuccessed=Uvoz u bazu uspešan +database.backupCreated=Rezervna kopija baze podataka je uspešna napravljena +database.fileNotFound=Datoteka nije pronađena +database.fileNullOrEmpty=Datoteka ne sme biti null ili prazna +database.failedImportFile=Neuspešan uvoz datoteke +database.notSupported=Ova funkcija nije dostupna za tvoju vezu sa bazom podataka. + +session.expired=Istekla ti je sesija. Osveži stranicu i pokušaj ponovo. +session.refreshPage=Osveži stranicu + +############# +# HOME-PAGE # +############# +home.desc=Lokalno hostovano rešenje koje za sve tvoje PDF potrebe na jednom mestu. +home.searchBar=Pretraži funkcije... + + +home.viewPdf.title=Pogledaj/izmeni PDF +home.viewPdf.desc=Pregled, komentarisanje, crtanje, dodavanje teksta ili slika +viewPdf.tags=pregledaj,čitaj,komentariši,tekst,slika,istakni,izmeni + +home.setFavorites=Podesi omiljene +home.hideFavorites=Sakrij omiljene +home.showFavorites=Prikaži omiljene +home.legacyHomepage=Stara početna strana +home.newHomePage=Isprobajte našu novu početnu stranu! +home.alphabetical=Abecedno +home.globalPopularity=Globalna popularnost +home.sortBy=Sortiranje: + +home.multiTool.title=PDF višenamenski alat +home.multiTool.desc=Spajanje, rotiranje, premeštanje, deljenje i uklanjanje stranica +multiTool.tags=Višenamenski alat,Višestruke operacije,korisnički interfejs,prevuci i pusti,frontend,klijentska strana,interaktivno,pomeri,obriši,migiraj,podeli + +home.merge.title=Spajanje +home.merge.desc=Lako spajanje više PDF-ova u jedan +merge.tags=spajanje,Operacije sa stranicama,Bekend,serverska strana + +home.split.title=Razdvajanje +home.split.desc=Razdvajanje PDF-ove u više dokumenata +split.tags=Operacije sa stranicama,podela,Višestruke stranice,sečenje,serverska strana + +home.rotate.title=Rotacija +home.rotate.desc=Lako rotiranje PDF-ova +rotate.tags=serverska strana + + +home.imageToPdf.title=Slika u PDF +home.imageToPdf.desc=Konvertovanje slika (PNG, JPEG, GIF) u PDF +imageToPdf.tags=konverzija,img,jpg,slika,foto + +home.pdfToImage.title=PDF u Sliku +home.pdfToImage.desc=Konvertovanje PDF u sliku (PNG, JPEG, GIF) +pdfToImage.tags=konverzija,img,jpg,slika,foto + +home.pdfOrganiser.title=Organizacija +home.pdfOrganiser.desc=Uklanjanje/premeštanje stranica po bilo kom redosledu +pdfOrganiser.tags=dupleks,parne,neparne,sortiranje,pomeranje + + +home.addImage.title=Dodaj sliku +home.addImage.desc=Dodavanje slike na željeno mesto u PDF-u +addImage.tags=img,jpg,slika,foto + +home.attachments.title=Dodaj priloge +home.attachments.desc=Dodavanje ili uklanjanje uključenih datoteka (priloga) u/iz PDF-a +attachments.tags=uključi,dodaj,datoteka,prilog,prilozi + +home.watermark.title=Dodaj vodeni žig +home.watermark.desc=Dodavanje prilagođenog vodenog žiga u PDF dokument +watermark.tags=Tekst,ponavljanje,etiketa,vlastiti,autorsko pravo,kopirajt,logo,img,jpg,slika,foto + +home.permissions.title=Podešavanje dozvola +home.permissions.desc=Izmena dozvola PDF dokumenta +permissions.tags=čitanje,pisanje,izmena,štampa + + +home.removePages.title=Ukloni +home.removePages.desc=Brisanje nepotrebnih stranice iz PDF dokumenta +removePages.tags=Ukloni stranice,obriši stranice + +home.addPassword.title=Dodaj šifru +home.addPassword.desc=Zaštita PDF dokumenata šifrom +addPassword.tags=bezbedno,zaštita + +home.removePassword.title=Ukloni lozinku +home.removePassword.desc=Uklanjanje lozinke iz PDF dokumenta +removePassword.tags=bezbedno,Dešifruj,zaštita,ukloni lozinku + +home.compressPdfs.title=Kompresuj +home.compressPdfs.desc=Kompresovanje PDF-ova radi smanjenja veličine datoteke +compressPdfs.tags=smanji,mali,minijaturni + +home.unlockPDFForms.title=Otključaj PDF obrazac +home.unlockPDFForms.desc=Uklanjanje oznake samo-za-čitanje sa svih polja PDF obrasca +unlockPDFForms.tags=ukloni,obriši,obrazac,polje,samo za čitanje + +home.changeMetadata.title=Izmena metapodataka +home.changeMetadata.desc=Izmena/uklanjanje/dodavanje metapodataka u PDF dokumentu +changeMetadata.tags=Naslov,autor,datum,kreacije,vreme,izdavač,proizvođač,statistike + +home.fileToPDF.title=Konvertuj datoteku u PDF +home.fileToPDF.desc=Konvertovanje gotovo bilo kojih datoteka u PDF (DOCX, PNG, XLS, PPT, TXT i drugih) +fileToPDF.tags=transformacija,format,dokument,slika,slajd,tekst,konverzija,office,docs,word,excel,powerpoint + +home.ocr.title=OCR / Čišćenje skenova +home.ocr.desc=Čišćenje skenova i detektovanje teksta na slikama unutar PDF-a i ponovno dodavanje kao teksta +ocr.tags=prepoznavanje,tekst,slika,sken,čitanje,identifikacija,detekcija,uređivanje + +home.extractImages.title=Izvuci slike +home.extractImages.desc=Izvlačenje svih slika iz PDF-a i kompresovanje u zip format +extractImages.tags=slika,foto,sačuvaj,arhiva,zip,zahvati,uhvati + +home.pdfToPDFA.title=PDF u PDF/A +home.pdfToPDFA.desc=Konvertovanje PDF u PDF/A za dugoročno čuvanje +pdfToPDFA.tags=arhiva,dugoročno,standard,konverzija,čuvanje,čuvanje + +home.PDFToWord.title=PDF u Word +home.PDFToWord.desc=Konvertovanje PDF u Word formate (DOC, DOCX i ODT) +PDFToWord.tags=doc,docx,odt,word,transformacija,format,konverzija,office,microsoft,docfile + +home.PDFToPresentation.title=PDF u prezentaciju +home.PDFToPresentation.desc=Konvertovanje PDF u formate za prezentaciju (PPT, PPTX i ODP) +PDFToPresentation.tags=slajdovi,prikaz,office,microsoft + +home.PDFToText.title=PDF u RTF (tekst) +home.PDFToText.desc=Konvertovanje PDF u tekst ili RTF format +PDFToText.tags=richformat,richtextformat,rich tekst format + +home.PDFToHTML.title=PDF u HTML +home.PDFToHTML.desc=Konvertovanje PDF u HTML format +PDFToHTML.tags=web sadržaj,pogodno za pretraživače + + +home.PDFToXML.title=PDF u XML +home.PDFToXML.desc=Konvertovanje PDF u XML format +PDFToXML.tags=izdvajanje-podataka,strukturirani-sadržaj,interop,transformacija,konvertovanje + +home.ScannerImageSplit.title=Detekcija/razdvajanje skeniranih fotografija +home.ScannerImageSplit.desc=Razdvajanje više fotografija unutar slike/PDF-a +ScannerImageSplit.tags=razdvoji,auto-detekcija,skeniranja,višestruke fotografije,organizacija + +home.sign.title=Potpis +home.sign.desc=Dodavanje potpisa u PDF crtežom, tekstom ili slikom +sign.tags=autorizacija,inicijali,crtani-potpis,tekstualni-potpis,slikovni-potpis + +home.flatten.title=Ravnanje +home.flatten.desc=Uklanjanje svih interaktivnih elemenata i formi iz PDF-a +flatten.tags=statično,deaktivirati,neinteraktivno,usmeriti + +home.repair.title=Popravi +home.repair.desc=Popravljanje oštećenih/izgubljenih PDF-ova +repair.tags=popravi,vrati,korekcija,obnovi + +home.removeBlanks.title=Ukloni prazne stranice +home.removeBlanks.desc=Detekcija i uklanjanje praznih stranica iz dokumenta +removeBlanks.tags=čišćenje,usmeriti,ne-sadržaj,organizacija + +home.removeAnnotations.title=Ukloni beleške +home.removeAnnotations.desc=Uklanjanje svih beleški/anotacije iz PDF dokumenta +removeAnnotations.tags=komentari,isticanje,beleške,oznake,ukloni + +home.compare.title=Uporedi +home.compare.desc=Upoređivanje i prikazivanje razlika između dva PDF dokumenata +compare.tags=razlikovati,kontrast,izmene,analiza + +home.certSign.title=Potpis sertifikatom +home.certSign.desc=Potpisivanje PDF dokumenta sertifikatom/ključem (PEM/P12) +certSign.tags=autentifikacija,PEM,P12,zvanično,šifrovanje + +home.removeCertSign.title=Uklanjanje digitalnog potpisa +home.removeCertSign.desc=Uklanjanje digitalnog potpisa sa sertifikatom iz PDF-a +removeCertSign.tags=autentifikacija,PEM,P12,zvanični,dekripcija + +home.pageLayout.title=Višestruki prikaz stranica +home.pageLayout.desc=Spajanje više stranica PDF dokumenta u jednu stranicu +pageLayout.tags=spajanje,kompozit,pojedinačan-prikaz,organizacija + +home.scalePages.title=Podesi veličinu/razmeru stranice +home.scalePages.desc=Promena veličine/rezmere stranice i/ili njenog sadržaja +scalePages.tags=izmena,modifikacija,dimenzija,adaptacija + +home.pipeline.title=Tok rada +home.pipeline.desc=Izvršavanje više radnji nad PDF dokumentima pomoću definisanih skripti za tok rada +pipeline.tags=automatizacija,sekvenciranje,skriptirano,batch-process + +home.add-page-numbers.title=Dodaj brojeve stranica +home.add-page-numbers.desc=Dodavanje brojeva stranica u dokumentu na željeno mesto +add-page-numbers.tags=paginacija,oznaka,organizacija,indeks + +home.auto-rename.title=Automatska promena imena PDF datoteke +home.auto-rename.desc=Automatsko menjanje imena PDF datoteke na osnovu detektovanog zaglavlja +auto-rename.tags=auto-detekcija,zaglavlje-bazirano,organizacija,preimenovanje + +home.adjust-contrast.title=Podesi boje/kontrast +home.adjust-contrast.desc=Podešavanje kontrasta, zasićenosti i osvetljenost PDF-a +adjust-contrast.tags=korekcija-boja,podešavanje,modifikacija,unapredi + +home.crop.title=Skraćivanje PDF-a +home.crop.desc=Skraćivanje PDF dokumenta radi smanjenja veličine (zadržava tekst!) +crop.tags=trimovanje,skupljanje,uređivanje,oblikovanje + +home.autoSplitPDF.title=Automatski razdvoj PDF +home.autoSplitPDF.desc=Automatska podela skeniranog PDF-a korišćenjem fizičkog QR koda za razdvajanje stranica +autoSplitPDF.tags=QR-bazirano,razdvoji,segment-skeniranja,organizacija + +home.sanitizePdf.title=Sanitizacija +home.sanitizePdf.desc=Uklanjanje skripti i drugih elemente iz PDF dokumenata +sanitizePdf.tags=čišćenje,bezbednost,bezbedno,ukloni-pretnje + +home.URLToPDF.title=URL/Website u PDF +home.URLToPDF.desc=Konvertuje bilo koji http(s) URL u PDF +URLToPDF.tags=uhvati-web,sačuvaj-stranicu,web-u-doc,arhiva + +home.HTMLToPDF.title=HTML u PDF +home.HTMLToPDF.desc=Konvertovanje bilo koje HTML datoteke ili zip u PDF +HTMLToPDF.tags=oznake,web-sadržaj,transformacija,konvertovanje + +#eml-to-pdf +home.EMLToPDF.title=Email u PDF +home.EMLToPDF.desc=Konvertovanje email (EML) datoteka u PDF format uključujući zaglavlje, telo poruke i ugrađene slike +EMLToPDF.tags=email,konverzija,eml,poruka,transformacija,konvertovanje,elektronska poruka + +EMLToPDF.title=Email u PDF +EMLToPDF.header=Email u PDF +EMLToPDF.submit=Konvertuj +EMLToPDF.downloadHtml=Preuzmi HTML međufajl umesto PDF-a +EMLToPDF.downloadHtmlHelp=Ovo omogućava da se vidi HTML verzija pre konverzije u PDF i može pomoći u otklanjanju problema sa formatiranjem. +EMLToPDF.includeAttachments=Uključi dodatke u PDF +EMLToPDF.maxAttachmentSize=Maksimalna veličina dodatka (MB) +EMLToPDF.help=Konvertovanje email (EML) datoteka u PDF format uključujući zaglavlje, telo poruke i ugrađene slike +EMLToPDF.troubleshootingTip1=Konverzija emaila u HTML je pouzdaniji proces, te se kod serijske obrade preporučuje čuvanje oba formata. +EMLToPDF.troubleshootingTip2=Kod malog broja emailova, ako je PDF neispravan, moguće je preuzeti HTML i ispraviti deo problematičnog HTML/CSS koda. +EMLToPDF.troubleshootingTip3=Ugradnja sadržaja, međutim, ne funkcioniše sa HTML fajlovima. + +home.MarkdownToPDF.title=Markdown u PDF +home.MarkdownToPDF.desc=Konvertovanje Markdown datoteka u PDF +MarkdownToPDF.tags=oznake,web-sadržaj,transformacija,konvertovanje + +home.PDFToMarkdown.title=PDF u Markdown +home.PDFToMarkdown.desc=Konvertovanje PDF datoteka u Markdown +PDFToMarkdown.tags=markup,web-sadržaj,transformacija,konvertovanje,md + +home.getPdfInfo.title=Prikazi sve informacije o PDF-u +home.getPdfInfo.desc=Prikazivanje svih mogućih informacija o PDF datotekama +getPdfInfo.tags=informacije,podaci,statistike + + +home.extractPage.title=Izdvajanje stranica +home.extractPage.desc=Izdvajanje odabranih stranice iz PDF dokumenta +extractPage.tags=izdvajanje + + +home.PdfToSinglePage.title=PDF u jednu veliku stranicu +home.PdfToSinglePage.desc=Spajanje svih stranica u PDF-u u jednu veliku stranicu +PdfToSinglePage.tags=jedna-stranica + + +home.showJS.title=Prikaži JavaScript +home.showJS.desc=Pretraživanje i prikaz JavaScriptova ubačenih u PDF +showJS.tags=JS + +home.autoRedact.title=Automatsko cenzurisanje +home.autoRedact.desc=Automatsko cenzurisanje teksta u PDF-u na osnovu unetog teksta +autoRedact.tags=Redakcija,Sakrij,prekrivanje,crna,marker,skriveno + +home.redact.title=Ručna redakcija +home.redact.desc=Redakcija PDF dokumenta na osnovu izabranog teksta, nacrtanih oblika i/ili izabranih strana +redact.tags=Redakcija,Sakrij,zacrnjivanje,crno,marker,skrfiveno,ručno + +home.tableExtraxt.title=PDF u CSV +home.tableExtraxt.desc=Izdvajanje tabele iz PDF-a pretvarajući ih u CSV +tableExtraxt.tags=CSV,Izdvajanje tabela,izdvajanje,konvertovanje + + +home.autoSizeSplitPDF.title=Automatsko deljenje po veličini/broju +home.autoSizeSplitPDF.desc=Deljenje jednog PDF-a na više na osnovu veličine, broja stranica ili broja dokumenata +autoSizeSplitPDF.tags=pdf,deljenje,dokumenti,organizacija + + +home.overlay-pdfs.title=Preklapanje PDF-ova +home.overlay-pdfs.desc=Preklapanje PDF dokumenata jedan preko drugog +overlay-pdfs.tags=Preklapanje + +home.split-by-sections.title=Deljenje PDF-a po sekcijama +home.split-by-sections.desc=Deljenje svake stranice PDF-a na manje horizontalne i vertikalne sekcije +split-by-sections.tags=Deljenje sekcija,Deljenje,Podešavanje + +home.AddStampRequest.title=Dodaj pečat u PDF +home.AddStampRequest.desc=Dodavanje teksta ili slike pečeta na željenim lokacijama +AddStampRequest.tags=Pečat, Dodaj sliku, centriraj sliku, Vodeni žig, PDF, Uključi, Prilagodi + + +home.removeImagePdf.title=Ukloni sliku +home.removeImagePdf.desc=Uklanjanje slike iz PDF-a u cilju smanjenja veličine datoteke +removeImagePdf.tags=Ukloni sliku, Zahvati na stranici, Bekend,serverska strana + + +home.splitPdfByChapters.title=Podeli PDF po poglavljima +home.splitPdfByChapters.desc=Deljenje PDF-a na više datoteka na osnovu strukture poglavlja +splitPdfByChapters.tags=podeli,poglavlja,zabeleške,organizacija + +home.validateSignature.title=Proveri PDF potpis +home.validateSignature.desc=Verifikacija digitalnog potpisa i sertifikata u PDF dokumentu +validateSignature.tags=potpis,verifikacija,valdiacija,pdf,sertifikat,digitalni potpis,Validacija potpisa,Validacija sertifikata + +#replace-invert-color +replace-color.title=Napredna podešavanja boja +replace-color.header=Zameni/invertuj boju PDF-a +home.replaceColorPdf.title=Napredna podešavanja boja +home.replaceColorPdf.desc=Zameni boju teksta i pozadine u PDF i invertuj celokupnu boju PDF-a u cilju smanjenja veličine datoteke +replaceColorPdf.tags=Zameni boju,Operacije na stranici,Bekend,Serverska strana +replace-color.selectText.1=Opcije zamene ili inverzije boja: +replace-color.selectText.2=Podrazumevano (Podrazumevane boje visokog kontrasta) +replace-color.selectText.3=Prilagođeno (Prilagođene boje) +replace-color.selectText.4=Puna inverzija (Invertuj sve boje) +replace-color.selectText.5=Opcije boja visokog kontrasta: +replace-color.selectText.6=Beli tekst na crnoj pozadini +replace-color.selectText.7=Crni tekst na beloj pozadini +replace-color.selectText.8=Žuti tekst na crnoj pozadini +replace-color.selectText.9=Zeleni tekst na crnoj pozadini +replace-color.selectText.10=Izaberi boju teksta: +replace-color.selectText.11=Izaberi boju pozadine: +replace-color.submit=Zameni + + + +########################### +# # +# WEB PAGES # +# # +########################### +#login +login.title=Prijavi se +login.header=Prijavi se +login.signin=Prijavi se +login.rememberme=Zapamti me +login.invalid=Neispravno korisničko ime ili lozinka. +login.locked=Nalog je zaključan. +login.signinTitle=Prijavite se +login.ssoSignIn=Prijavite se putem jedinstvene prijave +login.oAuth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno +login.oAuth2AdminBlockedUser=Registracija ili prijava neregistrovanog korisnika je trenutno onemogućeno. Kontaktirajte administratora. +login.oauth2RequestNotFound=Zahtev za autorizaciju nije pronađen +login.oauth2InvalidUserInfoResponse=Neispravan odgovor sa korisničkim informacijama +login.oauth2invalidRequest=Neispravan zahtev +login.oauth2AccessDenied=Pristup odbijen +login.oauth2InvalidTokenResponse=Neispravan odgovor tokena +login.oauth2InvalidIdToken=Neispravan ID tokena +login.relyingPartyRegistrationNotFound=Nije pronađena registracija partnerske strane +login.userIsDisabled=Korisnik deaktiviran, prijava sa ovim korisničkim imenom je trenutno blokirana. Kontaktiraj administratora. +login.alreadyLoggedIn=Već si prijavljen na +login.alreadyLoggedIn2=uređaja. Odjavi se sa uređaja i pokušaj ponovo. +login.toManySessions=Imaš previše aktivnih sesija +login.logoutMessage=Odjavljen si. + +#auto-redact +autoRedact.title=Automatsko cenzurisanje +autoRedact.header=Automatko cenzurisanje +autoRedact.colorLabel=Boja: +autoRedact.textsToRedactLabel=Pojmovi za centurisanje (svaki u novi red ): +autoRedact.textsToRedactPlaceholder=npr. \nPoverljivo \nVrhunski tajno +autoRedact.useRegexLabel=Koristi regex +autoRedact.wholeWordSearchLabel=Pretraga celih reči +autoRedact.customPaddingLabel=Dodatni prazan prostor: +autoRedact.convertPDFToImageLabel=Konvertuj PDF u PDF-Image (koristi se za uklanjanje teksta iza zatamnjenja) +autoRedact.submitButton=Potvrdi + +#redact +redact.title=Ručna cenzura +redact.header=Ručna cenzura +redact.submit=Redaktuj +redact.textBasedRedaction=Redakcija zasnovana na tekstu +redact.pageBasedRedaction=Redakcija zasnovana na stranici +redact.convertPDFToImageLabel=Konvertuj PDF u PDF-Image (koristi se za uklanjanje teksta iza okvira) +redact.pageRedactionNumbers.title=Strane +redact.pageRedactionNumbers.placeholder=(npr. 1,2,8 ili 4,7,12-16 ili 2n-1) +redact.redactionColor.title=Boja redakcije +redact.export=Izvezi +redact.upload=Otpremi +redact.boxRedaction=Redakcija iscrtavanjem okvira +redact.zoom=Zumiranje +redact.zoomIn=Uvećaj +redact.zoomOut=Umanji +redact.nextPage=Sledeća strana +redact.previousPage=Prethodna strana +redact.toggleSidebar=Uključi/isključi bočnu traku +redact.showThumbnails=Prikaži sličice +redact.showDocumentOutline=Prikaži strukturu dokumenta (dvostruki klik za otvaranje/zatvaranje svih stavki) +redact.showAttatchments=Prikaži priloge +redact.showLayers=Prikaži slojeve (dvostruki klik za vraćanje svih slojeva na podrazumevano stanje) +redact.colourPicker=Izbor boje +redact.findCurrentOutlineItem=Pronađi aktuelnu stavku pregleda +redact.applyChanges=Primeni izmene + +#showJS +showJS.title=Prikaži Javascript +showJS.header=Prikaži Javascript +showJS.downloadJS=Preuzmi Javascript +showJS.submit=Prikaži + + +#pdfToSinglePage +pdfToSinglePage.title=PDF u jednu stranicu +pdfToSinglePage.header=PDF u jednu stranicu +pdfToSinglePage.submit=Konvertuj u jednu stranicu + + +#pageExtracter +pageExtracter.title=Izdvajanje stranica +pageExtracter.header=Izdvajanje stranica +pageExtracter.submit=Izdvoj +pageExtracter.placeholder=(npr. 1,2,8 ili 4,7,12-16 ili 2n-1) + + +#getPdfInfo +getPdfInfo.title=Informacije o PDF-u +getPdfInfo.header=Informacije o PDF-u +getPdfInfo.submit=Prikaži +getPdfInfo.downloadJson=Preuzmi JSON +getPdfInfo.summary=PDF sažetak +getPdfInfo.summary.encrypted=Ovaj PDF je šifrovan, pa može doći do problema sa nekim aplikacijama +getPdfInfo.summary.permissions=Ovaj PDF ima {0} ograničenih dozvola koje mogu ograničiti mogućnosti rada sa njim +getPdfInfo.summary.compliance=Ovaj PDF zadovoljava specifikacije standarda {0} +getPdfInfo.summary.basicInfo=Osnovne informacije +getPdfInfo.summary.docInfo=Informacije o dokumentu +getPdfInfo.summary.encrypted.alert=Šifrovan PDF - Ovaj dokument je zaštićen lozinkom +getPdfInfo.summary.not.encrypted.alert=Nešifrovan PDF - Nije zaštićen lozinkom +getPdfInfo.summary.permissions.alert=Ograničene dozvole - {0} radnji nije dozvoljeno +getPdfInfo.summary.all.permissions.alert=Sve dozvole omogućene +getPdfInfo.summary.compliance.alert={0} u skladu +getPdfInfo.summary.no.compliance.alert=Bez usklađenih standarda +getPdfInfo.summary.security.section=Sigurnosni status +getPdfInfo.section.BasicInfo=Osnovne informacije o PDF dokumentu uključujući veličinu, broj strane i jezik +getPdfInfo.section.Metadata=Metapodaci dokumenta uključujući naslov, autora, datum kreiranja i druga svojstva dokumenta +getPdfInfo.section.DocumentInfo=Tehnički detalji o strukturi i verziji PDF dokumenta +getPdfInfo.section.Compliancy=Informacije o usklađenosti sa PDF standardima (PDF/A, PDF/X, itd.) +getPdfInfo.section.Encryption=Informacije o bezbednosti i šifrovanju dokumenta +getPdfInfo.section.Permissions=Postavke dozvola dokumenta koje određuju koje radnje su dozvoljene +getPdfInfo.section.Other=Dodatne komponente dokumenta kao što su obeleživači, slojevi i ugrađene datoteke +getPdfInfo.section.FormFields=Interaktivna polja formulara u dokumentu +getPdfInfo.section.PerPageInfo=Dodatne informacije o svakoj pojedinačnoj stranici u dokumentu + + +#markdown-to-pdf +MarkdownToPDF.title=Markdown u PDF +MarkdownToPDF.header=Markdown u PDF +MarkdownToPDF.submit=Konvertuj +MarkdownToPDF.help=Rad u toku +MarkdownToPDF.credit=Koristi WeasyPrint + + +#pdf-to-markdown +PDFToMarkdown.title=PDF u Markdown +PDFToMarkdown.header=PDF u Markdown +PDFToMarkdown.submit=Konvertuj + + +#url-to-pdf +URLToPDF.title=URL u PDF +URLToPDF.header=URL u PDF +URLToPDF.submit=Konvertuj +URLToPDF.credit=Koristi WeasyPrint + + +#html-to-pdf +HTMLToPDF.title=HTML u PDF +HTMLToPDF.header=HTML u PDF +HTMLToPDF.help=Podržava HTML datoteke i ZIP-ove koji sadrže html/css/slike itd. +HTMLToPDF.submit=Konvertuj +HTMLToPDF.credit=Koristi WeasyPrint +HTMLToPDF.zoom=Nivo zumiranja za prikaz web sajta: +HTMLToPDF.pageWidth=Širina stranice u centimetrima. (Prazno za podrazumevanu vrednost) +HTMLToPDF.pageHeight=Visina stranice u centimetrima. (Prazno za podrazumevanu vrednost) +HTMLToPDF.marginTop=Gornja margina stranice u milimetrima. (Prazno za podrazumevanu vrednost) +HTMLToPDF.marginBottom=Donja margina stranice u milimetrima. (Prazno za podrazumevanu vrednost) +HTMLToPDF.marginLeft=Leva margina stranice u milimetrima. (Prazno za podrazumevanu vrednost) +HTMLToPDF.marginRight=Desna margina stranice u milimetrima. (Prazno za podrazumevanu vrednost) +HTMLToPDF.printBackground=Prikaži pozadinu web sajta. +HTMLToPDF.defaultHeader=Omogući podrazumevano zaglavlje (Naziv i broj stranice) +HTMLToPDF.cssMediaType=Promeni tip medija za CSS na stranici. +HTMLToPDF.none=Nijedno +HTMLToPDF.print=Štampaj +HTMLToPDF.screen=Ekran + + +#AddStampRequest +AddStampRequest.header=Pečatiraj PDF +AddStampRequest.title=Dodavanje pečata u PDF +AddStampRequest.stampType=Tip pečeta: +AddStampRequest.stampText=Tekst pečata: +AddStampRequest.stampImage=Slika pečeta: +AddStampRequest.alphabet=Pismo: +AddStampRequest.fontSize=Veličina fonta/slike: +AddStampRequest.rotation=Rotacija: +AddStampRequest.opacity=Providnost: +AddStampRequest.position=Pozicija: +AddStampRequest.overrideX=Zameni X koordinatu: +AddStampRequest.overrideY=Zameni Y koordinatu: +AddStampRequest.customMargin=Podešavanje margina: +AddStampRequest.customColor=Željena boja teksta: +AddStampRequest.submit=Pošalji + + +#sanitizePDF +sanitizePDF.title=Sanitizacija PDF-a +sanitizePDF.header=Sanitizacija PDF fajla +sanitizePDF.selectText.1=Ukloni JavaScript akcije +sanitizePDF.selectText.2=Ukloni ugrađene fajlove +sanitizePDF.selectText.3=Ukloni XMP metapodatke +sanitizePDF.selectText.4=Ukloni linkove +sanitizePDF.selectText.5=Ukloni fontove +sanitizePDF.selectText.6=Ukloni metapodatke informacija o dokumentu +sanitizePDF.submit=Sanitizuj PDF + + +#addPageNumbers +addPageNumbers.title=Numerisanje stranica +addPageNumbers.header=Dodavanje brojeva stranica +addPageNumbers.selectText.1=Izaberi PDF fajl: +addPageNumbers.selectText.2=Veličina margine: +addPageNumbers.selectText.3=Pozicija: +addPageNumbers.selectText.4=Početni broj: +addPageNumbers.selectText.5=Stranice za numerisanje: +addPageNumbers.selectText.6=Prilagođeni tekst: +addPageNumbers.customTextDesc=Prilagođeni tekst +addPageNumbers.numberPagesDesc=Koje stranice brojati, podrazumevano 'sve', takođe prihvata 1-5 ili 2,5,9 itd. +addPageNumbers.customNumberDesc=Podrazumevano je {n}, takođe prihvata 'Stranica {n} od {ukupno}', 'Tekst-{n}', '{ime_fajla}-{n}' +addPageNumbers.submit=Numeriši + + +#auto-rename +auto-rename.title=Automatsko preimenovanje +auto-rename.header=Automatsko preimenovanje PDF-a +auto-rename.submit=Automatsko preimenovanje + + +#adjustContrast +adjustContrast.title=Podesi kontrast +adjustContrast.header=Podesi kontrast +adjustContrast.contrast=Kontrast: +adjustContrast.brightness=Osvetljenje: +adjustContrast.saturation=Zasićenje: +adjustContrast.download=Preuzmi + + +#crop +crop.title=Iseci +crop.header=Iseci PDF +crop.submit=Potvrdi + + +#autoSplitPDF +autoSplitPDF.title=Automatsko razdvajanje PDF-a +autoSplitPDF.header=Automatsko razdvajanje PDF-a +autoSplitPDF.description=Odštampaj, ubaci, skeniraj, otpremi i prepusti nama automatsko razdvajanje dokumenata. Nije potrebno ručno sortiranje. +autoSplitPDF.selectText.1=Odštampaj neki od razdelnika sa liste ispod (Crno-belo je u redu). +autoSplitPDF.selectText.2=Skeniraj sve dokumente odjednom, ubacivanjem lista razdelnika između njih. +autoSplitPDF.selectText.3=Otpremi jedan veliki skenirani PDF fajl i dozvoli Stirling PDF-u da obavi ostalo. +autoSplitPDF.selectText.4=Listovi razdelnici se automatski detektuju i uklanjaju, obezbeđujući uredan konačni dokument. +autoSplitPDF.formPrompt=Pošalji PDF koji sadrži Stirling-PDF listove razdelnike stranica: +autoSplitPDF.duplexMode=Dupleks režim (skeniranje prednje i zadnje strane) +autoSplitPDF.dividerDownload2=Preuzmi 'Auto Splitter Divider (with instructions).pdf' +autoSplitPDF.submit=Razdvoj + + +#pipeline +pipeline.title=Tok rada + + +#pageLayout +pageLayout.title=Višestranični raspored +pageLayout.header=Višestranični raspored +pageLayout.pagesPerSheet=Stranica po listu: +pageLayout.addBorder=Dodaj ivice +pageLayout.submit=Potvrdi + + +#scalePages +scalePages.title=Podesi razmeru stranice +scalePages.header=Podesi razmeru stranice +scalePages.pageSize=Veličina stranice dokumenta: +scalePages.keepPageSize=Originalna veličina +scalePages.scaleFactor=Nivo zumiranja (isečak) stranice: +scalePages.submit=Potvrdi + + +#certSign +certSign.title=Potpisivanje sertifikatom +certSign.header=Potpiši PDF svojim sertifikatom (Rad u toku) +certSign.selectPDF=Izaberi PDF dokument za potpisivanje: +certSign.jksNote=Napomena: Ako tvoj tip sertifikata nije naveden ispod, konvertuj ga u Java Keystore (.jks) format koristeći komandni alat keytool. Zatim izaberi opciju .jks ispod. +certSign.selectKey=Izaberi svoj privatni ključ (PKCS#8 format, može biti .pem ili .der): +certSign.selectCert=Izaberi svoj sertifikat (X.509 format, može biti .pem ili .der): +certSign.selectP12=Izaberi svoju PKCS#12 keystore datoteku (.p12 ili .pfx) (Opciono, ako je dostupan, trebalo bi da sadrži tvoj privatni ključ i sertifikat): +certSign.selectJKS=Izaberi svoju Java keystore datoteku (.jks or .keystore): +certSign.certType=Tip sertifikata: +certSign.password=Unesi lozinku keystore datoteke ili privatnog ključa (ako postoji): +certSign.showSig=Prikaži potpis +certSign.reason=Razlog +certSign.location=Lokacija +certSign.name=Ime +certSign.showLogo=Prikaži logo +certSign.submit=Potpiši PDF + + +#removeCertSign +removeCertSign.title=Ukloni potpis sertifikata +removeCertSign.header=Ukloni digitalni sertifikat iz PDF-a +removeCertSign.selectPDF=Izaberi PDF dokument: +removeCertSign.submit=Ukloni potpis + + +#removeBlanks +removeBlanks.title=Ukloni prazne stranice +removeBlanks.header=Ukloni prazne stranice +removeBlanks.threshold=Prag beline piksela: +removeBlanks.thresholdDesc=Prag za određivanje koliko piksel mora biti beo da bi se smatrao 'belim'. 0 = Crno, 255 čisto belo. +removeBlanks.whitePercent=Procenat bele boje (%): +removeBlanks.whitePercentDesc=Procenat stranice koji mora biti 'beo' da bi se uklonila. +removeBlanks.submit=Ukloni prazne + + +#removeAnnotations +removeAnnotations.title=Ukloni anotacije/beleške +removeAnnotations.header=Ukloni beleške +removeAnnotations.submit=Ukloni + + +#compare +compare.title=Uporedi +compare.header=Uporedi PDF-ove +compare.highlightColor.1=Boja isticanja 1: +compare.highlightColor.2=Boja isticanja 2: +compare.document.1=Dokument 1 +compare.document.2=Dokument 2 +compare.submit=Uporedi +compare.complex.message=Jedan ili oba dostavljena dokumenta su veliki pa tačnost poređenja može biti smanjena. +compare.large.file.message=Jedan ili oba dostavljena dokumenta su preveliki za obradu +compare.no.text.message=Jedan ili oba izabrana PDF-a nemaju tekstualni sadržaj. Izaberi PDF-ove sa tekstom za poređenje. + +#sign +sign.title=Potpiši +sign.header=Potpiši PDF-ove +sign.upload=Učitaj sliku +sign.draw=Nacrtaj potpis +sign.text=Tekstualni unos +sign.clear=Obriši +sign.add=Dodaj +sign.saved=Snimljeni potpisi +sign.save=Snimi potpis +sign.personalSigs=Lični potpisi +sign.sharedSigs=Deljeni potpisi +sign.noSavedSigs=Nema snimljenih potpisa +sign.addToAll=Dodaj na sve stranice +sign.delete=Obriši +sign.first=Prva strana +sign.last=Poslednja strana +sign.next=Sledeća strana +sign.previous=Prethodna strana +sign.maintainRatio=Uključi/isključi zadržavanje proporcija +sign.undo=Poništi +sign.redo=Ponovi + +#repair +repair.title=Popravi +repair.header=Popravi PDF-ove +repair.submit=Popravi + + +#flatten +flatten.title=Ravnanje +flatten.header=Ravnanje PDF-ova +flatten.flattenOnlyForms=Izravnaj samo forme +flatten.submit=Poravnaj + + +#ScannerImageSplit +ScannerImageSplit.selectText.1=Prag ugla: +ScannerImageSplit.selectText.2=Postavlja minimalni apsolutni ugao potreban za rotiranje slike (podrazumevano: 10). +ScannerImageSplit.selectText.3=Tolerancija: +ScannerImageSplit.selectText.4=Određuje opseg varijacije boja oko procenjene boje pozadine (podrazumevano: 30). +ScannerImageSplit.selectText.5=Minimalna površina: +ScannerImageSplit.selectText.6=Postavlja minimalni prag površine za fotografiju (podrazumevano: 10000). +ScannerImageSplit.selectText.7=Minimalna površina konture: +ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju. +ScannerImageSplit.selectText.9=Veličina ivice: +ScannerImageSplit.selectText.10=Postavlja veličinu ivice koja se dodaje i uklanja kako bi se sprečile bele ivice u izlazu (podrazumevano: 1). +ScannerImageSplit.info=Python nije instaliran. Neophodan je za rad. + + +#OCR +ocr.title=OCR / Čišćenje skeniranih dokumenata +ocr.header=Čišćenje skeniranja / OCR (Optičko prepoznavanje karaktera) +ocr.selectText.1=Izaberi jezike koji treba da budu detektovani u PDF-u (navedeni su trenutno detektovani jezici): +ocr.selectText.2=Napravi tekstualni fajl koji sadrži OCR tekst zajedno sa OCR PDF-om +ocr.selectText.3=Ispravi stranice koje su skenirane pod uglom rotirajući ih na svoje mesto +ocr.selectText.4=Očisti stranicu kako bi se smanjila mogućnost da OCR prepozna tekst u pozadinskoj buci. (Bez promene izlaz) +ocr.selectText.5=Očisti stranicu kako bi se smanjila mogućnost da OCR prepozna tekst u pozadinskoj buci, zadržavajući čišćenje u izlazu. +ocr.selectText.6=Ignoriše stranice koje sadrže interaktivni tekst, radi OCR samo na stranicama koje su slike +ocr.selectText.7=Forsiraj OCR, OCR će se izvršiti na svakoj stranici uklanjajući sve originalne tekstualne elemente +ocr.selectText.8=Normalno (Prikaže grešku ako PDF sadrži tekst) +ocr.selectText.9=Dodatne postavke +ocr.selectText.10=Režim OCR-a: +ocr.selectText.11=Ukloni slike nakon OCR-a (Uklanja SVE slike, korisno samo ako je deo procesa konverzije) +ocr.selectText.12=Tip renderovanja (napredno): +ocr.help=Molimo pročitajte sledeću dokumentaciju o tome kako koristiti ovu opciju za druge jezike i/ili kako koristiti van Dockera +ocr.credit=Ova usluga koristi qpdf i Tesseract za OCR. +ocr.submit=Obradi PDF sa OCR-om + + +#extractImages +extractImages.title=Izvuci slike +extractImages.header=Izvuci slike +extractImages.selectText=Izaberi format u koji će se konvertovati izvučene slike: +extractImages.allowDuplicates=Sačuvaj duplirane slike +extractImages.submit=Izvuci + + +#File to PDF +fileToPDF.title=Datoteka u PDF +fileToPDF.header=Konvertuj bilo koju datoteku u PDF +fileToPDF.credit=Ova usluga koristi LibreOffice i Unoconv za konverziju datoteka. +fileToPDF.supportedFileTypesInfo=Podržani tipovi datoteka +fileToPDF.supportedFileTypes=Podržani tipovi datoteka trebalo bi da uključuju navedene ispod, ali za kompletnu i ažuriranu listu podržanih formata, pogledajte LibreOffice dokumentaciju: +fileToPDF.submit=Konvertuj u PDF + + +#compress +compress.title=Kompresuj +compress.header=Kompresuj PDF +compress.credit=Ova usluga koristi qpdf za kompresiju/optimizaciju PDF-a. +compress.grayscale.label=Primeni monohromatski režim za kompresiju +compress.selectText.1=Podešavanje kompresije +compress.selectText.1.1=1-3 PDF kompresija,
4-6 blaga kompresija slika,
7-9 intenzivna kompresija slika koja značajno smanjuje kvalitet slika +compress.selectText.2=Nivo optimizacije: +compress.selectText.4=Automatski režim – Automatski podešava kvalitet kako bi PDF imao tačno određenu veličinu +compress.selectText.5=Željena veličina PDF-a (npr. 25MB, 10.8MB, 25KB) +compress.submit=Kompresuj + + +#Add image +addImage.title=Dodaj sliku +addImage.header=Dodaj sliku u PDF +addImage.everyPage=Na svaku stranicu? +addImage.upload=Dodaj sliku +addImage.submit=Dodaj sliku + +#attachments +attachments.title=Dodaj priloge +attachments.header=Dodaj priloge +attachments.description=Omogućava dodavanje priloga u PDF +attachments.descriptionPlaceholder=Upiši opis za priloge... +attachments.addButton=Dodaj priloge + +#merge +merge.title=Spajanje +merge.header=Spoji više PDF-ova (2+) +merge.sortByName=Sortiraj po imenu +merge.sortByDate=Sortiraj po datumu +merge.removeCertSign=Ukloni digitalni potpis iz spojenog dokumenta? +merge.generateToc=Generiši listu sadržaja u spojenom dokumentu? +merge.submit=Spoj + + +#pdfOrganiser +pdfOrganiser.title=Organizator stranica +pdfOrganiser.header=Organizator stranica u PDF-u +pdfOrganiser.submit=Preuredi stranice +pdfOrganiser.mode=Mod +pdfOrganiser.mode.1=Prilagođeni redosled stranica +pdfOrganiser.mode.2=Obrnuti redosled +pdfOrganiser.mode.3=Redosled za obostranu štampu +pdfOrganiser.mode.4=Redosled za brošuru +pdfOrganiser.mode.5=Redosled za brošuru sa spajanjem sa strane +pdfOrganiser.mode.6=Razdvoji neparne i parne stranice +pdfOrganiser.mode.7=Ukloni prvu +pdfOrganiser.mode.8=Ukloni poslednju +pdfOrganiser.mode.9=Ukloni prvu i poslednju +pdfOrganiser.mode.10=Spoji neparne i parne stranice +pdfOrganiser.mode.11=Dupliraj sve stranice +pdfOrganiser.placeholder=(npr. 1,3,2 ili 4-8,2,10-12 ili 2n-1) + + +#multiTool +multiTool.title=Višefunkcionalni PDF alat +multiTool.header=Višefunkcionalni PDF alat +multiTool.uploadPrompts=Naziv datoteke +multiTool.selectAll=Izaberi sve +multiTool.deselectAll=Poništi sve +multiTool.selectPages=Izbor stranica +multiTool.selectedPages=Izabrane stranice +multiTool.page=Stranica +multiTool.deleteSelected=Izaberi izabrano +multiTool.downloadAll=Izvoz +multiTool.downloadSelected=Izvezi izabrano + +multiTool.insertPageBreak=Ubaci prelom stranice +multiTool.addFile=Dodaj datoteku +multiTool.rotateLeft=Rotiraj levo +multiTool.rotateRight=Rotiraj desno +multiTool.split=Podeli +multiTool.moveLeft=Pomeri levo +multiTool.moveRight=Pomeri desno +multiTool.delete=Obriši +multiTool.dragDropMessage=Izabrane stranica/e +multiTool.undo=Poništi (CTRL + Z) +multiTool.redo=Ponovi (CTRL + Y) + +#decrypt +decrypt.passwordPrompt=Ova datoteka je zaštićena lozinkom. Unesi lozinku: +decrypt.cancelled=Operacija otkazana za PDF: {0} +decrypt.noPassword=Nije uneta lozinka za šifrovani PDF: {0} +decrypt.invalidPassword=Pokušaj ponovo sa ispravnom lozinkom. +decrypt.invalidPasswordHeader=Neispravna lozinka ili nepodržana enkripcija za PDF: {0} +decrypt.unexpectedError=Došle je do greške prilikom obrade datoteke. Pokušaj ponovo. +decrypt.serverError=Greška na serveru prilikom dekriptovanja: {0} +decrypt.success=Datoteka uspešno dekriptovana. + +#multiTool-advert +multiTool-advert.message=Ova funkcija je dostupna i na našoj stranici sa višenamenskim alatom. Potraži unapređeni interfejs po stranici i dodatne funkcije! + +#view pdf +viewPdf.title=Pogledaj/Izmeni PDF +viewPdf.header=Prikaz PDF-a + +#pageRemover +pageRemover.title=Uklanjanje stranica +pageRemover.header=Uklanjanje stranica iz PDF-a +pageRemover.pagesToDelete=Stranice za brisanje (unesi listu brojeva stranica odvojenih zarezima) : +pageRemover.submit=Obriši stranice +pageRemover.placeholder=(npr. 1,2,6 ili 1-10,15-30) + + +#rotate +rotate.title=Rotiranje PDF-a +rotate.header=Rotiranje PDF-a +rotate.selectAngle=Izaberi ugao rotacije (u množiocima od 90 stepeni): +rotate.submit=Rotiraj + + +#split-pdfs +split.title=Razdvajanje PDF-a +split.header=Razdvajanje PDF-a +split.desc.1=Izabrani brojevi predstavljaju stranice na kojima će se napraviti razdvajanje. +split.desc.2=Na primer, izbor 1,3,7-9 bi razdvojio dokument od 10 stranica u 6 odvojenih PDF-ova sa: +split.desc.3=Dokument #1: Stranica 1 +split.desc.4=Dokument #2: Stranice 2 i 3 +split.desc.5=Dokument #3: Stranice 4, 5, 6 i 7 +split.desc.6=Dokument #4: Stranica 8 +split.desc.7=Dokument #5: Stranica 9 +split.desc.8=Dokument #6: Stranice 10 +split.splitPages=Upiši brojeve stranica za razdvajanje: +split.submit=Razdvoj + + +#merge +imageToPDF.title=Slika u PDF +imageToPDF.header=Slika u PDF +imageToPDF.submit=Konvertuj +imageToPDF.selectLabel=Opcije prilagođavanja slike: +imageToPDF.fillPage=Popuni stranicu +imageToPDF.fitDocumentToImage=Prilagodi stranicu slici +imageToPDF.maintainAspectRatio=Zadrži proporcije +imageToPDF.selectText.2=Automatsko rotiranje PDF-a +imageToPDF.selectText.3=Logika za više datoteka (omogućeno samo ako se radi sa više slika): +imageToPDF.selectText.4=Spoji u jedan PDF +imageToPDF.selectText.5=Konvertuj u odvojene PDF-ove + + +#pdfToImage +pdfToImage.title=PDF u sliku +pdfToImage.header=PDF u sliku +pdfToImage.selectText=Format slike: +pdfToImage.singleOrMultiple=Izlazni format stranica kao slike: +pdfToImage.single=Jedna velika slika koja sadrži sve stranice +pdfToImage.multi=Više slika, jedna slika po stranici +pdfToImage.colorType=Režim boja: +pdfToImage.color=Kolor +pdfToImage.grey=Monohromatski +pdfToImage.blackwhite=Crno-belo (Može izgubiti detalje!) +pdfToImage.submit=Konvertuj +pdfToImage.info=Python nije instaliran. Neophodan je za WebP konverziju. +pdfToImage.placeholder=(npr. 1,2,8 ili 4,7,12-16 ili 2n-1) + + +#addPassword +addPassword.title=Dodaj šifru +addPassword.header=Dodaj šifru (enkripcija) +addPassword.selectText.1=Izaberi PDF koji želiš da zaštitiš: +addPassword.selectText.2=Korisnička šifra: +addPassword.selectText.3=Dužina enkripcijskog ključa: +addPassword.selectText.4=Veće vrednosti su jače, ali manje vrednosti imaju bolju kompatibilnost. +addPassword.selectText.5=Postavke dozvola (preporučuje se korišćenje sa šifrom vlasnika): +addPassword.selectText.6=Onemogući sastavljanje dokumenta +addPassword.selectText.7=Onemogući ekstrakciju sadržaja +addPassword.selectText.8=Onemogući pristup alatima za pristupačnost +addPassword.selectText.9=Onemogući popunjavanje formulara +addPassword.selectText.10=Onemogući modifikaciju +addPassword.selectText.11=Onemogući modifikaciju beleški +addPassword.selectText.12=Onemogući štampanje +addPassword.selectText.13=Onemogući štampanje u različitim formatima +addPassword.selectText.14=Šifra vlasnika: +addPassword.selectText.15=Ograničava šta se može raditi sa dokumentom nakon otvaranja. (Nije podržano od strane svih čitača) +addPassword.selectText.16=Ograničava otvaranje samog dokumenta. +addPassword.submit=Enkriptuj + + +#watermark +watermark.title=Dodaj vodeni žig +watermark.header=Dodaj vodeni žig +watermark.customColor=Prilagođena boja teksta +watermark.selectText.1=Izaberi PDF za dodavanje vodenog žiga: +watermark.selectText.2=Tekst vodenog žiga: +watermark.selectText.3=Veličina fonta: +watermark.selectText.4=Rotacija (0-360): +watermark.selectText.5=Širina razmaka (razmak između svakog vodenog žiga horizontalno): +watermark.selectText.6=Visina razmaka (razmak između svakog vodenog žiga vertikalno): +watermark.selectText.7=Providnost (0% - 100%): +watermark.selectText.8=Tip vodenog žiga: +watermark.selectText.9=Slika vodenog žiga: +watermark.selectText.10=Konvertuj PDF u PDF-sliku +watermark.submit=Dodaj vodeni žig +watermark.type.1=Tekst +watermark.type.2=Slika + + +#Change permissions +permissions.title=Promeni dozvole +permissions.header=Promeni dozvole +permissions.warning=Napomena: Da bi ove dozvole učinili nepromenljivim, preporučuje se postavljanje šifre putem stranice za dodavanje šifre. +permissions.selectText.1=Izaberi PDF za promenu dozvola: +permissions.selectText.2=Postavke dozvola: +permissions.selectText.3=Onemogući sastavljanje dokumenta +permissions.selectText.4=Onemogući ekstrakciju sadržaja +permissions.selectText.5=Onemogući ekstrakciju alatima za pristupačnost +permissions.selectText.6=Onemogući popunjavanje formulara +permissions.selectText.7=Onemogući modifikaciju +permissions.selectText.8=Onemogući modifikaciju beleški +permissions.selectText.9=Onemogući štampanje +permissions.selectText.10=Onemogući štampanje u različitim formatima +permissions.submit=Promeni + + +#remove password +removePassword.title=Ukloni šifru +removePassword.header=Ukloni šifru (dekripcija) +removePassword.selectText.1=Izaberi PDF za dekripciju: +removePassword.selectText.2=Šifra: +removePassword.submit=Ukloni + + +#changeMetadata +changeMetadata.title=Naslov: +changeMetadata.header=Izmeni metapodatke +changeMetadata.selectText.1=Izmenite promenljive koje želite da izmenite: +changeMetadata.selectText.2=Obriši sve metapodatke +changeMetadata.selectText.3=Prikaži prilagođene metapodatke: +changeMetadata.author=Autor: +changeMetadata.creationDate=Datum kreiranja (gggg/MM/dd HH:mm:ss): +changeMetadata.creator=Kreator: +changeMetadata.keywords=Ključne reči: +changeMetadata.modDate=Datum izmene (gggg/MM/dd HH:mm:ss): +changeMetadata.producer=Program koji je kreirao dokument: +changeMetadata.subject=Tema: +changeMetadata.trapped=Primenjen trapping: +changeMetadata.selectText.4=Drugi metapodaci: +changeMetadata.selectText.5=Dodaj sopstveni metapodatak +changeMetadata.submit=Izmeni + +#unlockPDFForms +unlockPDFForms.title=Ukloni režim samo-za-čitanje sa polja obrasca +unlockPDFForms.header=Otključaj PDF obrazac +unlockPDFForms.submit=Otključaj + +#pdfToPDFA +pdfToPDFA.title=PDF u PDF/A +pdfToPDFA.header=PDF u PDF/A +pdfToPDFA.credit=Ova usluga koristi LibreOffice za konverziju u PDF/A format. +pdfToPDFA.submit=Konvertuj +pdfToPDFA.tip=Trenutno nije podržano za više unosa istovremeno +pdfToPDFA.outputFormat=Izlazni format: +pdfToPDFA.pdfWithDigitalSignature=PDF sadrži digitalni potpis. Biće uklonjen u sledećem koraku. + + +#PDFToWord +PDFToWord.title=PDF u Word +PDFToWord.header=PDF u Word +PDFToWord.selectText.1=Format izlazne datoteke: +PDFToWord.credit=Ova usluga koristi LibreOffice za konverziju datoteka. +PDFToWord.submit=Konvertuj + + +#PDFToPresentation +PDFToPresentation.title=PDF u prezentaciju +PDFToPresentation.header=PDF u prezentaciju +PDFToPresentation.selectText.1=Format izlazne datoteke: +PDFToPresentation.credit=Ova usluga koristi LibreOffice za konverziju datoteka. +PDFToPresentation.submit=Konvertuj + + +#PDFToText +PDFToText.title=PDF u RTF (Tekst) +PDFToText.header=PDF u RTF (Tekst) +PDFToText.selectText.1=Format izlazne datoteke: +PDFToText.credit=Ova usluga koristi LibreOffice za konverziju datoteka. +PDFToText.submit=Konvertuj + + +#PDFToHTML +PDFToHTML.title=PDF u HTML +PDFToHTML.header=PDF u HTML +PDFToHTML.credit=Ova usluga koristi pdftohtml za konverziju datoteka. +PDFToHTML.submit=Konvertuj + + +#PDFToXML +PDFToXML.title=PDF u XML +PDFToXML.header=PDF u XML +PDFToXML.credit=Ova usluga koristi LibreOffice za konverziju datoteka. +PDFToXML.submit=Konvertuj + +#PDFToCSV +PDFToCSV.title=PDF u CSV +PDFToCSV.header=PDF u CSV +PDFToCSV.prompt=Izaberi stranicu za ekstrakciju tabele +PDFToCSV.submit=Izvuci + +#split-by-size-or-count +split-by-size-or-count.title=Razdvoji PDF po veličini ili broju +split-by-size-or-count.header=Razdvoji PDF po veličini ili broju +split-by-size-or-count.type.label=Izaberi način razdvajanja: +split-by-size-or-count.type.size=Po veličini +split-by-size-or-count.type.pageCount=Po broju stranica +split-by-size-or-count.type.docCount=Po broju dokumenata +split-by-size-or-count.value.label=Unesi vrednost: +split-by-size-or-count.value.placeholder=Unesi veličinu (npr. 2MB ili 3KB) ili broj (npr. 5) +split-by-size-or-count.submit=Potvrdi + + +#overlay-pdfs +overlay-pdfs.header=Preklapanje PDF fajlova +overlay-pdfs.baseFile.label=Izaberi osnovnu PDF datoteku +overlay-pdfs.overlayFiles.label=Izaberi PDF datoteke za preklapanje: +overlay-pdfs.mode.label=Izaberi režim preklapanja: +overlay-pdfs.mode.sequential=Sekvencijalno preklapanje +overlay-pdfs.mode.interleaved=Naizmenično preklapanje +overlay-pdfs.mode.fixedRepeat=Fiksno ponovljeno preklapanje +overlay-pdfs.counts.label=Broj preklapanja (za režim Fiksno preklapanje) +overlay-pdfs.counts.placeholder=Unesi brojeve odvojene zarezom (npr. 2,3,1) +overlay-pdfs.position.label=Izaberi poziciju preklapanja: +overlay-pdfs.position.foreground=Prethodni plan +overlay-pdfs.position.background=Pozadina +overlay-pdfs.submit=Potvrdi + + +#split-by-sections +split-by-sections.title=Razdvoji PDF po sekcijama +split-by-sections.header=Razdvoji PDF po sekcijama +split-by-sections.horizontal.label=Horizontalne podele: +split-by-sections.vertical.label=Vertikalne podele: +split-by-sections.horizontal.placeholder=Unesi broj horizontalnih podela +split-by-sections.vertical.placeholder=Unesi broj vertikalnih podela +split-by-sections.submit=Razdvoji PDF +split-by-sections.merge=Spoji u jedan PDF + + +#printFile +printFile.title=Odštampaj datoteku +printFile.header=Odštampaj datoteku na štampaču +printFile.selectText.1=Izaberi datoteku za štampu +printFile.selectText.2=Unesi naziv štampača +printFile.submit=Štampaj + + +#licenses +licenses.nav=Licence +licenses.title=Licence trećih strana +licenses.header=Licence trećih strana +licenses.module=Modul +licenses.version=Verzija +licenses.license=Licenca + +#survey +survey.nav=Anketa +survey.title=Stirling-PDF anketa +survey.description=Stirling-PDF ne prati korisnike, zato želimo da čujemo tvoje utiske kako bismo unapredili Stirling-PDF! +survey.changes=Stirling-PDF se promenio od poslednje ankete! Za više informacija, pogledaj naš blog post ovde: +survey.changes2=Sa ovim promenama dobijamo plaćenu poslovnu podršku i finansiranje +survey.please=Molimo te da razmotriš učešće u našoj anketi! +survey.disabled=(Popup za anketu će biti onemogućen u narednim ažuriranjima, ali će ostati dostupan na dnu stranice) +survey.button=Popuni anketu +survey.dontShowAgain=Ne prikazuj ponovo +survey.meeting.1=Ako koristiš Stirling PDF na poslu, voleli bismo da razgovaramo sa tobom. Nudimo tehničke sesije podrške u zamenu za 15-minutni korisnički intervju. +survey.meeting.2=Ovo je prilika da: +survey.meeting.3=Dobiješ pomoć oko postavljanja, integracije ili rešavanja problema +survey.meeting.4=Pružiš direktne povratne informacije o performansama, specifičnim slučajevima i nedostacima funkcionalnosti +survey.meeting.5=Pomozi nam da unapredimo Stirling PDF za praktičnu upotrebu u preduzećima +survey.meeting.6=Ukoliko si zainteresov, možeš zakazati direktni termin sa našim timom. (Samo na engleskom jeziku) +survey.meeting.7=Radujemo se što ćemo detaljnije istražiti tvoje slučajeve korišćenja i učiniti Stirling PDF još boljim! +survey.meeting.notInterested=Nisi poslovni korisnik i/ili nisi zainteresovan za sastanak? +survey.meeting.button=Zakaži sastanak + +#error +error.sorry=Izvinjavamo se zbog problema! +error.needHelp=Potrebna pomoć / Naišli ste na problem? +error.contactTip=Ako i dalje imaš problema, ne oklevaj da nas kontaktiraš za pomoć. Možeš poslati prijavu na našoj GitHub stranici ili nas kontaktirati putem Discord-a: +error.404.head=404 – Stranica nije pronađena | Ups, sapleli smo se u kodu! +error.404.1=Izgleda da ne možemo da pronađemo stranicu koju tražiš. +error.404.2=Nešto nije u redu +error.github=Pošalji prijavu na GitHub-u +error.showStack=Prikaži trag greške (Stack Trace) +error.copyStack=Kopiraj trag greške (Stack Trace) +error.githubSubmit=GitHub - pošalji prijavu +error.discordSubmit=Discord - pošalji poruku za podršku + + +#remove-image +removeImage.title=Ukloni sliku +removeImage.header=Ukloni sliku +removeImage.removeImage=Ukloni sliku +removeImage.submit=Ukloni sliku + + +splitByChapters.title=Podeli PDF po poglavljima +splitByChapters.header=Podeli PDF po poglavljima +splitByChapters.bookmarkLevel=Nivo oznake u sadržaju: +splitByChapters.includeMetadata=Uključi metapodatke +splitByChapters.allowDuplicates=Dozvoli duplikate +splitByChapters.desc.1=Ovaj alat deli PDF fajl na više PDF-ova po osnovu strukture poglavlja. +splitByChapters.desc.2=Nivo oznake: Izaberite nivo oznaka koji će se koristiti za deljenje (0 za najviši nivo, 1 za drugi nivo, itd.). +splitByChapters.desc.3=Uključi metapodatke: Ako je označeno, metapodaci iz originalnog PDF-a biće uključeni u svaki podeljeni PDF. +splitByChapters.desc.4=Dozvoli duplikate: Ako je označeno, omogućava da više oznaka na istoj strani kreira odvojene PDF fajlove. +splitByChapters.submit=Podeli PDF + +#File Chooser +fileChooser.click=Klikni +fileChooser.or=ili +fileChooser.dragAndDrop=Prevuci i ispusti +fileChooser.dragAndDropPDF=Prevuci PDF datoteku +fileChooser.dragAndDropImage=Prevuci sliku +fileChooser.hoveredDragAndDrop=Prevuci datoteku/e ovde +fileChooser.extractPDF=Izvlačim... +fileChooser.addAttachments=prevuci priloge ovde + +#release notes +releases.footer=Izdanja +releases.title=Beleške o izdanju +releases.header=Beleške o izdanju +releases.current.version=Aktuelno izdanje +releases.note=Beleške o izdanju su dostupne samo na engleskom jeziku + +#Validate Signature +validateSignature.title=Verifikuj PDF potpise +validateSignature.header=Verifikuj digitalne potpise +validateSignature.selectPDF=Izaberi potpisanu PDF datoteku za proveru: +validateSignature.submit=Verifikuj potpise +validateSignature.results=Rezultati verifikacije: +validateSignature.status=Status +validateSignature.signer=Potpisnik +validateSignature.date=Datum +validateSignature.reason=Razlog +validateSignature.location=Lokacija +validateSignature.noSignatures=Digitalni potpisi nisu pronađeni u ovom dokumentu +validateSignature.status.valid=Validan +validateSignature.status.invalid=Invalidan +validateSignature.chain.invalid=Provera lanca sertifikata nije uspela – nije moguće potvrditi identitet potpisnika +validateSignature.trust.invalid=Sertifikat nije u skladištu poverenja – izvor nije moguće potvrditi +validateSignature.cert.expired=Sertifikat je istekao +validateSignature.cert.revoked=Sertifikat je opozvan +validateSignature.signature.info=Informacije o potpisu +validateSignature.signature=Potpis +validateSignature.signature.mathValid=Potpis je matematički validan ALI: +validateSignature.selectCustomCert=Prilagođena X.509 datoteka sertifikata (opciono) +validateSignature.cert.info=Detalji o sertifikatu: +validateSignature.cert.issuer=Izdavalac +validateSignature.cert.subject=Subjekat +validateSignature.cert.serialNumber=Serijski broj +validateSignature.cert.validFrom=Važi od +validateSignature.cert.validUntil=Važi do +validateSignature.cert.algorithm=Algoritam +validateSignature.cert.keySize=Veličina ključa +validateSignature.cert.version=Verzija +validateSignature.cert.keyUsage=Namena ključa +validateSignature.cert.selfSigned=Samopotpisan +validateSignature.cert.bits=bitova + +# Audit Dashboard +audit.dashboard.title=Nadzorna tabla za reviziju +audit.dashboard.systemStatus=Status sistema za reviziju +audit.dashboard.status=Status +audit.dashboard.enabled=Omogućen +audit.dashboard.disabled=Onemogućen +audit.dashboard.currentLevel=Trenutni nivo +audit.dashboard.retentionPeriod=Period čuvanja +audit.dashboard.days=dana +audit.dashboard.totalEvents=Ukupno događaja + +# Audit Dashboard Tabs +audit.dashboard.tab.dashboard=Kontrolna tabla +audit.dashboard.tab.events=Revizorski događaji +audit.dashboard.tab.export=Izvezi +# Dashboard Charts +audit.dashboard.eventsByType=Događaji po tipu +audit.dashboard.eventsByUser=Događaji po korisniku +audit.dashboard.eventsOverTime=Događaji tokom vremena +audit.dashboard.period.7days=7 dana +audit.dashboard.period.30days=30 dana +audit.dashboard.period.90days=90 dana + +# Events Tab +audit.dashboard.auditEvents=Revizorski događaji +audit.dashboard.filter.eventType=Tip događaja +audit.dashboard.filter.allEventTypes=Svi tipovi događaja +audit.dashboard.filter.user=Korisnik +audit.dashboard.filter.userPlaceholder=Filtriraj po korisniku +audit.dashboard.filter.startDate=Početni datum +audit.dashboard.filter.endDate=Završni datum +audit.dashboard.filter.apply=Primeni filtere +audit.dashboard.filter.reset=Poništi filtere + +# Table Headers +audit.dashboard.table.id=ID +audit.dashboard.table.time=Vreme +audit.dashboard.table.user=Korisnik +audit.dashboard.table.type=Tip +audit.dashboard.table.details=Detalji +audit.dashboard.table.viewDetails=Pogledaj detalje + +# Pagination +audit.dashboard.pagination.show=Prikaži +audit.dashboard.pagination.entries=stavke +audit.dashboard.pagination.pageInfo1=Strana +audit.dashboard.pagination.pageInfo2=od +audit.dashboard.pagination.totalRecords=Ukupno zapisa: + +# Modal +audit.dashboard.modal.eventDetails=Detalji događaja +audit.dashboard.modal.id=ID +audit.dashboard.modal.user=Korisnik +audit.dashboard.modal.type=Tip +audit.dashboard.modal.time=Vreme +audit.dashboard.modal.data=Datum + +# Export Tab +audit.dashboard.export.title=Izvoz revizorskih podataka +audit.dashboard.export.format=Format izvoza +audit.dashboard.export.csv=CSV (vrednosti odvojene zarezom) +audit.dashboard.export.json=JSON (JavaScript notacija objekata) +audit.dashboard.export.button=Izvezi podatke +audit.dashboard.export.infoTitle=Izvezi informacije +audit.dashboard.export.infoDesc1=Izvoz će obuhvatiti sve događaje revizije koji odgovaraju izabranim filterima. Za velike skupove podataka, izvoz može potrajati nekoliko trenutaka. +audit.dashboard.export.infoDesc2=Izvezeni podaci će sadržati: +audit.dashboard.export.infoItem1=ID događaja +audit.dashboard.export.infoItem2=Korisnik +audit.dashboard.export.infoItem3=Tip događaja +audit.dashboard.export.infoItem4=Vreme +audit.dashboard.export.infoItem5=Informacije o događaju + +# JavaScript i18n keys +audit.dashboard.js.noEventsFound=Nisu pronađeni događaji koji odgovaraju trenutnim filterima +audit.dashboard.js.errorLoading=Greška prilikom učitavanja podataka: +audit.dashboard.js.errorRendering=Greška prilikom generisanja tabele: +audit.dashboard.js.loadingPage=Učitavam stranicu + +#################### +# Cookie banner # +#################### +cookieBanner.popUp.title=Kako koristimo kolačiće +cookieBanner.popUp.description.1=Koristimo kolačiće i druge tehnologije kako bismo poboljšali rad Stirling PDF-a — pomažući nam da unapredimo naše alate i nastavimo da razvijamo funkcije koje ćete voleti. +cookieBanner.popUp.description.2=Ako to ne želite, klikom na 'Ne, hvala' biće omogućeni samo osnovni kolačići neophodni za nesmetan rad sistema. +cookieBanner.popUp.acceptAllBtn=U redu +cookieBanner.popUp.acceptNecessaryBtn=Ne, hvala +cookieBanner.popUp.showPreferencesBtn=Upravljaj podešavanjima +cookieBanner.preferencesModal.title=Centar za podešavanja saglasnoti +cookieBanner.preferencesModal.acceptAllBtn=Prihvati sve +cookieBanner.preferencesModal.acceptNecessaryBtn=Odbij sve +cookieBanner.preferencesModal.savePreferencesBtn=Sačuvaj podešavanja +cookieBanner.preferencesModal.closeIconLabel=Zatvori modal +cookieBanner.preferencesModal.serviceCounterLabel=Usluga|Usluge +cookieBanner.preferencesModal.subtitle=Korišćenje kolačića +cookieBanner.preferencesModal.description.1=Stirling PDF koristi kolačiće i slične tehnologije kako bi poboljšao vaše iskustvo i razumeo kako se naši alati koriste. Ovo nam pomaže da unapredimo performanse, razvijamo funkcije koje su vam važne i pružimo kontinuiranu podršku našim korisnicima. +cookieBanner.preferencesModal.description.2=Stirling PDF ne može — i nikada neće — pratiti ili pristupati sadržaju dokumenata koje koristite. +cookieBanner.preferencesModal.description.3=Vaša privatnost i poverenje su osnovni principi našeg rada. +cookieBanner.preferencesModal.necessary.title.1=Isključivo neophodni kolačići +cookieBanner.preferencesModal.necessary.title.2=Uvek omogućeno +cookieBanner.preferencesModal.necessary.description=Ovi kolačići su neophodni za pravilno funkcionisanje sajta. Omogućavaju osnovne funkcije kao što su podešavanje privatnosti, prijavljivanje i popunjavanje obrazaca — zato ih nije moguće isključiti. +cookieBanner.preferencesModal.analytics.title=Analitika +cookieBanner.preferencesModal.analytics.description=Ovi kolačići nam pomažu da razumemo kako se naši alati koriste, kako bismo mogli da se fokusiramo na razvoj funkcija koje naša zajednica najviše ceni. Budite sigurni — Stirling PDF ne može i nikada neće pratiti sadržaj dokumenata sa kojima radite. + +#fakeScan +fakeScan.title=Lažno skeniranje +fakeScan.header=Lažno skeniranje +fakeScan.description=Kreiraj PDF koji izgleda kao da je skeniran +fakeScan.selectPDF=Izaberi PDF: +fakeScan.quality=Kvalitet skeniranja: +fakeScan.quality.low=Nizak +fakeScan.quality.medium=Srednji +fakeScan.quality.high=Visok +fakeScan.rotation=Ugao rotiranja: +fakeScan.rotation.none=Nijedno +fakeScan.rotation.slight=Blago +fakeScan.rotation.moderate=Umereno +fakeScan.rotation.severe=Značajno +fakeScan.submit=Kreiraj lažno skeniranje + +#home.fakeScan +home.fakeScan.title=Lažno skeniranje +home.fakeScan.desc=Kreiraj PDF koji izgleda kao da je skeniran +fakeScan.tags=sken,simuliraj,realistično,konvertuj + +# FakeScan advanced settings (frontend) +fakeScan.advancedSettings=Omogući naprednja podešavanja za skeniranje +fakeScan.colorspace=Režim boja: +fakeScan.colorspace.grayscale=Monohromatski +fakeScan.colorspace.color=Kolor +fakeScan.border=Ivica (px) +fakeScan.rotate=Osnovni ugao rotacije (stepeni) +fakeScan.rotateVariance=Varijacija rotacije (stepeni) +fakeScan.brightness=Osvetljenje +fakeScan.contrast=Kontrast +fakeScan.blur=Zamućenje +fakeScan.noise=Buka +fakeScan.yellowish=Žutilo (simulacija starog papira) +fakeScan.resolution=Rezolucija (DPI) + + +# Table of Contents Feature +home.editTableOfContents.title=Izmeni sadržaj +home.editTableOfContents.desc=Dodaj ili izmeni obeleživače i sadržaj u PDF dokumentima + +editTableOfContents.tags=obeleživači,sadržaj,navigacija,indeks,poglavlja,sekcije,raspored +editTableOfContents.title=Izmeni sadržaj +editTableOfContents.header=Dodaj ili izmeni sadržaj PDF dokumenta +editTableOfContents.replaceExisting=Zameni postojeće obeleživače (isključi da bi se dodali na postojeće) +editTableOfContents.editorTitle=Editor obeleživača +editTableOfContents.editorDesc=Dodaj i rasporedi obeleživače ispod. Klikni + za dodavanje podređenih obeleživača. +editTableOfContents.addBookmark=Dodaj novi obeleživač +editTableOfContents.desc.1=Ovaj alat omogućava dodavanje ili izmenu sadržaja (obeleživača) u PDF dokumentu. +editTableOfContents.desc.2=Moguće je kreirati hijerarhijsku strukturu dodavanjem podređenih obeleživača nadređenim obeleživačima. +editTableOfContents.desc.3=Svaki obeleživač zahteva naslov i broj ciljne strane. +editTableOfContents.submit=Potvrdi diff --git a/stirling-pdf/src/main/resources/messages_sv_SE.properties b/app/core/src/main/resources/messages_sv_SE.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_sv_SE.properties rename to app/core/src/main/resources/messages_sv_SE.properties index 2a7a65438..1b05a7b05 100644 --- a/stirling-pdf/src/main/resources/messages_sv_SE.properties +++ b/app/core/src/main/resources/messages_sv_SE.properties @@ -163,13 +163,74 @@ alphabet=Alfabet downloadPdf=Ladda ner PDF text=Text font=Teckensnitt -selectFillter=-- Välj -- +selectFilter=-- Välj -- pageNum=Sidnummer sizes.small=Liten sizes.medium=Mellan sizes.large=Stor sizes.x-large=Extra stor error.pdfPassword=PDF-dokumentet är lösenordsskyddat och antingen har lösenordet inte angetts eller är felaktigt +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Radera username=Användarnamn password=Lösenord @@ -181,7 +242,6 @@ red=Röd green=Grön blue=Blå custom=Anpassad... -WorkInProgess=Pågående arbete, kan vara icke fungerande eller buggigt. Rapportera eventuella problem! poweredBy=Drivs av yes=Ja no=Nej @@ -525,6 +585,10 @@ home.addImage.title=Lägg till bild home.addImage.desc=Lägger till en bild på en angiven plats i PDF:en (pågår arbete) addImage.tags=img,jpg,bild,foto +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Lägg till vattenstämpel home.watermark.desc=Lägg till en anpassad vattenstämpel till ditt PDF-dokument. watermark.tags=Text,upprepande,etikett,egen,upphovsrätt,varumärke,img,jpg,bild,foto @@ -1205,6 +1269,12 @@ addImage.everyPage=Varje sida? addImage.upload=Lägg till bild addImage.submit=Lägg till bild +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Sammanfoga @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Dra & Släpp PDF fil fileChooser.dragAndDropImage=Dra & Släpp bildfil fileChooser.hoveredDragAndDrop=Dra & Släpp fil(er) här fileChooser.extractPDF=Extraherar... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Utgåvor diff --git a/stirling-pdf/src/main/resources/messages_th_TH.properties b/app/core/src/main/resources/messages_th_TH.properties similarity index 96% rename from stirling-pdf/src/main/resources/messages_th_TH.properties rename to app/core/src/main/resources/messages_th_TH.properties index 95b0f7d0f..094bf6632 100644 --- a/stirling-pdf/src/main/resources/messages_th_TH.properties +++ b/app/core/src/main/resources/messages_th_TH.properties @@ -163,13 +163,74 @@ alphabet=ตัวอักษร downloadPdf=ดาวน์โหลด PDF text=ข้อความ font=ฟอนต์ -selectFillter=-- เลือก -- +selectFilter=-- เลือก -- pageNum=หมายเลขหน้า sizes.small=เล็ก sizes.medium=กลาง sizes.large=ใหญ่ sizes.x-large=ใหญ่มาก error.pdfPassword=เอกสาร PDF มีรหัสผ่าน และไม่ได้ระบุรหัสผ่านหรือรหัสผ่านไม่ถูกต้อง +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=ลบ username=ชื่อผู้ใช้ password=รหัสผ่าน @@ -181,7 +242,6 @@ red=แดง green=เขียว blue=น้ำเงิน custom=ปรับแต่ง... -WorkInProgess=กำลังดำเนินการ อาจไม่ทำงานหรือมีบั๊ก โปรดรายงานปัญหาใด ๆ! poweredBy=ขับเคลื่อนโดย yes=ใช่ no=ไม่ @@ -525,6 +585,10 @@ home.addImage.title=เพิ่มรูปภาพ home.addImage.desc=เพิ่มรูปภาพไปยังตำแหน่งที่กำหนดใน PDF addImage.tags=รูปภาพ, JPG, ภาพ, รูปถ่าย +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=เพิ่มลายน้ำ home.watermark.desc=เพิ่มลายน้ำที่กำหนดเองลงในเอกสาร PDF ของคุณ watermark.tags=ข้อความ, ซ้ำ, ป้าย, ของคุณเอง, ลิขสิทธิ์, เครื่องหมายการค้า, รูปภาพ, JPG, ภาพ, รูปถ่าย @@ -1205,6 +1269,12 @@ addImage.everyPage=ทุกหน้า? addImage.upload=เพิ่มรูปภาพ addImage.submit=เพิ่มรูปภาพ +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=รวม @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_tr_TR.properties b/app/core/src/main/resources/messages_tr_TR.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_tr_TR.properties rename to app/core/src/main/resources/messages_tr_TR.properties index 5be4d62a3..5a16196cd 100644 --- a/stirling-pdf/src/main/resources/messages_tr_TR.properties +++ b/app/core/src/main/resources/messages_tr_TR.properties @@ -163,13 +163,74 @@ alphabet=Alfabe downloadPdf=PDF İndir text=Metin font=Yazı tipi -selectFillter=-- Seçiniz -- +selectFilter=-- Seçiniz -- pageNum=Sayfa Numarası sizes.small=Küçük sizes.medium=Orta sizes.large=Büyük sizes.x-large=Çok Büyük error.pdfPassword=PDF belgesi şifreli ve şifre ya sağlanmadı ya da yanlış. +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Sil username=Kullanıcı Adı password=Parola @@ -181,7 +242,6 @@ red=Kırmızı green=Yeşil blue=Mavi custom=Özel -WorkInProgess=Çalışmalar devam ediyor, Çalışmayabilir veya hatalı olabilir, Lütfen herhangi bir sorunu bildirin! poweredBy=Tarafından desteklenmektedir yes=Evet no=Hayır @@ -525,6 +585,10 @@ home.addImage.title=Resim Ekle home.addImage.desc=PDF'e belirli bir konuma resim ekler addImage.tags=img,jpg,fotoğraf,resim +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Filigran Ekle home.watermark.desc=PDF belgenize özel bir filigran ekleyin. watermark.tags=Metin,tekrarlayan,etiket,kendi,telif hakkı,marka,img,jpg,fotoğraf,resim @@ -1205,6 +1269,12 @@ addImage.everyPage=Her Sayfa mı? addImage.upload=Resim ekle addImage.submit=Resim ekle +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Birleştir @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=PDF dosyasını Sürükle & Bırak fileChooser.dragAndDropImage=Görsel dosyasını Sürükle & Bırak fileChooser.hoveredDragAndDrop=Dosya(lar)ı buraya sürükleyip bırakın fileChooser.extractPDF=PDF Çıkarılıyor... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Sürümler diff --git a/stirling-pdf/src/main/resources/messages_uk_UA.properties b/app/core/src/main/resources/messages_uk_UA.properties similarity index 95% rename from stirling-pdf/src/main/resources/messages_uk_UA.properties rename to app/core/src/main/resources/messages_uk_UA.properties index bbd46cfc8..1389189d2 100644 --- a/stirling-pdf/src/main/resources/messages_uk_UA.properties +++ b/app/core/src/main/resources/messages_uk_UA.properties @@ -163,13 +163,74 @@ alphabet=Алфавіт downloadPdf=Завантажити PDF text=Текст font=Шрифт -selectFillter=-- Вибрати -- +selectFilter=-- Вибрати -- pageNum=номер сторінки sizes.small=Малий sizes.medium=Середній sizes.large=Великий sizes.x-large=Дуже великий error.pdfPassword=Документ PDF захищено паролем, і пароль не був наданий або був невірним +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Видалити username=Ім'я користувача password=Пароль @@ -181,7 +242,6 @@ red=Червоний green=Зелений blue=Синій custom=Звичай... -WorkInProgess=Робота триває, може не працювати або глючити, будь ласка, повідомляйте про будь-які проблеми! poweredBy=Працює на yes=Так no=Ні @@ -525,6 +585,10 @@ home.addImage.title=Додати зображення home.addImage.desc=Додає зображення у вказане місце в PDF (в розробці) addImage.tags=зображення,jpg,картинка,фото +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Додати водяний знак home.watermark.desc=Додайте свій водяний знак до документа PDF. watermark.tags=текст,повторний,мітка,власний,авторське право,торговельна марка,зображення,jpg,картинка,фото @@ -1205,6 +1269,12 @@ addImage.everyPage=Кожна сторінка? addImage.upload=Додати зображення addImage.submit=Додати зображення +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Об'єднати @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Перетащите PDF-файл fileChooser.dragAndDropImage=Перетащите файл зображення fileChooser.hoveredDragAndDrop=Перетащите файл(и) сюда fileChooser.extractPDF=Видобування... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Релізи diff --git a/stirling-pdf/src/main/resources/messages_vi_VN.properties b/app/core/src/main/resources/messages_vi_VN.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_vi_VN.properties rename to app/core/src/main/resources/messages_vi_VN.properties index 951b706e7..e7aa8b568 100644 --- a/stirling-pdf/src/main/resources/messages_vi_VN.properties +++ b/app/core/src/main/resources/messages_vi_VN.properties @@ -163,13 +163,74 @@ alphabet=Bảng chữ cái downloadPdf=Tải xuống PDF text=Văn bản font=Phông chữ -selectFillter=-- Chọn -- +selectFilter=-- Chọn -- pageNum=Số trang sizes.small=Nhỏ sizes.medium=Trung bình sizes.large=Lớn sizes.x-large=Rất lớn error.pdfPassword=Tài liệu PDF được bảo vệ bằng mật khẩu và mật khẩu không được cung cấp hoặc không chính xác +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=Xóa username=Tên người dùng password=Mật khẩu @@ -181,7 +242,6 @@ red=Đỏ green=Xanh lá blue=Xanh dương custom=Tùy chỉnh... -WorkInProgess=Đang trong quá trình phát triển, Có thể không hoạt động hoặc có lỗi, Vui lòng báo cáo mọi vấn đề! poweredBy=Được hỗ trợ bởi yes=Có no=Không @@ -525,6 +585,10 @@ home.addImage.title=Thêm hình ảnh home.addImage.desc=Thêm hình ảnh vào vị trí cố định trên PDF addImage.tags=img,jpg,hình ảnh,ảnh +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=Thêm hình mờ home.watermark.desc=Thêm hình mờ tùy chỉnh vào tài liệu PDF của bạn. watermark.tags=Văn bản,lặp lại,nhãn,riêng,bản quyền,thương hiệu,img,jpg,hình ảnh,ảnh @@ -1205,6 +1269,12 @@ addImage.everyPage=Mọi trang? addImage.upload=Thêm hình ảnh addImage.submit=Thêm hình ảnh +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=Trộn @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=Drag & Drop PDF file fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here fileChooser.extractPDF=Extracting... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=Releases diff --git a/stirling-pdf/src/main/resources/messages_zh_CN.properties b/app/core/src/main/resources/messages_zh_CN.properties similarity index 92% rename from stirling-pdf/src/main/resources/messages_zh_CN.properties rename to app/core/src/main/resources/messages_zh_CN.properties index 07c10e561..8dba289a2 100644 --- a/stirling-pdf/src/main/resources/messages_zh_CN.properties +++ b/app/core/src/main/resources/messages_zh_CN.properties @@ -163,13 +163,74 @@ alphabet=字母表 downloadPdf=下载 PDF text=文本 font=字体 -selectFillter=-- 选择-- +selectFilter=-- 选择-- pageNum=页码 sizes.small=小型尺寸 sizes.medium=中型尺寸 sizes.large=大型尺寸 sizes.x-large=超大型尺寸 error.pdfPassword=PDF文档有密码,未提供密码或密码不正确 +error.pdfCorrupted=PDF文件似乎已损坏或损坏。在继续此操作之前,请先尝试使用“修复PDF”功能修复文件。 +error.pdfCorruptedMultiple=一个或多个PDF文件似乎已损坏或损坏。请先对单个文件使用“修复PDF”功能,然后再尝试合并它们。 +error.pdfCorruptedDuring=错误 {0} :PDF文件似乎已损坏或损坏。在继续此操作之前,请先尝试使用“修复PDF”功能修复文件。 + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} 未被安装 +error.toolRequired={1} 依赖于 {0} +error.conversionFailed={0} 转换失败 +error.commandFailed={0} 执行命令失败 +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=该端点被管理员禁用 +error.urlNotReachable=URL无法访问,请提供有效的URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI值 {0} 超过 {1} 的最大安全限值。高DPI值可能导致内存溢出或崩溃。请尝试较低的DPI值。 +error.pageTooBigForDpi=PDF页面 {0} 太大,无法以 {1} DPI呈现。请尝试较低的DPI值(建议:150或更低)。 +error.pageTooBigExceedsArray=PDF页面 {0} 太大,无法以 {1} DPI呈现。生成的图像将超过Java的最大数组大小。请尝试较低的DPI值(建议:150或更低)。 +error.pageTooBigFor300Dpi=PDF页面 {0} 太大,无法以300 DPI呈现。生成的图像将超过Java的最大数组大小。请使用较低的DPI值进行pdf到图像的转换。 + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API秘钥无效。 +error.userNotFound=用户未找到。 +error.passwordRequired=密码不应为空。 +error.accountLocked=由于过多的失败登录尝试,你的账户被锁定。 +error.invalidEmail=提供了无效的电子邮件地址。 +error.emailAttachmentRequired=发送该电子邮件需要附件。 +error.signatureNotFound=证书文件未找到。 + +# File processing messages +error.fileNotFound=具有此ID的文件未找到: {0} + +# Database and configuration messages +error.noBackupScripts=未找到备份脚本。 +error.unsupportedProvider={0} 当前不被支持。 +error.pathTraversalDetected=检测到存在安全问题的路径遍历操作。 + +# Validation messages +error.invalidArgument=不合法的参数: {0} +error.argumentRequired={0} 不应当为空 +error.operationFailed=操作失败: {0} +error.angleNotMultipleOf90=角度应当为90°的倍数 +error.pdfBookmarksNotFound=文档中没有找到PDF书签/大纲 +error.fontLoadingFailed=处理字体文件出错 +error.fontDirectoryReadFailed=无法读取字体目录 delete=删除 username=用户名 password=密码 @@ -181,7 +242,6 @@ red=红色 green=绿色 blue=蓝色 custom=自定义... -WorkInProgess=工作正在进行中,可能无法工作或有错误,请报告任何问题! poweredBy=服务来源: yes=是 no=否 @@ -200,7 +260,7 @@ disabledCurrentUserMessage=无法禁用当前用户。 downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。 userAlreadyExistsOAuthMessage=该用户已作为 OAuth2 用户存在。 userAlreadyExistsWebMessage=该用户已作为 Web 用户存在。 -invalidRoleMessage=Invalid role. +invalidRoleMessage=无效角色。 error=错误 oops=哎呀! help=帮助 @@ -212,8 +272,8 @@ donate=捐款 color=颜色 sponsor=赞助 info=信息 -pro=专业版 -proFeatures=Pro Features +pro=Pro版本 +proFeatures=Pro版本功能 page=页面 pages=页码 loading=加载中... @@ -221,11 +281,11 @@ addToDoc=添加至文件 reset=重置 apply=应用 noFileSelected=未选择文件,请上传一个文件。 -view=View -cancel=Cancel +view=预览 +cancel=取消 -back.toSettings=Back to Settings -back.toHome=Back to Home +back.toSettings=回到设置 +back.toHome=回到主页 back.toAdmin=Back to Admin legal.privacy=隐私政策 @@ -390,17 +450,17 @@ adminUserSettings.teamName=团队名称 adminUserSettings.teamExists=该团队已存在 adminUserSettings.teamCreated=团队成功创建 adminUserSettings.teamChanged=用户所属团队已更新 -adminUserSettings.teamHidden=Hidden +adminUserSettings.teamHidden=隐藏 adminUserSettings.totalMembers=成员总数 adminUserSettings.confirmDeleteTeam=您确定要删除此团队吗? -teamCreated=Team created successfully -teamExists=A team with that name already exists -teamNameExists=Another team with that name already exists -teamNotFound=Team not found -teamDeleted=Team deleted -teamHasUsers=Cannot delete a team with users assigned -teamRenamed=Team renamed successfully +teamCreated=团队创建成功 +teamExists=同名称的团队已存在 +teamNameExists=同名称的团队已存在 +teamNotFound=未找到团队 +teamDeleted=团队被删除 +teamHasUsers=不能删除已经被分配用户的团队 +teamRenamed=团队重命名成功 # Team user management team.addUser=添加用户到团队 @@ -412,16 +472,16 @@ team.back=返回团队列表 team.internal=内部团队 team.internalTeamNotAccessible=内部团队为系统预设,无法访问 team.cannotMoveInternalUsers=内部团队中的用户无法转移至其他团队 -team.hidden=Hidden -team.name=Team Name -team.totalMembers=Total Members -team.members=Members -team.username=Username -team.role=Role -team.status=Status -team.enabled=Enabled -team.disabled=Disabled -team.noMembers=This team has no members yet. +team.hidden=隐藏 +team.name=团队名称 +team.totalMembers=总人数 +team.members=成员 +team.username=用户名 +team.role=角色 +team.status=状态 +team.enabled=启用 +team.disabled=禁用 +team.noMembers=这个团队还没有成员。 @@ -525,6 +585,10 @@ home.addImage.title=在 PDF 中添加图片 home.addImage.desc=将图像添加到 PDF 的指定位置。 addImage.tags=图像、JPG、图片、照片 +home.attachments.title=添加附件 +home.attachments.desc=在 PDF 中添加或删除嵌入文件(附件) +attachments.tags=嵌入、附件、文件、附加 + home.watermark.title=添加水印 home.watermark.desc=在 PDF 中添加自定义水印。 watermark.tags=文本、重复、标签、自定义、版权、商标、图像、JPG、图片、照片 @@ -660,8 +724,8 @@ home.crop.desc=裁剪 PDF 以减小其文件大小(保留文本!) crop.tags=修剪、缩小、编辑、形状 home.autoSplitPDF.title=自动拆分页面 -home.autoSplitPDF.desc=使用物理扫描页面分割器 QR 代码自动拆分扫描的 PDF -autoSplitPDF.tags=基于 QR 码、分离、扫描分割、整理 +home.autoSplitPDF.desc=使用物理扫描页面分割器二维码自动拆分扫描的 PDF +autoSplitPDF.tags=基于二维码、分离、扫描分割、整理 home.sanitizePdf.title=清理 home.sanitizePdf.desc=从 PDF 文件中删除脚本和其他元素 @@ -767,11 +831,11 @@ validateSignature.tags=签名,验证,验证,PDF,证书,数字签名, replace-color.title=替换-反转-颜色 replace-color.header=替换-反转 PDF 颜色 home.replaceColorPdf.title=替换和反转颜色 -home.replaceColorPdf.desc=替换 PDF 中文本和背景的颜色,并将PDF全色反转以减小文件大小 +home.replaceColorPdf.desc=替换 PDF 中文本和背景的颜色,并将PDF反转颜色以减小文件大小 replaceColorPdf.tags=更换颜色,页面操作,后端,服务器端 replace-color.selectText.1=替换或反转颜色选项 replace-color.selectText.2=默认(默认高对比度颜色) -replace-color.selectText.3=定制(定制的颜色) +replace-color.selectText.3=定制(定制的颜色) replace-color.selectText.4=全反转(反转所有颜色) replace-color.selectText.5=高对比度颜色选项 replace-color.selectText.6=黑底白字 @@ -1205,6 +1269,12 @@ addImage.everyPage=每一页? addImage.upload=添加图片 addImage.submit=添加图片 +#attachments +attachments.title=添加附件 +attachments.header=添加附件 +attachments.description=允许您向PDF添加附件 +attachments.descriptionPlaceholder=为附件输入描述… +attachments.addButton=添加附件 #merge merge.title=合并 @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=拖放PDF文件 fileChooser.dragAndDropImage=拖放图片文件 fileChooser.hoveredDragAndDrop=拖放文件到此处 fileChooser.extractPDF=处理中... +fileChooser.addAttachments=拖放附件到此处 #release notes releases.footer=版本 @@ -1651,14 +1722,14 @@ audit.dashboard.totalEvents=Total Events # Audit Dashboard Tabs audit.dashboard.tab.dashboard=Dashboard audit.dashboard.tab.events=Audit Events -audit.dashboard.tab.export=Export +audit.dashboard.tab.export=导出 # Dashboard Charts audit.dashboard.eventsByType=Events by Type audit.dashboard.eventsByUser=Events by User audit.dashboard.eventsOverTime=Events Over Time -audit.dashboard.period.7days=7 Days -audit.dashboard.period.30days=30 Days -audit.dashboard.period.90days=90 Days +audit.dashboard.period.7days=7天 +audit.dashboard.period.30days=30天 +audit.dashboard.period.90days=90天 # Events Tab audit.dashboard.auditEvents=Audit Events @@ -1673,11 +1744,11 @@ audit.dashboard.filter.reset=Reset Filters # Table Headers audit.dashboard.table.id=ID -audit.dashboard.table.time=Time -audit.dashboard.table.user=User -audit.dashboard.table.type=Type -audit.dashboard.table.details=Details -audit.dashboard.table.viewDetails=View Details +audit.dashboard.table.time=时间 +audit.dashboard.table.user=用户 +audit.dashboard.table.type=类型 +audit.dashboard.table.details=详情 +audit.dashboard.table.viewDetails=查看详情 # Pagination audit.dashboard.pagination.show=Show diff --git a/stirling-pdf/src/main/resources/messages_zh_TW.properties b/app/core/src/main/resources/messages_zh_TW.properties similarity index 94% rename from stirling-pdf/src/main/resources/messages_zh_TW.properties rename to app/core/src/main/resources/messages_zh_TW.properties index 927e7c037..7ef8b99f4 100644 --- a/stirling-pdf/src/main/resources/messages_zh_TW.properties +++ b/app/core/src/main/resources/messages_zh_TW.properties @@ -163,13 +163,74 @@ alphabet=字母表 downloadPdf=下載 PDF text=文字 font=字型 -selectFillter=-- 選擇 -- +selectFilter=-- 選擇 -- pageNum=頁碼 sizes.small=小 sizes.medium=中 sizes.large=大 sizes.x-large=特大 error.pdfPassword=PDF 檔案已加密,但未提供密碼或密碼不正確 +error.pdfCorrupted=PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. +error.pdfCorruptedMultiple=One or more PDF files appear to be corrupted or damaged. Please try using the 'Repair PDF' feature on each file first before attempting to merge them. +error.pdfCorruptedDuring=Error {0}: PDF file appears to be corrupted or damaged. Please try using the 'Repair PDF' feature first to fix the file before proceeding with this operation. + +# Frontend corruption error messages +error.pdfInvalid=The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the 'Repair PDF' feature to fix the file before proceeding. +error.tryRepair=Try using the Repair PDF feature to fix corrupted files. + +# Additional error messages +error.pdfEncryption=The PDF appears to have corrupted encryption data. This can happen when the PDF was created with incompatible encryption methods. Please try using the 'Repair PDF' feature first, or contact the document creator for a new copy. +error.fileProcessing=An error occurred while processing the file during {0} operation: {1} + +# Generic error message templates +error.toolNotInstalled={0} is not installed +error.toolRequired={0} is required for {1} +error.conversionFailed={0} conversion failed +error.commandFailed={0} command failed +error.algorithmNotAvailable={0} algorithm not available +error.optionsNotSpecified={0} options are not specified +error.fileFormatRequired=File must be in {0} format +error.invalidFormat=Invalid {0} format: {1} +error.endpointDisabled=This endpoint has been disabled by the admin +error.urlNotReachable=URL is not reachable, please provide a valid URL + +# DPI and image rendering messages - used by frontend for dynamic translation +# Backend sends: [TRANSLATE:messageKey:arg1,arg2] English message +# Frontend parses this and replaces with localized versions using these keys +error.dpiExceedsLimit=DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value. +error.pageTooBigForDpi=PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigExceedsArray=PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less). +error.pageTooBigFor300Dpi=PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion. + +# URL and website conversion messages + +# System requirements messages + +# Authentication and security messages +error.apiKeyInvalid=API key is not valid. +error.userNotFound=User not found. +error.passwordRequired=Password must not be null. +error.accountLocked=Your account has been locked due to too many failed login attempts. +error.invalidEmail=Invalid email addresses provided. +error.emailAttachmentRequired=An attachment is required to send the email. +error.signatureNotFound=Signature file not found. + +# File processing messages +error.fileNotFound=File not found with ID: {0} + +# Database and configuration messages +error.noBackupScripts=No backup scripts were found. +error.unsupportedProvider={0} is not currently supported. +error.pathTraversalDetected=Path traversal detected for security reasons. + +# Validation messages +error.invalidArgument=Invalid argument: {0} +error.argumentRequired={0} must not be null +error.operationFailed=Operation failed: {0} +error.angleNotMultipleOf90=Angle must be a multiple of 90 +error.pdfBookmarksNotFound=No PDF bookmarks/outline found in document +error.fontLoadingFailed=Error processing font file +error.fontDirectoryReadFailed=Failed to read font directory delete=刪除 username=使用者名稱 password=密碼 @@ -181,7 +242,6 @@ red=紅色 green=綠色 blue=藍色 custom=自訂... -WorkInProgess=工作正在進行中,可能無法工作或有問題,請報告任何問題! poweredBy=Powered by yes=是 no=否 @@ -525,6 +585,10 @@ home.addImage.title=新增圖片 home.addImage.desc=在 PDF 的指定位置新增圖片 addImage.tags=img,jpg,圖片,照片 +home.attachments.title=Add Attachments +home.attachments.desc=Add or remove embedded files (attachments) to/from a PDF +attachments.tags=embed,attach,file,attachment,attachments + home.watermark.title=新增浮水印 home.watermark.desc=在您的 PDF 檔案中新增自訂浮水印。 watermark.tags=文字,重複,標籤,自有,版權,商標,img,jpg,圖片,照片 @@ -1205,6 +1269,12 @@ addImage.everyPage=每一頁? addImage.upload=新增圖片 addImage.submit=新增圖片 +#attachments +attachments.title=Add Attachments +attachments.header=Add attachments +attachments.description=Allows you to add attachments to the PDF +attachments.descriptionPlaceholder=Enter a description for the attachments... +attachments.addButton=Add Attachments #merge merge.title=合併 @@ -1594,6 +1664,7 @@ fileChooser.dragAndDropPDF=拖放 PDF 檔案 fileChooser.dragAndDropImage=拖放圖片檔案 fileChooser.hoveredDragAndDrop=將檔案拖放至此 fileChooser.extractPDF=處理中... +fileChooser.addAttachments=drag & drop attachments here #release notes releases.footer=版本資訊 diff --git a/stirling-pdf/src/main/resources/settings.yml.template b/app/core/src/main/resources/settings.yml.template similarity index 95% rename from stirling-pdf/src/main/resources/settings.yml.template rename to app/core/src/main/resources/settings.yml.template index d45b8482b..a26f256f7 100644 --- a/stirling-pdf/src/main/resources/settings.yml.template +++ b/app/core/src/main/resources/settings.yml.template @@ -62,7 +62,7 @@ security: premium: key: 00000000-0000-0000-0000-000000000000 - enabled: true # Enable license key checks for pro/enterprise features + enabled: false # Enable license key checks for pro/enterprise features proFeatures: database: true # Enable database features SSOAutoLogin: false @@ -119,15 +119,15 @@ system: name: postgres # set the name of your database. Should match the name of the database you create customPaths: pipeline: - watchedFoldersDir: '' #Defaults to /pipeline/watchedFolders - finishedFoldersDir: '' #Defaults to /pipeline/finishedFolders + watchedFoldersDir: '' # Defaults to /pipeline/watchedFolders + finishedFoldersDir: '' # Defaults to /pipeline/finishedFolders operations: - weasyprint: '' #Defaults to /opt/venv/bin/weasyprint - unoconvert: '' #Defaults to /opt/venv/bin/unoconvert + weasyprint: '' # Defaults to /opt/venv/bin/weasyprint + unoconvert: '' # Defaults to /opt/venv/bin/unoconvert fileUploadLimit: '' # Defaults to "". No limit when string is empty. Set a number, between 0 and 999, followed by one of the following strings to set a limit. "KB", "MB", "GB". tempFileManagement: baseTmpDir: '' # Defaults to java.io.tmpdir/stirling-pdf - libreofficeDir: '' # Defaults to tempFileManagement.baseTmpDir/libreoffice + libreofficeDir: '' # Defaults to tempFileManagement.baseTmpDir/libreoffice systemTempDir: '' # Only used if cleanupSystemTemp is true prefix: stirling-pdf- # Prefix for temp file names maxAgeHours: 24 # Maximum age in hours before temp files are cleaned up @@ -164,6 +164,8 @@ processExecutor: weasyPrintSessionLimit: 16 installAppSessionLimit: 1 calibreSessionLimit: 1 + ghostscriptSessionLimit: 8 + ocrMyPdfSessionLimit: 2 timeoutMinutes: # Process executor timeout in minutes libreOfficetimeoutMinutes: 30 pdfToHtmltimeoutMinutes: 20 @@ -172,3 +174,6 @@ processExecutor: installApptimeoutMinutes: 60 calibretimeoutMinutes: 30 tesseractTimeoutMinutes: 30 + qpdfTimeoutMinutes: 30 + ghostscriptTimeoutMinutes: 30 + ocrMyPdfTimeoutMinutes: 30 diff --git a/stirling-pdf/src/main/resources/static/3rdPartyLicenses.json b/app/core/src/main/resources/static/3rdPartyLicenses.json similarity index 93% rename from stirling-pdf/src/main/resources/static/3rdPartyLicenses.json rename to app/core/src/main/resources/static/3rdPartyLicenses.json index 1c251a10d..440cdb265 100644 --- a/stirling-pdf/src/main/resources/static/3rdPartyLicenses.json +++ b/app/core/src/main/resources/static/3rdPartyLicenses.json @@ -165,12 +165,6 @@ "moduleLicense": "Apache-2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" }, - { - "moduleName": "com.google.errorprone:error_prone_annotations", - "moduleVersion": "2.11.0", - "moduleLicense": "Apache 2.0", - "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" - }, { "moduleName": "com.google.errorprone:error_prone_annotations", "moduleUrl": "https://errorprone.info/error_prone_annotations", @@ -283,7 +277,7 @@ { "moduleName": "com.opencsv:opencsv", "moduleUrl": "http://opencsv.sf.net", - "moduleVersion": "5.11.1", + "moduleVersion": "5.11.2", "moduleLicense": "Apache 2", "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, @@ -642,42 +636,21 @@ { "moduleName": "io.swagger.core.v3:swagger-annotations-jakarta", "moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-annotations", - "moduleVersion": "2.2.30", - "moduleLicense": "Apache License, Version 2.0", - "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" - }, - { - "moduleName": "io.swagger.core.v3:swagger-annotations-jakarta", - "moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-annotations", - "moduleVersion": "2.2.33", + "moduleVersion": "2.2.34", "moduleLicense": "Apache License, Version 2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" }, { "moduleName": "io.swagger.core.v3:swagger-core-jakarta", "moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-core", - "moduleVersion": "2.2.30", - "moduleLicense": "Apache License, Version 2.0", - "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" - }, - { - "moduleName": "io.swagger.core.v3:swagger-core-jakarta", - "moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-core", - "moduleVersion": "2.2.33", + "moduleVersion": "2.2.34", "moduleLicense": "Apache License, Version 2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" }, { "moduleName": "io.swagger.core.v3:swagger-models-jakarta", "moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-models", - "moduleVersion": "2.2.30", - "moduleLicense": "Apache License, Version 2.0", - "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" - }, - { - "moduleName": "io.swagger.core.v3:swagger-models-jakarta", - "moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-models", - "moduleVersion": "2.2.33", + "moduleVersion": "2.2.34", "moduleLicense": "Apache License, Version 2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" }, @@ -744,13 +717,6 @@ "moduleLicense": "GPL2 w/ CPE", "moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html" }, - { - "moduleName": "jakarta.servlet:jakarta.servlet-api", - "moduleUrl": "https://www.eclipse.org", - "moduleVersion": "6.1.0", - "moduleLicense": "GPL2 w/ CPE", - "moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html" - }, { "moduleName": "jakarta.transaction:jakarta.transaction-api", "moduleUrl": "https://projects.eclipse.org/projects/ee4j.jta", @@ -800,13 +766,6 @@ "moduleLicense": "GPL2 w/ CPE", "moduleLicenseUrl": "https://oss.oracle.com/licenses/CDDL+GPL-1.1" }, - { - "moduleName": "junit:junit", - "moduleUrl": "http://junit.org", - "moduleVersion": "4.13.2", - "moduleLicense": "Eclipse Public License 1.0", - "moduleLicenseUrl": "http://www.eclipse.org/legal/epl-v10.html" - }, { "moduleName": "me.friwi:gluegen-rt", "moduleUrl": "http://jogamp.org/gluegen/www/", @@ -896,13 +855,6 @@ "moduleLicense": "Apache-2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" }, - { - "moduleName": "org.apache.commons:commons-text", - "moduleUrl": "https://commons.apache.org/proper/commons-text", - "moduleVersion": "1.10.0", - "moduleLicense": "Apache License, Version 2.0", - "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" - }, { "moduleName": "org.apache.commons:commons-text", "moduleUrl": "https://commons.apache.org/proper/commons-text", @@ -1025,13 +977,6 @@ "moduleLicense": "The Apache Software License, Version 2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" }, - { - "moduleName": "org.bouncycastle:bcpkix-jdk18on", - "moduleUrl": "https://www.bouncycastle.org/java.html", - "moduleVersion": "1.72", - "moduleLicense": "Bouncy Castle Licence", - "moduleLicenseUrl": "https://www.bouncycastle.org/licence.html" - }, { "moduleName": "org.bouncycastle:bcpkix-jdk18on", "moduleUrl": "https://www.bouncycastle.org/download/bouncy-castle-java/", @@ -1046,13 +991,6 @@ "moduleLicense": "Bouncy Castle Licence", "moduleLicenseUrl": "https://www.bouncycastle.org/licence.html" }, - { - "moduleName": "org.bouncycastle:bcutil-jdk18on", - "moduleUrl": "https://www.bouncycastle.org/java.html", - "moduleVersion": "1.72", - "moduleLicense": "Bouncy Castle Licence", - "moduleLicenseUrl": "https://www.bouncycastle.org/licence.html" - }, { "moduleName": "org.bouncycastle:bcutil-jdk18on", "moduleUrl": "https://www.bouncycastle.org/download/bouncy-castle-java/", @@ -1069,13 +1007,13 @@ }, { "moduleName": "org.commonmark:commonmark", - "moduleVersion": "0.24.0", + "moduleVersion": "0.25.0", "moduleLicense": "BSD-2-Clause", "moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause" }, { "moduleName": "org.commonmark:commonmark-ext-gfm-tables", - "moduleVersion": "0.24.0", + "moduleVersion": "0.25.0", "moduleLicense": "BSD-2-Clause", "moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause" }, @@ -1093,6 +1031,13 @@ "moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception", "moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html" }, + { + "moduleName": "org.eclipse.angus:angus-mail", + "moduleUrl": "https://www.eclipse.org", + "moduleVersion": "2.0.3", + "moduleLicense": "GPL2 w/ CPE", + "moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html" + }, { "moduleName": "org.eclipse.angus:jakarta.mail", "moduleUrl": "https://www.eclipse.org", @@ -1303,20 +1248,6 @@ "moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception", "moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html" }, - { - "moduleName": "org.hamcrest:hamcrest", - "moduleUrl": "http://hamcrest.org/JavaHamcrest/", - "moduleVersion": "3.0", - "moduleLicense": "BSD-3-Clause", - "moduleLicenseUrl": "https://raw.githubusercontent.com/hamcrest/JavaHamcrest/master/LICENSE" - }, - { - "moduleName": "org.hamcrest:hamcrest-core", - "moduleUrl": "http://hamcrest.org/JavaHamcrest/", - "moduleVersion": "3.0", - "moduleLicense": "BSD-3-Clause", - "moduleLicenseUrl": "https://raw.githubusercontent.com/hamcrest/JavaHamcrest/master/LICENSE" - }, { "moduleName": "org.hdrhistogram:HdrHistogram", "moduleUrl": "http://hdrhistogram.github.io/HdrHistogram/", @@ -1372,34 +1303,6 @@ "moduleLicense": "The Apache License, Version 2.0", "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, - { - "moduleName": "org.junit.platform:junit-platform-commons", - "moduleUrl": "https://junit.org/junit5/", - "moduleVersion": "1.12.2", - "moduleLicense": "Eclipse Public License v2.0", - "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html" - }, - { - "moduleName": "org.junit.platform:junit-platform-engine", - "moduleUrl": "https://junit.org/junit5/", - "moduleVersion": "1.12.2", - "moduleLicense": "Eclipse Public License v2.0", - "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html" - }, - { - "moduleName": "org.junit.vintage:junit-vintage-engine", - "moduleUrl": "https://junit.org/junit5/", - "moduleVersion": "5.12.2", - "moduleLicense": "Eclipse Public License v2.0", - "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html" - }, - { - "moduleName": "org.junit:junit-bom", - "moduleUrl": "https://junit.org/junit5/", - "moduleVersion": "5.12.2", - "moduleLicense": "Eclipse Public License v2.0", - "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html" - }, { "moduleName": "org.latencyutils:LatencyUtils", "moduleUrl": "http://latencyutils.github.io/LatencyUtils/", @@ -1509,13 +1412,6 @@ "moduleLicense": "The Apache Software License, Version 2.0", "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, - { - "moduleName": "org.opentest4j:opentest4j", - "moduleUrl": "https://github.com/ota4j-team/opentest4j", - "moduleVersion": "1.3.0", - "moduleLicense": "The Apache License, Version 2.0", - "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" - }, { "moduleName": "org.ow2.asm:asm", "moduleUrl": "http://asm.ow2.org", @@ -1611,13 +1507,6 @@ "moduleLicense": "Apache License, Version 2.0", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" }, - { - "moduleName": "org.springframework.boot:spring-boot-devtools", - "moduleUrl": "https://spring.io/projects/spring-boot", - "moduleVersion": "3.5.3", - "moduleLicense": "Apache License, Version 2.0", - "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" - }, { "moduleName": "org.springframework.boot:spring-boot-starter", "moduleUrl": "https://spring.io/projects/spring-boot", diff --git a/stirling-pdf/src/main/resources/static/android-chrome-192x192.png b/app/core/src/main/resources/static/android-chrome-192x192.png similarity index 100% rename from stirling-pdf/src/main/resources/static/android-chrome-192x192.png rename to app/core/src/main/resources/static/android-chrome-192x192.png diff --git a/stirling-pdf/src/main/resources/static/android-chrome-512x512.png b/app/core/src/main/resources/static/android-chrome-512x512.png similarity index 100% rename from stirling-pdf/src/main/resources/static/android-chrome-512x512.png rename to app/core/src/main/resources/static/android-chrome-512x512.png diff --git a/stirling-pdf/src/main/resources/static/apple-touch-icon.png b/app/core/src/main/resources/static/apple-touch-icon.png similarity index 100% rename from stirling-pdf/src/main/resources/static/apple-touch-icon.png rename to app/core/src/main/resources/static/apple-touch-icon.png diff --git a/stirling-pdf/src/main/resources/static/browserconfig.xml b/app/core/src/main/resources/static/browserconfig.xml similarity index 100% rename from stirling-pdf/src/main/resources/static/browserconfig.xml rename to app/core/src/main/resources/static/browserconfig.xml diff --git a/stirling-pdf/src/main/resources/static/css/account.css b/app/core/src/main/resources/static/css/account.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/account.css rename to app/core/src/main/resources/static/css/account.css diff --git a/stirling-pdf/src/main/resources/static/css/add-image.css b/app/core/src/main/resources/static/css/add-image.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/add-image.css rename to app/core/src/main/resources/static/css/add-image.css diff --git a/stirling-pdf/src/main/resources/static/css/bootstrap-icons.css b/app/core/src/main/resources/static/css/bootstrap-icons.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/bootstrap-icons.css rename to app/core/src/main/resources/static/css/bootstrap-icons.css diff --git a/stirling-pdf/src/main/resources/static/css/bootstrap-icons.min.css b/app/core/src/main/resources/static/css/bootstrap-icons.min.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/bootstrap-icons.min.css rename to app/core/src/main/resources/static/css/bootstrap-icons.min.css diff --git a/stirling-pdf/src/main/resources/static/css/bootstrap.min.css b/app/core/src/main/resources/static/css/bootstrap.min.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/bootstrap.min.css rename to app/core/src/main/resources/static/css/bootstrap.min.css diff --git a/stirling-pdf/src/main/resources/static/css/bootstrap.min.css.map b/app/core/src/main/resources/static/css/bootstrap.min.css.map similarity index 100% rename from stirling-pdf/src/main/resources/static/css/bootstrap.min.css.map rename to app/core/src/main/resources/static/css/bootstrap.min.css.map diff --git a/stirling-pdf/src/main/resources/static/css/cookieconsent.css b/app/core/src/main/resources/static/css/cookieconsent.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/cookieconsent.css rename to app/core/src/main/resources/static/css/cookieconsent.css diff --git a/stirling-pdf/src/main/resources/static/css/cookieconsentCustomisation.css b/app/core/src/main/resources/static/css/cookieconsentCustomisation.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/cookieconsentCustomisation.css rename to app/core/src/main/resources/static/css/cookieconsentCustomisation.css diff --git a/stirling-pdf/src/main/resources/static/css/dragdrop.css b/app/core/src/main/resources/static/css/dragdrop.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/dragdrop.css rename to app/core/src/main/resources/static/css/dragdrop.css diff --git a/stirling-pdf/src/main/resources/static/css/edit-table-of-contents.css b/app/core/src/main/resources/static/css/edit-table-of-contents.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/edit-table-of-contents.css rename to app/core/src/main/resources/static/css/edit-table-of-contents.css diff --git a/stirling-pdf/src/main/resources/static/css/error.css b/app/core/src/main/resources/static/css/error.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/error.css rename to app/core/src/main/resources/static/css/error.css diff --git a/stirling-pdf/src/main/resources/static/css/errorBanner.css b/app/core/src/main/resources/static/css/errorBanner.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/errorBanner.css rename to app/core/src/main/resources/static/css/errorBanner.css diff --git a/stirling-pdf/src/main/resources/static/css/fileSelect.css b/app/core/src/main/resources/static/css/fileSelect.css similarity index 83% rename from stirling-pdf/src/main/resources/static/css/fileSelect.css rename to app/core/src/main/resources/static/css/fileSelect.css index 88bef91d5..8a305e4b8 100644 --- a/stirling-pdf/src/main/resources/static/css/fileSelect.css +++ b/app/core/src/main/resources/static/css/fileSelect.css @@ -98,6 +98,61 @@ font-weight: bold; } +/* Responsive text sizing for drag & drop area */ +#fileInputText { + font-size: 16px; + font-weight: bold; + color: var(--md-sys-color-on-surface); + max-width: 100%; + padding: 0 10px; + box-sizing: border-box; +} + +/* Progressive font size reduction for high zoom levels */ +@media only screen and (max-width: 1280px) { + #fileInputText { + font-size: 15px; + } +} + +@media only screen and (max-width: 960px) { + #fileInputText { + font-size: 14px; + } +} + +@media only screen and (max-width: 768px) { + #fileInputText { + font-size: 13px; + } +} + +@media only screen and (max-width: 640px) { + #fileInputText { + font-size: 12px; + } +} + +@media only screen and (max-width: 480px) { + #fileInputText { + font-size: 11px; + line-height: 1.3; + } +} + +@media only screen and (max-width: 384px) { + #fileInputText { + font-size: 10px; + line-height: 1.4; + } + + /* Also scale the container at ultra-high zoom */ + .input-container { + height: 130px; + padding: 5px; + } +} + .file-input-btn { display: inline-block; diff --git a/stirling-pdf/src/main/resources/static/css/fonts/bootstrap-icons.woff b/app/core/src/main/resources/static/css/fonts/bootstrap-icons.woff similarity index 100% rename from stirling-pdf/src/main/resources/static/css/fonts/bootstrap-icons.woff rename to app/core/src/main/resources/static/css/fonts/bootstrap-icons.woff diff --git a/stirling-pdf/src/main/resources/static/css/fonts/bootstrap-icons.woff2 b/app/core/src/main/resources/static/css/fonts/bootstrap-icons.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/css/fonts/bootstrap-icons.woff2 rename to app/core/src/main/resources/static/css/fonts/bootstrap-icons.woff2 diff --git a/stirling-pdf/src/main/resources/static/css/footer.css b/app/core/src/main/resources/static/css/footer.css similarity index 98% rename from stirling-pdf/src/main/resources/static/css/footer.css rename to app/core/src/main/resources/static/css/footer.css index 3945b1b43..274be2178 100644 --- a/stirling-pdf/src/main/resources/static/css/footer.css +++ b/app/core/src/main/resources/static/css/footer.css @@ -11,6 +11,7 @@ align-items: center; /* Center children horizontally */ flex-grow: 1; flex-direction: column; + margin-top: 1rem;; } .footer-powered-by { @@ -57,4 +58,4 @@ .footer-link-list{ flex-direction: column; /* Stack links vertically on smaller screens */ } -} \ No newline at end of file +} diff --git a/stirling-pdf/src/main/resources/static/css/game.css b/app/core/src/main/resources/static/css/game.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/game.css rename to app/core/src/main/resources/static/css/game.css diff --git a/stirling-pdf/src/main/resources/static/css/general.css b/app/core/src/main/resources/static/css/general.css similarity index 95% rename from stirling-pdf/src/main/resources/static/css/general.css rename to app/core/src/main/resources/static/css/general.css index 88e7a1b11..f94eef705 100644 --- a/stirling-pdf/src/main/resources/static/css/general.css +++ b/app/core/src/main/resources/static/css/general.css @@ -16,9 +16,8 @@ .navbar { height: auto; - /* Adjusts height automatically based on content */ white-space: nowrap; - /* Prevents wrapping of navbar contents */ + width: 100vw; } /* TODO enable later @@ -30,6 +29,7 @@ margin-right: auto; }*/ + html[dir="ltr"] * { direction: ltr; } diff --git a/stirling-pdf/src/main/resources/static/css/home-legacy.css b/app/core/src/main/resources/static/css/home-legacy.css similarity index 99% rename from stirling-pdf/src/main/resources/static/css/home-legacy.css rename to app/core/src/main/resources/static/css/home-legacy.css index b25fafc17..3539edd1f 100644 --- a/stirling-pdf/src/main/resources/static/css/home-legacy.css +++ b/app/core/src/main/resources/static/css/home-legacy.css @@ -3,7 +3,7 @@ background-color: var(--md-sys-color-surface-container-low); width: 100%; font-size: 16px; - margin-bottom: 2rem; + margin-bottom: 0.5rem; padding: 0.75rem 3.5rem; border: 1px solid var(--md-sys-color-outline-variant); border-radius: 3rem; diff --git a/stirling-pdf/src/main/resources/static/css/home.css b/app/core/src/main/resources/static/css/home.css similarity index 98% rename from stirling-pdf/src/main/resources/static/css/home.css rename to app/core/src/main/resources/static/css/home.css index c36a1eb95..fc1a8c3fb 100644 --- a/stirling-pdf/src/main/resources/static/css/home.css +++ b/app/core/src/main/resources/static/css/home.css @@ -91,7 +91,8 @@ } .newfeature{ - min-width:12rem; + display: flex; + width:fit-content } .recent-features{ display: flex; diff --git a/stirling-pdf/src/main/resources/static/css/imageHighlighter.css b/app/core/src/main/resources/static/css/imageHighlighter.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/imageHighlighter.css rename to app/core/src/main/resources/static/css/imageHighlighter.css diff --git a/stirling-pdf/src/main/resources/static/css/licenses.css b/app/core/src/main/resources/static/css/licenses.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/licenses.css rename to app/core/src/main/resources/static/css/licenses.css diff --git a/stirling-pdf/src/main/resources/static/css/login.css b/app/core/src/main/resources/static/css/login.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/login.css rename to app/core/src/main/resources/static/css/login.css diff --git a/stirling-pdf/src/main/resources/static/css/merge.css b/app/core/src/main/resources/static/css/merge.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/merge.css rename to app/core/src/main/resources/static/css/merge.css diff --git a/app/core/src/main/resources/static/css/multi-tool.css b/app/core/src/main/resources/static/css/multi-tool.css new file mode 100644 index 000000000..0f104be14 --- /dev/null +++ b/app/core/src/main/resources/static/css/multi-tool.css @@ -0,0 +1,625 @@ +/* Base Container Styles */ +.multi-tool-container { + max-width: 100vw; + margin: 0; + padding: 0 20px; +} + +/* Form Elements */ +label { + text-align: left; + display: block; + padding: 0rem 0.25rem; + font-size: 1.25rem; +} + +.form-control { + border-radius: 16px !important; + padding: 0.75rem; + border: 1px solid var(--theme-color-outline-variant); + flex-grow: 5; +} + +/* Action Bar Styles */ +.mt-action-bar { + display: flex; + gap: 10px; + align-items: start; + border: none; + backdrop-filter: blur(2px); + top: 10px; + z-index: 11; + padding: 1.25rem; + border-radius: 2rem; + margin: 0px 25px; + justify-content: center; +} + +.mt-action-bar > * { + padding-bottom: 0.5rem; +} + +.mt-file-uploader { + width: 100%; +} + +.mt-action-bar svg, +.mt-action-btn svg { + width: 20px; + height: 20px; +} + +.mt-action-bar .mt-filename { + width: 100%; + display: flex; + gap: 10px; +} + +/* Action Button Styles */ +.mt-action-btn { + position: fixed; + bottom: 80px; + left: 50%; + transform: translateX(-50%); + border-radius: 2rem; + z-index: 12; + background-color: var(--md-sys-color-surface-container-low); + display: flex; + gap: 10px; + width: fit-content; + justify-content: center; + padding: 10px 20px; + transition: all 0.3s ease-in-out; +} + +.mt-action-btn .btn { + width: 3.5rem; + height: 3.5rem; + border-radius: 20px; + padding: 0; + position: relative; +} + +/* Card and Container Styles */ +.bg-card { + background-color: var(--md-sys-color-surface-5); + border-radius: 3rem; + padding: 15px 0; + margin-left: 55px; + margin-right: 20px; + display: flex; + flex-direction: column; + align-items: stretch; +} + +#pages-container-wrapper { + width: 100%; + display: flex; + justify-content: center; + padding: 0.75rem; + border-radius: 25px; + min-height: 275px; + margin: 0 0 20px 0; +} + +#pages-container { + display: inline-flex; + flex-wrap: wrap; + gap: 20px; + justify-content: flex-start; + width: fit-content; + max-width: 100%; +} + +/* Scrollbar Styles */ +#pages-container-wrapper::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +#pages-container-wrapper::-webkit-scrollbar-track { + background: var(--scroll-bar-color); +} + +#pages-container-wrapper::-webkit-scrollbar-thumb { + border-radius: 10px; + background: var(--scroll-bar-thumb); +} + +#pages-container-wrapper::-webkit-scrollbar-thumb:hover { + background: var(--scroll-bar-thumb-hover); +} + +/* Page Container Base Styles */ +.page-container { + display: inline-block; + list-style-type: none; + width: 260px; + height: 260px; + line-height: 50px; + margin-top: 15px; + box-sizing: border-box; + text-align: center; + aspect-ratio: 1; + position: relative; + user-select: none; + transition: width 0.3s ease-in-out; +} + +/* Responsive Page Container Sizes */ +@media only screen and (max-width: 480px) { + .page-container { + width: calc(100vw - 90px); + height: calc(100vw - 90px); + max-width: 300px; + max-height: 300px; + margin: 5px auto; + } + #pages-container { gap: 10px; } +} + +@media only screen and (min-width: 481px) and (max-width: 768px) { + .page-container { + width: calc((100vw - 120px - 12px) / 2); + height: calc((100vw - 120px - 12px) / 2); + max-width: 250px; + max-height: 250px; + margin: 6px; + } + #pages-container { gap: 12px; } +} + +@media only screen and (min-width: 769px) and (max-width: 1199px) { + .page-container { + width: calc((100vw - 140px - 45px) / 3); + height: calc((100vw - 140px - 45px) / 3); + max-width: 220px; + max-height: 220px; + margin: 7px; + } + #pages-container { gap: 15px; } +} + +@media only screen and (min-width: 1200px) and (max-width: 1280px) { + .page-container { + width: calc((100vw - 160px - 60px) / 4); + height: calc((100vw - 160px - 60px) / 4); + max-width: 200px; + max-height: 200px; + margin: 8px; + } + #pages-container { gap: 17px; } +} + +@media only screen and (min-width: 1281px) { + .page-container { + width: calc((100vw - 180px - 80px) / 5); + height: calc((100vw - 180px - 80px) / 5); + max-width: 190px; + max-height: 190px; + margin: 10px; + } + #pages-container { gap: 20px; } +} + +/* Split Page Styles */ +.page-container.split-before { + border-left: 1px dashed var(--md-sys-color-on-surface); + padding-left: -1px; +} + +.page-container.split-before:first-child { + border-left: none; +} + +.page-container:first-child .pdf-actions_split-file-button { + display: none; +} + +/* RTL Language Support */ +.page-container:last-child:lang(ar), +.page-container:last-child:lang(he), +.page-container:last-child:lang(fa), +.page-container:last-child:lang(ur), +.page-container:last-child:lang(ckb), +.page-container:last-child:lang(ks), +.page-container:last-child:lang(kk), +.page-container:last-child:lang(uz), +.page-container:last-child:lang(ky), +.page-container:last-child:lang(bal), +.page-container:last-child:lang(dv), +.page-container:last-child:lang(ps), +.page-container:last-child:lang(sdg), +.page-container:last-child:lang(syr), +.page-container:last-child:lang(mzn), +.page-container:last-child:lang(tgl), +.page-container:last-child:lang(pnb), +.page-container:last-child:lang(ug), +.page-container:last-child:lang(nqo), +.page-container:last-child:lang(bqi) { + margin-left: auto !important; + margin-right: 0 !important; +} + +/* Page Image Styles */ +.page-container img { + max-width: calc(100% - 8px); + max-height: calc(100% - 8px); + display: block; + position: absolute; + left: 50%; + top: 50%; + translate: -50% -50%; + box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384); + border-radius: 4px; + transition: rotate 0.3s; +} + +/* Page Number Styles */ +.page-number { + position: absolute; + top: 5px; + left: 5px; + line-height: normal; + color: var(--md-sys-color-on-secondary); + background-color: rgba(162, 201, 255, 0.8); + padding: 6px 8px; + border-radius: 8px; + font-size: 16px; + z-index: 2; + font-weight: 450; +} + +/* Tool Header and Button Styles */ +.tool-header { + margin: 0.5rem 1rem 1rem; +} + +#select-pages-button { + opacity: 0.5; +} + +#add-pdf-button { + margin: 0 auto; +} + +/* Selected Pages Container Styles */ +.selected-pages-container { + background-color: var(--md-sys-color-surface); + border-radius: 16px; + padding: 15px; + width: 100%; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + font-family: Arial, sans-serif; +} + +.selected-pages-container h3 { + color: var(--md-sys-color-on-surface); + font-size: 1.2em; + margin-bottom: 10px; +} + +.selected-pages-header { + margin-bottom: 15px; +} + +.selected-pages-header h5 { + margin: 0 0 8px 0 !important; + font-size: 1.1rem; + font-weight: 600; + color: var(--md-sys-color-on-surface); +} + +.selected-pages-header #csv-input { + width: 100%; + height: 2.5rem; + border-radius: 8px; + border: 1px solid var(--md-sys-color-outline); + background-color: var(--md-sys-color-surface); + color: var(--md-sys-color-on-surface); + padding: 0 12px; + font-size: 0.95rem; +} + +.selected-pages-header #csv-input:focus { + outline: none; + border-color: var(--md-sys-color-primary); + box-shadow: 0 0 0 2px rgba(var(--md-sys-color-primary-rgb), 0.2); +} + +/* Pages List Styles */ +.pages-list { + display: flex; + flex-wrap: wrap; + gap: 10px; + padding: 0; + list-style: none; + min-height: 0; + max-height: 10rem; + overflow: auto; +} + +.page-item { + background-color: var(--md-sys-color-surface-container-low); + border-radius: 8px; + padding: 8px 12px; + display: flex; + align-items: center; + gap: 8px; + font-weight: bold; + color: var(--md-sys-color-on-surface); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + width: 7rem; + height: 2.5rem; +} + +.selected-page-number { + width: 4rem; + font-size: small; +} + +.remove-btn { + cursor: pointer; + color: var(--md-sys-color-on-surface); + font-size: 1.2em; +} + +.checkbox-container { + align-items: center; + justify-content: center; + display: flex; + flex-direction: column; +} + +.checkbox-label { + font-size: medium; +} + +/* Zoom Level Responsive Styles */ +@media only screen and (min-width: 2000px) { + .mt-action-btn { + gap: 12px; + padding: 12px 24px; + border-radius: 2.5rem; + } + .mt-action-btn .btn { + width: 4rem; + height: 4rem; + border-radius: 22px; + } + .mt-action-btn .btn .material-symbols-rounded { + font-size: 1.7rem; + } +} + +@media only screen and (min-width: 2560px) { + .mt-action-btn { + gap: 15px; + padding: 15px 30px; + border-radius: 3rem; + } + .mt-action-btn .btn { + width: 5rem; + height: 5rem; + border-radius: 28px; + } + .mt-action-btn .btn .material-symbols-rounded { + font-size: 2.1rem; + } +} + +@media only screen and (min-width: 3840px) { + .mt-action-btn { + gap: 20px; + padding: 20px 40px; + border-radius: 4rem; + } + .mt-action-btn .btn { + width: 7rem; + height: 7rem; + border-radius: 40px; + } + .mt-action-btn .btn .material-symbols-rounded { + font-size: 3rem; + } +} + +@media only screen and (min-width: 7680px) { + .mt-action-btn { + gap: 40px; + padding: 40px 80px; + border-radius: 8rem; + } + .mt-action-btn .btn { + width: 14rem; + height: 14rem; + border-radius: 80px; + } + .mt-action-btn .btn .material-symbols-rounded { + font-size: 6rem; + } +} + +/* Zoom-responsive Sidebar Styles */ +@media only screen and (max-width: 1280px) { + .container { + position: relative; + } + + .mt-action-btn { + position: fixed !important; + left: 10px !important; + top: 80px !important; + bottom: 20px !important; + margin: 0 !important; + transform: none !important; + border-radius: 16px !important; + background-color: var(--md-sys-color-surface-container-low); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + backdrop-filter: blur(8px); + display: flex !important; + flex-direction: column !important; + align-items: center !important; + justify-content: center !important; + height: calc(100vh - 100px) !important; + overflow-y: auto !important; + scrollbar-width: none !important; + -ms-overflow-style: none !important; + z-index: 12; + width: 70px !important; + gap: 8px !important; + padding: 12px 8px !important; + box-sizing: border-box !important; + } + + .mt-action-btn:has(.btn:nth-last-child(n+7)) { + justify-content: flex-start !important; + } + + .mt-action-btn::-webkit-scrollbar { + display: none !important; + } + + .mt-action-btn .btn { + width: 48px !important; + height: 48px !important; + border-radius: 12px !important; + padding: 0 !important; + margin: 0 !important; + flex-shrink: 0; + font-size: 16px !important; + box-sizing: border-box !important; + } + + .mt-action-btn .btn .material-symbols-rounded { + font-size: 20px !important; + line-height: 1 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + width: 100% !important; + height: 100% !important; + font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24 !important; + } + + .multi-tool-container { + margin-left: 0 !important; + max-width: 100% !important; + } + + .mt-action-bar { + margin-left: 25px !important; + margin-right: 25px !important; + } + + .mt-action-btn:not(:has(*:nth-child(6))) { + justify-content: center !important; + } +} + +/* Mobile and High Zoom Responsive Styles */ +@media only screen and (max-width: 960px) { + .mt-action-btn { + left: 8px !important; + top: 75px !important; + bottom: 15px !important; + height: calc(100vh - 90px) !important; + } +} + +@media only screen and (max-width: 768px) { + .mt-action-btn { + left: 5px !important; + width: 60px !important; + top: calc(var(--navbar-height, 60px) + 10px) !important; + bottom: 10px !important; + height: calc(100vh - var(--navbar-height, 60px) - 20px) !important; + } + + .mt-action-btn .btn { + width: 40px !important; + height: 40px !important; + box-sizing: border-box !important; + } + + .mt-action-btn .btn .material-symbols-rounded { + font-size: 16px !important; + } + + #pages-container { + margin: 0 auto !important; + display: flex !important; + flex-wrap: wrap !important; + justify-content: center !important; + width: 100% !important; + } + + .page-container { + width: calc(100vw - 55px) !important; + height: calc(100vw - 60px) !important; + max-width: 350px !important; + max-height: 350px !important; + margin: 5px auto !important; + } +} + +@media only screen and (max-width: 480px) { + .mt-action-btn { + left: 2px !important; + top: calc(var(--navbar-height, 60px) + 5px) !important; + bottom: 5px !important; + height: calc(100vh - var(--navbar-height, 60px) - 10px) !important; + width: 50px !important; + gap: 6px !important; + padding: 10px 6px !important; + } + + .mt-action-btn .btn { + width: 32px !important; + height: 32px !important; + border-radius: 10px !important; + box-sizing: border-box !important; + } + + .mt-action-btn .btn .material-symbols-rounded { + font-size: 14px !important; + } +} + +@media only screen and (max-width: 384px) { + .mt-action-btn { + left: 2px !important; + top: calc(var(--navbar-height, 60px) + 5px) !important; + bottom: 5px !important; + height: calc(100vh - var(--navbar-height, 60px) - 10px) !important; + width: 40px !important; + gap: 4px !important; + padding: 8px 4px !important; + } + + .mt-action-btn .btn { + width: 28px !important; + height: 28px !important; + border-radius: 8px !important; + box-sizing: border-box !important; + } + + .mt-action-btn .btn .material-symbols-rounded { + font-size: 12px !important; + } + + .page-container { + width: calc(100vw - 55px) !important; + height: calc(100vw - 60px) !important; + max-width: 280px !important; + max-height: 280px !important; + margin: 3px auto !important; + } + + .page-container img { + max-width: calc(100% - 4px) !important; + max-height: calc(100% - 4px) !important; + } +} + + diff --git a/stirling-pdf/src/main/resources/static/css/navbar.css b/app/core/src/main/resources/static/css/navbar.css similarity index 65% rename from stirling-pdf/src/main/resources/static/css/navbar.css rename to app/core/src/main/resources/static/css/navbar.css index 31099cdf2..047957b6d 100644 --- a/stirling-pdf/src/main/resources/static/css/navbar.css +++ b/app/core/src/main/resources/static/css/navbar.css @@ -63,6 +63,79 @@ transform: translateY(-2px); } +/* Responsive navbar brand - prevent hamburger from wrapping */ +.navbar-brand { + display: flex !important; + align-items: center; + gap: 8px; + min-width: 0; /* Allow shrinking */ +} + +.navbar-brand .icon-text { + font-size: 1.5rem; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Progressive text shrinking to prevent hamburger wrap */ +@media only screen and (max-width: 480px) { + .navbar-brand .icon-text { + font-size: 1.3rem; + } + + .main-icon { + width: 32px; + height: 32px; + } +} + +@media only screen and (max-width: 420px) { + .navbar-brand .icon-text { + font-size: 1.1rem; + } + + .main-icon { + width: 28px; + height: 28px; + } +} + +@media only screen and (max-width: 380px) { + .navbar-brand .icon-text { + font-size: 1rem; + } + + .main-icon { + width: 24px; + height: 24px; + } +} + +@media only screen and (max-width: 340px) { + .navbar-brand .icon-text { + font-size: 0.9rem; + } + + .main-icon { + width: 20px; + height: 20px; + } +} + +/* Ultra-small screens - hide text, keep icon */ +@media only screen and (max-width: 320px) { + .navbar-brand .icon-text { + display: none; + } + + .main-icon { + width: 24px; + height: 24px; + } +} + .nav-icon { vertical-align: middle; font-size: 2rem !important; @@ -86,13 +159,78 @@ .scalable-languages-container { display: grid; - grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); /* Auto-fill columns, with a minimum width of 180px */ + grid-template-columns: repeat(1, 1fr); +} + +@media (min-width: 400px) { + #languageSelection.scalable-languages-container { + grid-template-columns: repeat(2, 1fr); + } +} +@media (min-width: 600px) { + #languageSelection.scalable-languages-container { + grid-template-columns: repeat(3, 1fr); + } +} +@media (min-width: 900px) { + #languageSelection.scalable-languages-container { + grid-template-columns: repeat(4, 1fr) !important; + } } .scalable-languages-container:not(:has(> :nth-child(4))) .lang-dropdown-item-wrapper:last-child { border: 0px !important } +html[dir="ltr"] #languageSelection .lang-dropdown-item-wrapper:last-child { + border-right: none !important; +} + +#languageSelection .lang-dropdown-item-wrapper:last-child { + border: 0px !important; +} +@media (max-width: 600px) { + .scalable-languages-container { + grid-template-columns: repeat(2, 1fr); + } + + .scalable-languages-container:not(:has(> :nth-child(2))) { + grid-template-columns: repeat(var(--count), 1fr) !important; + } + + .scalable-languages-container .lang-dropdown-item-wrapper:nth-child(2n) { + border: 0px + } +} + +@media (min-width: 601px) and (max-width: 900px) { + .scalable-languages-container { + grid-template-columns: repeat(3, 1fr); + } + + .scalable-languages-container:not(:has(> :nth-child(3))) { + grid-template-columns: repeat(var(--count), 1fr) !important; + } + + .scalable-languages-container .lang-dropdown-item-wrapper:nth-child(3n) { + border: 0px + } +} + +@media (min-width: 901px) { + .scalable-languages-container { + grid-template-columns: repeat(4, 1fr); + } + + .scalable-languages-container:not(:has(> :nth-child(4))) { + grid-template-columns: repeat(var(--count), 1fr) !important; + } + + .scalable-languages-container .lang-dropdown-item-wrapper:nth-child(4n) { + border: 0px + } +} + .scalable-languages-container:has(> *:nth-child(1)) { --count: 1; } @@ -106,57 +244,27 @@ } html[dir="ltr"] .lang-dropdown-item-wrapper { - border-right: 2px solid var(--md-nav-color-on-seperator); + border-right: 2px solid var(--md-nav-color-on-separator); } html[dir="rtl"] .lang-dropdown-item-wrapper { - border-left: 2px solid var(--md-nav-color-on-seperator); + border-left: 2px solid var(--md-nav-color-on-separator); } /* Responsive adjustments */ -@media (min-width: 1200px){ +@media (min-width: 1200px) { .lang-dropdown-item-wrapper .dropdown-item { min-width: 200px - } } -@media (max-width: 600px) { - .scalable-languages-container { - grid-template-columns: repeat(2, 1fr); - } - .scalable-languages-container:not(:has(> :nth-child(2))){ - grid-template-columns: repeat(var(--count), 1fr) !important; - } - .scalable-languages-container .lang-dropdown-item-wrapper:nth-child(2n) { - border: 0px - } +.scroll-lock-y { + overflow-y: auto; + max-height: 80vh; + overscroll-behavior-y: contain; + -webkit-overflow-scrolling: touch; +} } -@media (min-width: 601px) and (max-width: 900px) { - .scalable-languages-container { - grid-template-columns: repeat(3, 1fr); - } - .scalable-languages-container:not(:has(> :nth-child(3))){ - grid-template-columns: repeat(var(--count), 1fr) !important; - } - .scalable-languages-container .lang-dropdown-item-wrapper:nth-child(3n) { - border: 0px - } -} - -@media (min-width: 901px) { - .scalable-languages-container { - grid-template-columns: repeat(4, 1fr); - } - - .scalable-languages-container:not(:has(> :nth-child(4))){ - grid-template-columns: repeat(var(--count), 1fr) !important; - } - - .scalable-languages-container .lang-dropdown-item-wrapper:nth-child(4n) { - border: 0px - } -} .dropdown-item .icon-text { text-wrap: wrap; @@ -212,6 +320,21 @@ span.icon-text::after { color: var(--md-sys-color-on-surface-variant); } +.nav-link { + display: flex; + align-items: center; + max-width: 98vw; +} + +.chevron-icon { + margin-left: auto; + transition: transform 0.3s ease; +} + +[aria-expanded="true"] > .chevron-icon { + transform: rotate(180deg); +} + .nav-item { position: relative; } @@ -269,7 +392,9 @@ span.icon-text::after { /* Mega Menu */ .dropdown-mega .dropdown-menu { - width: 98%; + width: 100%; + left: 0 !important; + right: auto !important; } .dropdown-mega .title { @@ -382,19 +507,7 @@ html[dir="rtl"] .dropdown-menu { right: auto; } -html[dir="ltr"] .dropdown-menu[data-bs-popper] { - top: auto; - left: auto; - right: 0; - margin-top: 0 !important; -} - -html[dir="rtl"] .dropdown-menu[data-bs-popper] { - top: auto; - left: 0; - right: auto; - margin-top: 0 !important; -} +/* Bootstrap Popper positioning overrides removed - dropdowns now position naturally relative to their buttons */ .dropdown-menu-wrapper { padding: 1.5rem 0; @@ -405,6 +518,7 @@ html[dir="rtl"] .dropdown-menu[data-bs-popper] { box-shadow: var(--md-sys-elevation-2); } + .dropdown-menu-tp { color: transparent; background-color: transparent; @@ -416,27 +530,119 @@ html[dir="rtl"] .dropdown-menu[data-bs-popper] { display: inline-flex; } -@media (min-width:992px) { +@media (max-width:1199.98px) { + .navbar-collapse .dropdown-menu { + width: 100%; + } + .navbar-collapse .dropdown-menu-wrapper { + width: 100%; + box-sizing: border-box; + } + .navbar-collapse .dropdown-mw-28 { + min-width: 0; + } +} + +@media (min-width:1200px) { + /* This CSS-based hover is disabled because it conflicts with Bootstrap's JavaScript. + Hover functionality is now handled in navbar.js and search.js */ + /* .dropdown:hover .dropdown-menu { display: block; margin-top: 0; } + */ - /* .icon-hide { - display: none; - } */ -} - -@media (max-width:1199px) { - .icon-hide { - display: inline-flex; - } -} - -@media (min-width:1200px) { .icon-hide { display: none; } + .chevron-icon { + display: none !important; + } +} + +@media (max-width: 1199.98px) { + .navbar-collapse .dropdown-menu { + width: 100vw !important; + max-width: 100vw !important; + left: 0 !important; + right: 0 !important; + transform: none !important; + transform-origin: none !important; + } + + .navbar .navbar-expand-xl .dropdown-menu, + .navbar-expand .dropdown-menu { + transform: none !important; + transform-origin: none !important; + left: 0 !important; + right: 0 !important; + } + + .navbar-collapse .dropdown-mega .dropdown-menu { + max-height: 60vh; + overflow-y: auto; + } + .navbar-collapse .dropdown-mega .dropdown-menu-wrapper { + border-radius: 0; + } + + #favoritesDropdown, + #languageDropdown + .dropdown-menu .dropdown-menu-wrapper, + #searchDropdown + .dropdown-menu .dropdown-menu-wrapper { + padding: 1.5rem 1rem; + } + + #favoritesDropdown, #languageSelection, #searchResults { + width: 100%; + box-sizing: border-box; + } + + .navbar-collapse .dropdown-menu-wrapper { + width: 95vw; + box-sizing: border-box; + margin-left: 0 !important; + padding: 0 !important; + } + .navbar-collapse .dropdown-mw-28 { + min-width: 0; + } + .icon-hide { + display: inline-flex; + } + + .navbar-collapse .dropdown-item { + margin-left: 0 !important; + } + + .container { + margin-left: auto !important; + margin-right: auto !important; + padding-left: 4px !important; + } + + #mainNavbarDropdownMenu { + transform: none !important; + transform-origin: none !important; + left: 0 !important; + right: 0 !important; + width: 100vw !important; + margin-bottom: 0 !important; + } + + .dropdown-menu, + .dropdown-menu-tp, + .dropdown-menu-tp.show { + transform: none !important; + transform-origin: none !important; + max-width: 95vw !important; + width: 100vw !important; + left: 0 !important; + right: 0 !important; + margin-bottom: 0 !important; + } + + } .go-pro-link { @@ -477,9 +683,8 @@ html[dir="rtl"] .dropdown-menu[data-bs-popper] { display: flex; gap: 30px; justify-content: center; - width: 140%; + width: 100%; position: relative; - left: -20%; } .feature-group { @@ -491,6 +696,12 @@ html[dir="rtl"] .dropdown-menu[data-bs-popper] { box-sizing: border-box; } +@media (max-width: 768px) { + .feature-group { + min-width: 10rem; + } +} + .feature-rows { display: flex; flex-wrap: wrap; diff --git a/stirling-pdf/src/main/resources/static/css/pdfActions.css b/app/core/src/main/resources/static/css/pdfActions.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/pdfActions.css rename to app/core/src/main/resources/static/css/pdfActions.css diff --git a/stirling-pdf/src/main/resources/static/css/pipeline.css b/app/core/src/main/resources/static/css/pipeline.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/pipeline.css rename to app/core/src/main/resources/static/css/pipeline.css diff --git a/stirling-pdf/src/main/resources/static/css/prism.css b/app/core/src/main/resources/static/css/prism.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/prism.css rename to app/core/src/main/resources/static/css/prism.css diff --git a/stirling-pdf/src/main/resources/static/css/rainbow-mode.css b/app/core/src/main/resources/static/css/rainbow-mode.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/rainbow-mode.css rename to app/core/src/main/resources/static/css/rainbow-mode.css diff --git a/stirling-pdf/src/main/resources/static/css/redact.css b/app/core/src/main/resources/static/css/redact.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/redact.css rename to app/core/src/main/resources/static/css/redact.css diff --git a/stirling-pdf/src/main/resources/static/css/removeImage.css b/app/core/src/main/resources/static/css/removeImage.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/removeImage.css rename to app/core/src/main/resources/static/css/removeImage.css diff --git a/stirling-pdf/src/main/resources/static/css/rotate-pdf.css b/app/core/src/main/resources/static/css/rotate-pdf.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/rotate-pdf.css rename to app/core/src/main/resources/static/css/rotate-pdf.css diff --git a/stirling-pdf/src/main/resources/static/css/sign.css b/app/core/src/main/resources/static/css/sign.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/sign.css rename to app/core/src/main/resources/static/css/sign.css diff --git a/stirling-pdf/src/main/resources/static/css/split-pdf-by-sections.css b/app/core/src/main/resources/static/css/split-pdf-by-sections.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/split-pdf-by-sections.css rename to app/core/src/main/resources/static/css/split-pdf-by-sections.css diff --git a/stirling-pdf/src/main/resources/static/css/stamp.css b/app/core/src/main/resources/static/css/stamp.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/stamp.css rename to app/core/src/main/resources/static/css/stamp.css diff --git a/stirling-pdf/src/main/resources/static/css/tab-container.css b/app/core/src/main/resources/static/css/tab-container.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/tab-container.css rename to app/core/src/main/resources/static/css/tab-container.css diff --git a/stirling-pdf/src/main/resources/static/css/theme/componentes.css b/app/core/src/main/resources/static/css/theme/componentes.css similarity index 99% rename from stirling-pdf/src/main/resources/static/css/theme/componentes.css rename to app/core/src/main/resources/static/css/theme/componentes.css index c10806ff7..a113015eb 100644 --- a/stirling-pdf/src/main/resources/static/css/theme/componentes.css +++ b/app/core/src/main/resources/static/css/theme/componentes.css @@ -40,7 +40,7 @@ textarea { } *::-webkit-scrollbar-corner { - background-color: var(--md-sys-color-surface); + background-color: var(--md-sys-color-surface); } /* Alerts */ @@ -66,6 +66,9 @@ td { background-color: var(--md-sys-color-surface-5); border-radius: 3rem; padding: 2.5rem; + + max-width: 95vw; + margin-left: 2vw; } .card { diff --git a/stirling-pdf/src/main/resources/static/css/theme/font.css b/app/core/src/main/resources/static/css/theme/font.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/theme/font.css rename to app/core/src/main/resources/static/css/theme/font.css diff --git a/stirling-pdf/src/main/resources/static/css/theme/theme.css b/app/core/src/main/resources/static/css/theme/theme.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/theme/theme.css rename to app/core/src/main/resources/static/css/theme/theme.css diff --git a/app/core/src/main/resources/static/css/theme/theme.dark.css b/app/core/src/main/resources/static/css/theme/theme.dark.css new file mode 100644 index 000000000..411c8f14c --- /dev/null +++ b/app/core/src/main/resources/static/css/theme/theme.dark.css @@ -0,0 +1,79 @@ +:root { + /* Colors */ + --md-sys-color-primary: rgb(162 201 255); + --md-sys-color-surface-tint: rgb(162 201 255); + --md-sys-color-on-primary: rgb(0 49 92); + --md-sys-color-primary-container: rgb(0 118 208); + --md-sys-color-on-primary-container: rgb(255 255 255); + --md-sys-color-secondary: rgb(169 201 246); + --md-sys-color-on-secondary: rgb(12 49 87); + --md-sys-color-secondary-container: rgb(29 62 100); + --md-sys-color-on-secondary-container: rgb(180 210 255); + --md-sys-color-tertiary: rgb(193 194 248); + --md-sys-color-on-tertiary: rgb(42 44 88); + --md-sys-color-tertiary-container: rgb(110 112 161); + --md-sys-color-on-tertiary-container: rgb(255 255 255); + --md-sys-color-error: rgb(255 180 171); + --md-sys-color-on-error: rgb(105 0 5); + --md-sys-color-error-container: rgb(147 0 10); + --md-sys-color-on-error-container: rgb(255 218 214); + --md-sys-color-background: rgb(15 20 26); + --md-sys-color-on-background: rgb(223 226 235); + --md-sys-color-surface: rgb(15 20 26); + --md-sys-color-on-surface: rgb(223 226 235); + --md-sys-color-surface-variant: rgb(64 71 83); + --md-sys-color-on-surface-variant: rgb(192 199 213); + --md-sys-color-outline: rgb(138 145 158); + --md-sys-color-outline-variant: rgb(64 71 83); + --md-sys-color-shadow: rgb(0 0 0); + --md-sys-color-scrim: rgb(0 0 0); + --md-sys-color-inverse-surface: rgb(223 226 235); + --md-sys-color-inverse-on-surface: rgb(45 49 55); + --md-sys-color-inverse-primary: rgb(0 96 170); + --md-sys-color-primary-fixed: rgb(211 228 255); + --md-sys-color-on-primary-fixed: rgb(0 28 56); + --md-sys-color-primary-fixed-dim: rgb(162 201 255); + --md-sys-color-on-primary-fixed-variant: rgb(0 72 130); + --md-sys-color-secondary-fixed: rgb(211 228 255); + --md-sys-color-on-secondary-fixed: rgb(0 28 56); + --md-sys-color-secondary-fixed-dim: rgb(169 201 246); + --md-sys-color-on-secondary-fixed-variant: rgb(40 72 111); + --md-sys-color-tertiary-fixed: rgb(225 224 255); + --md-sys-color-on-tertiary-fixed: rgb(20 22 66); + --md-sys-color-tertiary-fixed-dim: rgb(193 194 248); + --md-sys-color-on-tertiary-fixed-variant: rgb(64 67 112); + --md-sys-color-surface-dim: rgb(15 20 26); + --md-sys-color-surface-bright: rgb(53 57 64); + --md-sys-color-surface-container-lowest: rgb(10 14 20); + --md-sys-color-surface-container-low: rgb(24 28 34); + --md-sys-color-surface-container: rgb(28 32 38); + --md-sys-color-surface-container-high: rgb(38 42 49); + --md-sys-color-surface-container-highest: rgb(49 53 60); + /* Tools Color */ + --md-nav-section-color-opacity: 1; + --md-nav-on-section-color-opacity: 1; + --md-nav-section-color-sign: rgba(25, 101, 212, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-sign: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-organize: rgba(120, 130, 255, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-organize: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-convert: rgba(25, 177, 212, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-convert: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-convertto: rgba(104, 220, 149, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-convertto: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-security: rgba(255, 120, 146, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-security: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-other: rgba(72, 189, 84, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-other: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-advance: rgba(245, 84, 84, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-advance: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-image: rgba(212, 172, 25, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-image: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-word: rgba(61, 153, 245, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-word: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-section-color-ppt: rgba(255, 128, 0, var(--md-nav-section-color-opacity)); + --md-nav-on-section-color-ppt: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity)); + --md-nav-color-on-separator: rgb(24 28 34); + --md-nav-background: rgb(15 20 26); + --favourite-add: #9ed18c; + --favourite-remove: palevioletred; +} \ No newline at end of file diff --git a/stirling-pdf/src/main/resources/static/css/theme/theme.light.css b/app/core/src/main/resources/static/css/theme/theme.light.css similarity index 98% rename from stirling-pdf/src/main/resources/static/css/theme/theme.light.css rename to app/core/src/main/resources/static/css/theme/theme.light.css index 269ccd68b..f4bfc4065 100644 --- a/stirling-pdf/src/main/resources/static/css/theme/theme.light.css +++ b/app/core/src/main/resources/static/css/theme/theme.light.css @@ -72,8 +72,8 @@ --md-nav-on-section-color-word: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity)); --md-nav-section-color-ppt: rgba(255, 128, 0, var(--md-nav-section-color-opacity)); --md-nav-on-section-color-ppt: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity)); - --md-nav-color-on-seperator: rgb(174, 178, 179); + --md-nav-color-on-separator: rgb(174, 178, 179); --md-nav-background: rgb(248 249 255); --favourite-add: #25ab6c; --favourite-remove: rgb(222, 94, 137); -} +} \ No newline at end of file diff --git a/stirling-pdf/src/main/resources/static/css/usage.css b/app/core/src/main/resources/static/css/usage.css similarity index 100% rename from stirling-pdf/src/main/resources/static/css/usage.css rename to app/core/src/main/resources/static/css/usage.css diff --git a/stirling-pdf/src/main/resources/static/favicon-16x16.png b/app/core/src/main/resources/static/favicon-16x16.png similarity index 100% rename from stirling-pdf/src/main/resources/static/favicon-16x16.png rename to app/core/src/main/resources/static/favicon-16x16.png diff --git a/stirling-pdf/src/main/resources/static/favicon-32x32.png b/app/core/src/main/resources/static/favicon-32x32.png similarity index 100% rename from stirling-pdf/src/main/resources/static/favicon-32x32.png rename to app/core/src/main/resources/static/favicon-32x32.png diff --git a/stirling-pdf/src/main/resources/static/favicon.icns b/app/core/src/main/resources/static/favicon.icns similarity index 100% rename from stirling-pdf/src/main/resources/static/favicon.icns rename to app/core/src/main/resources/static/favicon.icns diff --git a/stirling-pdf/src/main/resources/static/favicon.ico b/app/core/src/main/resources/static/favicon.ico similarity index 100% rename from stirling-pdf/src/main/resources/static/favicon.ico rename to app/core/src/main/resources/static/favicon.ico diff --git a/stirling-pdf/src/main/resources/static/favicon.png b/app/core/src/main/resources/static/favicon.png similarity index 100% rename from stirling-pdf/src/main/resources/static/favicon.png rename to app/core/src/main/resources/static/favicon.png diff --git a/stirling-pdf/src/main/resources/static/favicon.svg b/app/core/src/main/resources/static/favicon.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/favicon.svg rename to app/core/src/main/resources/static/favicon.svg diff --git a/stirling-pdf/src/main/resources/static/files/Auto Splitter Divider (with instructions).pdf b/app/core/src/main/resources/static/files/Auto Splitter Divider (with instructions).pdf similarity index 100% rename from stirling-pdf/src/main/resources/static/files/Auto Splitter Divider (with instructions).pdf rename to app/core/src/main/resources/static/files/Auto Splitter Divider (with instructions).pdf diff --git a/stirling-pdf/src/main/resources/static/files/popularity.txt b/app/core/src/main/resources/static/files/popularity.txt similarity index 100% rename from stirling-pdf/src/main/resources/static/files/popularity.txt rename to app/core/src/main/resources/static/files/popularity.txt diff --git a/stirling-pdf/src/main/resources/static/fonts/Arimo-Regular.woff2 b/app/core/src/main/resources/static/fonts/Arimo-Regular.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/Arimo-Regular.woff2 rename to app/core/src/main/resources/static/fonts/Arimo-Regular.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/DancingScript-Regular.woff2 b/app/core/src/main/resources/static/fonts/DancingScript-Regular.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/DancingScript-Regular.woff2 rename to app/core/src/main/resources/static/fonts/DancingScript-Regular.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/Estonia.woff2 b/app/core/src/main/resources/static/fonts/Estonia.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/Estonia.woff2 rename to app/core/src/main/resources/static/fonts/Estonia.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/IndieFlower-Regular.woff2 b/app/core/src/main/resources/static/fonts/IndieFlower-Regular.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/IndieFlower-Regular.woff2 rename to app/core/src/main/resources/static/fonts/IndieFlower-Regular.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/Meiryo.ttf b/app/core/src/main/resources/static/fonts/Meiryo.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/Meiryo.ttf rename to app/core/src/main/resources/static/fonts/Meiryo.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/NotoSans-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSans-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/NotoSans-Regular.ttf rename to app/core/src/main/resources/static/fonts/NotoSans-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/NotoSansArabic-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSansArabic-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/NotoSansArabic-Regular.ttf rename to app/core/src/main/resources/static/fonts/NotoSansArabic-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/NotoSansJP-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSansJP-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/NotoSansJP-Regular.ttf rename to app/core/src/main/resources/static/fonts/NotoSansJP-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/NotoSansSC-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSansSC-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/NotoSansSC-Regular.ttf rename to app/core/src/main/resources/static/fonts/NotoSansSC-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/NotoSansThai-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSansThai-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/NotoSansThai-Regular.ttf rename to app/core/src/main/resources/static/fonts/NotoSansThai-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/SimSun.ttf b/app/core/src/main/resources/static/fonts/SimSun.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/SimSun.ttf rename to app/core/src/main/resources/static/fonts/SimSun.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/Tangerine.woff2 b/app/core/src/main/resources/static/fonts/Tangerine.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/Tangerine.woff2 rename to app/core/src/main/resources/static/fonts/Tangerine.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/Tinos-Regular.woff2 b/app/core/src/main/resources/static/fonts/Tinos-Regular.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/Tinos-Regular.woff2 rename to app/core/src/main/resources/static/fonts/Tinos-Regular.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/google-symbol.woff2 b/app/core/src/main/resources/static/fonts/google-symbol.woff2 similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/google-symbol.woff2 rename to app/core/src/main/resources/static/fonts/google-symbol.woff2 diff --git a/stirling-pdf/src/main/resources/static/fonts/malgun.ttf b/app/core/src/main/resources/static/fonts/malgun.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/malgun.ttf rename to app/core/src/main/resources/static/fonts/malgun.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/static/NotoSansArabic-Regular.ttf b/app/core/src/main/resources/static/fonts/static/NotoSansArabic-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/static/NotoSansArabic-Regular.ttf rename to app/core/src/main/resources/static/fonts/static/NotoSansArabic-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/fonts/static/NotoSansJP-Regular.ttf b/app/core/src/main/resources/static/fonts/static/NotoSansJP-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/fonts/static/NotoSansJP-Regular.ttf rename to app/core/src/main/resources/static/fonts/static/NotoSansJP-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/images/Files.svg b/app/core/src/main/resources/static/images/Files.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/Files.svg rename to app/core/src/main/resources/static/images/Files.svg diff --git a/stirling-pdf/src/main/resources/static/images/arrow-right-short.svg b/app/core/src/main/resources/static/images/arrow-right-short.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/arrow-right-short.svg rename to app/core/src/main/resources/static/images/arrow-right-short.svg diff --git a/stirling-pdf/src/main/resources/static/images/book.svg b/app/core/src/main/resources/static/images/book.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/book.svg rename to app/core/src/main/resources/static/images/book.svg diff --git a/stirling-pdf/src/main/resources/static/images/clipboard.svg b/app/core/src/main/resources/static/images/clipboard.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/clipboard.svg rename to app/core/src/main/resources/static/images/clipboard.svg diff --git a/stirling-pdf/src/main/resources/static/images/discord.svg b/app/core/src/main/resources/static/images/discord.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/discord.svg rename to app/core/src/main/resources/static/images/discord.svg diff --git a/stirling-pdf/src/main/resources/static/images/docker.svg b/app/core/src/main/resources/static/images/docker.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/docker.svg rename to app/core/src/main/resources/static/images/docker.svg diff --git a/stirling-pdf/src/main/resources/static/images/file-earmark-pdf.svg b/app/core/src/main/resources/static/images/file-earmark-pdf.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/file-earmark-pdf.svg rename to app/core/src/main/resources/static/images/file-earmark-pdf.svg diff --git a/stirling-pdf/src/main/resources/static/images/github.svg b/app/core/src/main/resources/static/images/github.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/github.svg rename to app/core/src/main/resources/static/images/github.svg diff --git a/stirling-pdf/src/main/resources/static/images/google-drive.svg b/app/core/src/main/resources/static/images/google-drive.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/google-drive.svg rename to app/core/src/main/resources/static/images/google-drive.svg diff --git a/stirling-pdf/src/main/resources/static/images/redact-auto.svg b/app/core/src/main/resources/static/images/redact-auto.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/redact-auto.svg rename to app/core/src/main/resources/static/images/redact-auto.svg diff --git a/stirling-pdf/src/main/resources/static/images/redact-manual.svg b/app/core/src/main/resources/static/images/redact-manual.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/redact-manual.svg rename to app/core/src/main/resources/static/images/redact-manual.svg diff --git a/stirling-pdf/src/main/resources/static/images/rename.svg b/app/core/src/main/resources/static/images/rename.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/rename.svg rename to app/core/src/main/resources/static/images/rename.svg diff --git a/stirling-pdf/src/main/resources/static/images/signature.png b/app/core/src/main/resources/static/images/signature.png similarity index 100% rename from stirling-pdf/src/main/resources/static/images/signature.png rename to app/core/src/main/resources/static/images/signature.png diff --git a/stirling-pdf/src/main/resources/static/images/split-auto.svg b/app/core/src/main/resources/static/images/split-auto.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/split-auto.svg rename to app/core/src/main/resources/static/images/split-auto.svg diff --git a/stirling-pdf/src/main/resources/static/images/split-chapters.svg b/app/core/src/main/resources/static/images/split-chapters.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/split-chapters.svg rename to app/core/src/main/resources/static/images/split-chapters.svg diff --git a/stirling-pdf/src/main/resources/static/images/split-size.svg b/app/core/src/main/resources/static/images/split-size.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/split-size.svg rename to app/core/src/main/resources/static/images/split-size.svg diff --git a/stirling-pdf/src/main/resources/static/images/update.svg b/app/core/src/main/resources/static/images/update.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/images/update.svg rename to app/core/src/main/resources/static/images/update.svg diff --git a/stirling-pdf/src/main/resources/static/js/DecryptFiles.js b/app/core/src/main/resources/static/js/DecryptFiles.js similarity index 91% rename from stirling-pdf/src/main/resources/static/js/DecryptFiles.js rename to app/core/src/main/resources/static/js/DecryptFiles.js index 6701649c3..67349a012 100644 --- a/stirling-pdf/src/main/resources/static/js/DecryptFiles.js +++ b/app/core/src/main/resources/static/js/DecryptFiles.js @@ -125,6 +125,16 @@ export class DecryptFile { } else if (error.code === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { return {isEncrypted: true, requiresPassword: false}; } + } else if (error.name === 'InvalidPDFException' || + (error.message && error.message.includes('Invalid PDF structure'))) { + // Handle corrupted PDF files + console.error('Corrupted PDF detected:', error); + this.showErrorBanner( + `${window.stirlingPDF.pdfCorruptedMessage.replace('{0}', file.name)}`, + error.stack || '', + `${window.stirlingPDF.tryRepairMessage}` + ); + throw new Error('PDF file is corrupted.'); } console.error('Error checking encryption:', error); diff --git a/stirling-pdf/src/main/resources/static/js/cacheFormInputs.js b/app/core/src/main/resources/static/js/cacheFormInputs.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/cacheFormInputs.js rename to app/core/src/main/resources/static/js/cacheFormInputs.js diff --git a/stirling-pdf/src/main/resources/static/js/compare/diff.js b/app/core/src/main/resources/static/js/compare/diff.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/compare/diff.js rename to app/core/src/main/resources/static/js/compare/diff.js diff --git a/stirling-pdf/src/main/resources/static/js/compare/pdfWorker.js b/app/core/src/main/resources/static/js/compare/pdfWorker.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/compare/pdfWorker.js rename to app/core/src/main/resources/static/js/compare/pdfWorker.js diff --git a/stirling-pdf/src/main/resources/static/js/csrf.js b/app/core/src/main/resources/static/js/csrf.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/csrf.js rename to app/core/src/main/resources/static/js/csrf.js diff --git a/stirling-pdf/src/main/resources/static/js/darkmode.js b/app/core/src/main/resources/static/js/darkmode.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/darkmode.js rename to app/core/src/main/resources/static/js/darkmode.js diff --git a/stirling-pdf/src/main/resources/static/js/download.js b/app/core/src/main/resources/static/js/download.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/download.js rename to app/core/src/main/resources/static/js/download.js diff --git a/stirling-pdf/src/main/resources/static/js/downloader.js b/app/core/src/main/resources/static/js/downloader.js similarity index 93% rename from stirling-pdf/src/main/resources/static/js/downloader.js rename to app/core/src/main/resources/static/js/downloader.js index 7bdcd83d5..42ba0c357 100644 --- a/stirling-pdf/src/main/resources/static/js/downloader.js +++ b/app/core/src/main/resources/static/js/downloader.js @@ -2,6 +2,13 @@ if (window.isDownloadScriptInitialized) return; // Prevent re-execution window.isDownloadScriptInitialized = true; + // Global PDF processing count tracking for survey system + window.incrementPdfProcessingCount = function() { + let pdfProcessingCount = parseInt(localStorage.getItem('pdfProcessingCount') || '0'); + pdfProcessingCount++; + localStorage.setItem('pdfProcessingCount', pdfProcessingCount.toString()); + }; + const { pdfPasswordPrompt, multipleInputsForSingleRequest, @@ -193,13 +200,13 @@ if (error.name === 'PasswordException' && error.code === 1) { console.log(`PDF requires password: ${file.name}`, error); console.log(`Attempting to remove password from PDF: ${file.name} with password.`); - const password = prompt(`${window.translations.decrypt.passwordPrompt}`); + const password = prompt(`${window.decrypt.passwordPrompt}`); if (!password) { console.error(`No password provided for encrypted PDF: ${file.name}`); showErrorBanner( - `${window.translations.decrypt.noPassword.replace('{0}', file.name)}`, - `${window.translations.decrypt.unexpectedError}` + `${window.decrypt.noPassword.replace('{0}', file.name)}`, + `${window.decrypt.unexpectedError}` ); throw error; } @@ -233,11 +240,20 @@ } catch (decryptError) { console.error(`Failed to decrypt PDF: ${file.name}`, decryptError); showErrorBanner( - `${window.translations.invalidPasswordHeader.replace('{0}', file.name)}`, - `${window.translations.invalidPassword}` + `${window.decrypt.invalidPasswordHeader.replace('{0}', file.name)}`, + `${window.decrypt.invalidPassword}` ); throw decryptError; } + } else if (error.name === 'InvalidPDFException' || + (error.message && error.message.includes('Invalid PDF structure'))) { + // Handle corrupted PDF files + console.log(`Corrupted PDF detected: ${file.name}`, error); + showErrorBanner( + `${window.stirlingPDF.pdfCorruptedMessage.replace('{0}', file.name)}`, + `${window.stirlingPDF.tryRepairMessage}` + ); + throw error; } else { console.log(`Error loading PDF: ${file.name}`, error); throw error; @@ -303,6 +319,11 @@ pdf_pages: pageCount, }); } + + // Increment PDF processing count for survey tracking + if (success && typeof window.incrementPdfProcessingCount === 'function') { + window.incrementPdfProcessingCount(); + } } } diff --git a/stirling-pdf/src/main/resources/static/js/draggable-utils.js b/app/core/src/main/resources/static/js/draggable-utils.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/draggable-utils.js rename to app/core/src/main/resources/static/js/draggable-utils.js diff --git a/stirling-pdf/src/main/resources/static/js/errorBanner.js b/app/core/src/main/resources/static/js/errorBanner.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/errorBanner.js rename to app/core/src/main/resources/static/js/errorBanner.js diff --git a/stirling-pdf/src/main/resources/static/js/favourites.js b/app/core/src/main/resources/static/js/favourites.js similarity index 90% rename from stirling-pdf/src/main/resources/static/js/favourites.js rename to app/core/src/main/resources/static/js/favourites.js index 913c656b2..169cf53d9 100644 --- a/stirling-pdf/src/main/resources/static/js/favourites.js +++ b/app/core/src/main/resources/static/js/favourites.js @@ -44,8 +44,16 @@ function updateFavoritesDropdown() { contentWrapper.style.color = 'inherit'; // Clone the original content - var originalContent = navbarEntry.querySelector('div').cloneNode(true); - contentWrapper.appendChild(originalContent); + var divElement = navbarEntry.querySelector('div'); + if (divElement) { + var originalContent = divElement.cloneNode(true); + contentWrapper.appendChild(originalContent); + } else { + // Fallback: create content manually if div is not found + var fallbackContent = document.createElement('div'); + fallbackContent.innerHTML = navbarEntry.innerHTML; + contentWrapper.appendChild(fallbackContent); + } // Create the remove button var removeButton = document.createElement('button'); diff --git a/stirling-pdf/src/main/resources/static/js/fetch-utils.js b/app/core/src/main/resources/static/js/fetch-utils.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/fetch-utils.js rename to app/core/src/main/resources/static/js/fetch-utils.js diff --git a/stirling-pdf/src/main/resources/static/js/file-icon-factory.js b/app/core/src/main/resources/static/js/file-icon-factory.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/file-icon-factory.js rename to app/core/src/main/resources/static/js/file-icon-factory.js diff --git a/stirling-pdf/src/main/resources/static/js/file-utils.js b/app/core/src/main/resources/static/js/file-utils.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/file-utils.js rename to app/core/src/main/resources/static/js/file-utils.js diff --git a/stirling-pdf/src/main/resources/static/js/fileInput.js b/app/core/src/main/resources/static/js/fileInput.js similarity index 97% rename from stirling-pdf/src/main/resources/static/js/fileInput.js rename to app/core/src/main/resources/static/js/fileInput.js index f06371986..71b6a1ebf 100644 --- a/stirling-pdf/src/main/resources/static/js/fileInput.js +++ b/app/core/src/main/resources/static/js/fileInput.js @@ -226,7 +226,8 @@ function setupFileInput(chooser) { try { const { isEncrypted, requiresPassword } = await decryptFile.checkFileEncrypted(file); - if (file.type === 'application/pdf' && isEncrypted) { + if (file.type === 'application/pdf' && isEncrypted && + !window.location.pathname.includes('remove-password')) { decryptedFile = await decryptFile.decryptFile(file, requiresPassword); if (!decryptedFile) throw new Error('File decryption failed.'); } @@ -235,6 +236,13 @@ function setupFileInput(chooser) { } catch (error) { console.error(`Error decrypting file: ${file.name}`, error); + + // Check if this is a PDF corruption error + if (error.message && error.message.includes('PDF file is corrupted')) { + // The error banner is already shown by DecryptFiles.js, just continue with the file + console.warn(`Continuing with corrupted PDF file: ${file.name}`); + } + if (!file.uniqueId) file.uniqueId = UUID.uuidv4(); return file; } diff --git a/stirling-pdf/src/main/resources/static/js/game.js b/app/core/src/main/resources/static/js/game.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/game.js rename to app/core/src/main/resources/static/js/game.js diff --git a/stirling-pdf/src/main/resources/static/js/githubVersion.js b/app/core/src/main/resources/static/js/githubVersion.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/githubVersion.js rename to app/core/src/main/resources/static/js/githubVersion.js diff --git a/stirling-pdf/src/main/resources/static/js/googleFilePicker.js b/app/core/src/main/resources/static/js/googleFilePicker.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/googleFilePicker.js rename to app/core/src/main/resources/static/js/googleFilePicker.js diff --git a/stirling-pdf/src/main/resources/static/js/homecard-legacy.js b/app/core/src/main/resources/static/js/homecard-legacy.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/homecard-legacy.js rename to app/core/src/main/resources/static/js/homecard-legacy.js diff --git a/stirling-pdf/src/main/resources/static/js/homecard.js b/app/core/src/main/resources/static/js/homecard.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/homecard.js rename to app/core/src/main/resources/static/js/homecard.js diff --git a/stirling-pdf/src/main/resources/static/js/languageSelection.js b/app/core/src/main/resources/static/js/languageSelection.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/languageSelection.js rename to app/core/src/main/resources/static/js/languageSelection.js diff --git a/stirling-pdf/src/main/resources/static/js/local-pdf-input-download.js b/app/core/src/main/resources/static/js/local-pdf-input-download.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/local-pdf-input-download.js rename to app/core/src/main/resources/static/js/local-pdf-input-download.js diff --git a/stirling-pdf/src/main/resources/static/js/merge.js b/app/core/src/main/resources/static/js/merge.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/merge.js rename to app/core/src/main/resources/static/js/merge.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/DragDropManager.js b/app/core/src/main/resources/static/js/multitool/DragDropManager.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/DragDropManager.js rename to app/core/src/main/resources/static/js/multitool/DragDropManager.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/ImageHighlighter.js b/app/core/src/main/resources/static/js/multitool/ImageHighlighter.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/ImageHighlighter.js rename to app/core/src/main/resources/static/js/multitool/ImageHighlighter.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/PdfActionsManager.js b/app/core/src/main/resources/static/js/multitool/PdfActionsManager.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/PdfActionsManager.js rename to app/core/src/main/resources/static/js/multitool/PdfActionsManager.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/PdfContainer.js b/app/core/src/main/resources/static/js/multitool/PdfContainer.js similarity index 99% rename from stirling-pdf/src/main/resources/static/js/multitool/PdfContainer.js rename to app/core/src/main/resources/static/js/multitool/PdfContainer.js index 90d130b2f..125801a0a 100644 --- a/stirling-pdf/src/main/resources/static/js/multitool/PdfContainer.js +++ b/app/core/src/main/resources/static/js/multitool/PdfContainer.js @@ -271,6 +271,11 @@ class PdfContainer { pdf_pages: pageCount, }); } + + // Increment PDF processing count for survey tracking + if (success && typeof window.incrementPdfProcessingCount === 'function') { + window.incrementPdfProcessingCount(); + } } catch { } } diff --git a/stirling-pdf/src/main/resources/static/js/multitool/UndoManager.js b/app/core/src/main/resources/static/js/multitool/UndoManager.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/UndoManager.js rename to app/core/src/main/resources/static/js/multitool/UndoManager.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/add-page.js b/app/core/src/main/resources/static/js/multitool/commands/add-page.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/add-page.js rename to app/core/src/main/resources/static/js/multitool/commands/add-page.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/command.js b/app/core/src/main/resources/static/js/multitool/commands/command.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/command.js rename to app/core/src/main/resources/static/js/multitool/commands/command.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/commands-sequence.js b/app/core/src/main/resources/static/js/multitool/commands/commands-sequence.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/commands-sequence.js rename to app/core/src/main/resources/static/js/multitool/commands/commands-sequence.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/delete-page.js b/app/core/src/main/resources/static/js/multitool/commands/delete-page.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/delete-page.js rename to app/core/src/main/resources/static/js/multitool/commands/delete-page.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/move-page.js b/app/core/src/main/resources/static/js/multitool/commands/move-page.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/move-page.js rename to app/core/src/main/resources/static/js/multitool/commands/move-page.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/page-break.js b/app/core/src/main/resources/static/js/multitool/commands/page-break.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/page-break.js rename to app/core/src/main/resources/static/js/multitool/commands/page-break.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/remove.js b/app/core/src/main/resources/static/js/multitool/commands/remove.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/remove.js rename to app/core/src/main/resources/static/js/multitool/commands/remove.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/rotate.js b/app/core/src/main/resources/static/js/multitool/commands/rotate.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/rotate.js rename to app/core/src/main/resources/static/js/multitool/commands/rotate.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/select.js b/app/core/src/main/resources/static/js/multitool/commands/select.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/select.js rename to app/core/src/main/resources/static/js/multitool/commands/select.js diff --git a/stirling-pdf/src/main/resources/static/js/multitool/commands/split.js b/app/core/src/main/resources/static/js/multitool/commands/split.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/multitool/commands/split.js rename to app/core/src/main/resources/static/js/multitool/commands/split.js diff --git a/stirling-pdf/src/main/resources/static/js/navbar.js b/app/core/src/main/resources/static/js/navbar.js similarity index 52% rename from stirling-pdf/src/main/resources/static/js/navbar.js rename to app/core/src/main/resources/static/js/navbar.js index 1d8c0dcce..a95ff1639 100644 --- a/stirling-pdf/src/main/resources/static/js/navbar.js +++ b/app/core/src/main/resources/static/js/navbar.js @@ -42,6 +42,39 @@ function toolsManager() { }); } +function setupDropdowns() { + const dropdowns = document.querySelectorAll('.navbar-nav > .nav-item.dropdown'); + + dropdowns.forEach((dropdown) => { + const toggle = dropdown.querySelector('[data-bs-toggle="dropdown"]'); + if (!toggle) return; + + // Skip search dropdown, it has its own logic + if (toggle.id === 'searchDropdown') { + return; + } + + dropdown.addEventListener('show.bs.dropdown', () => { + // Find all other open dropdowns and hide them + const openDropdowns = document.querySelectorAll('.navbar-nav .dropdown-menu.show'); + openDropdowns.forEach((menu) => { + const parentDropdown = menu.closest('.dropdown'); + if (parentDropdown && parentDropdown !== dropdown) { + const parentToggle = parentDropdown.querySelector('[data-bs-toggle="dropdown"]'); + if (parentToggle) { + // Get or create Bootstrap dropdown instance + let instance = bootstrap.Dropdown.getInstance(parentToggle); + if (!instance) { + instance = new bootstrap.Dropdown(parentToggle); + } + instance.hide(); + } + } + }); + }); + }); +} + window.tooltipSetup = () => { const tooltipElements = document.querySelectorAll('[title]'); @@ -56,23 +89,54 @@ window.tooltipSetup = () => { document.body.appendChild(customTooltip); element.addEventListener('mouseenter', (event) => { - customTooltip.style.display = 'block'; - customTooltip.style.left = `${event.pageX + 10}px`; // Position tooltip slightly away from the cursor - customTooltip.style.top = `${event.pageY + 10}px`; + if (window.innerWidth >= 1200) { + customTooltip.style.display = 'block'; + customTooltip.style.left = `${event.pageX + 10}px`; + customTooltip.style.top = `${event.pageY + 10}px`; + } }); - // Update the position of the tooltip as the user moves the mouse element.addEventListener('mousemove', (event) => { - customTooltip.style.left = `${event.pageX + 10}px`; - customTooltip.style.top = `${event.pageY + 10}px`; + if (window.innerWidth >= 1200) { + customTooltip.style.left = `${event.pageX + 10}px`; + customTooltip.style.top = `${event.pageY + 10}px`; + } }); - // Hide the tooltip when the mouse leaves element.addEventListener('mouseleave', () => { customTooltip.style.display = 'none'; }); }); }; + +// Override the bootstrap dropdown styles for mobile +function fixNavbarDropdownStyles() { + if (window.innerWidth < 1200) { + document.querySelectorAll('.navbar .dropdown-menu').forEach(function(menu) { + menu.style.transform = 'none'; + menu.style.transformOrigin = 'none'; + menu.style.left = '0'; + menu.style.right = '0'; + menu.style.maxWidth = '95vw'; + menu.style.width = '100vw'; + menu.style.marginBottom = '0'; + }); + } else { + document.querySelectorAll('.navbar .dropdown-menu').forEach(function(menu) { + menu.style.transform = ''; + menu.style.transformOrigin = ''; + menu.style.left = ''; + menu.style.right = ''; + menu.style.maxWidth = ''; + menu.style.width = ''; + menu.style.marginBottom = ''; + }); + } +} + document.addEventListener('DOMContentLoaded', () => { tooltipSetup(); + setupDropdowns(); + fixNavbarDropdownStyles(); }); +window.addEventListener('resize', fixNavbarDropdownStyles); diff --git a/stirling-pdf/src/main/resources/static/js/pages/add-image.js b/app/core/src/main/resources/static/js/pages/add-image.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/add-image.js rename to app/core/src/main/resources/static/js/pages/add-image.js diff --git a/stirling-pdf/src/main/resources/static/js/pages/adjust-contrast.js b/app/core/src/main/resources/static/js/pages/adjust-contrast.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/adjust-contrast.js rename to app/core/src/main/resources/static/js/pages/adjust-contrast.js diff --git a/stirling-pdf/src/main/resources/static/js/pages/change-metadata.js b/app/core/src/main/resources/static/js/pages/change-metadata.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/change-metadata.js rename to app/core/src/main/resources/static/js/pages/change-metadata.js diff --git a/stirling-pdf/src/main/resources/static/js/pages/crop.js b/app/core/src/main/resources/static/js/pages/crop.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/crop.js rename to app/core/src/main/resources/static/js/pages/crop.js diff --git a/stirling-pdf/src/main/resources/static/js/pages/edit-table-of-contents.js b/app/core/src/main/resources/static/js/pages/edit-table-of-contents.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/edit-table-of-contents.js rename to app/core/src/main/resources/static/js/pages/edit-table-of-contents.js diff --git a/stirling-pdf/src/main/resources/static/js/pages/home.js b/app/core/src/main/resources/static/js/pages/home.js similarity index 93% rename from stirling-pdf/src/main/resources/static/js/pages/home.js rename to app/core/src/main/resources/static/js/pages/home.js index bb1e1ad4a..a2673ef6c 100644 --- a/stirling-pdf/src/main/resources/static/js/pages/home.js +++ b/app/core/src/main/resources/static/js/pages/home.js @@ -66,19 +66,16 @@ document.addEventListener('DOMContentLoaded', function () { const dontShowAgain = document.getElementById('dontShowAgain'); const takeSurveyButton = document.getElementById('takeSurvey'); - const viewThresholds = [5, 10, 15, 22, 30, 50, 75, 100, 150, 200]; + const pdfProcessingThresholds = [8, 15, 22, 35, 50, 75, 100, 150]; - // Check if survey version changed and reset page views if it did + // Check if survey version changed and reset PDF processing count if it did const storedVersion = localStorage.getItem('surveyVersion'); if (storedVersion && storedVersion !== surveyVersion) { - localStorage.setItem('pageViews', '0'); + localStorage.setItem('pdfProcessingCount', '0'); localStorage.setItem('surveyVersion', surveyVersion); } - let pageViews = parseInt(localStorage.getItem('pageViews') || '0'); - - pageViews++; - localStorage.setItem('pageViews', pageViews.toString()); + let pdfProcessingCount = parseInt(localStorage.getItem('pdfProcessingCount') || '0'); function shouldShowSurvey() { if(!window.showSurvey) { @@ -90,11 +87,11 @@ document.addEventListener('DOMContentLoaded', function () { } // If survey version changed and we hit a threshold, show the survey - if (localStorage.getItem('surveyVersion') !== surveyVersion && viewThresholds.includes(pageViews)) { + if (localStorage.getItem('surveyVersion') !== surveyVersion && pdfProcessingThresholds.includes(pdfProcessingCount)) { return true; } - return viewThresholds.includes(pageViews); + return pdfProcessingThresholds.includes(pdfProcessingCount); } if (shouldShowSurvey()) { diff --git a/stirling-pdf/src/main/resources/static/js/pages/pdf-to-csv.js b/app/core/src/main/resources/static/js/pages/pdf-to-csv.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/pdf-to-csv.js rename to app/core/src/main/resources/static/js/pages/pdf-to-csv.js diff --git a/stirling-pdf/src/main/resources/static/js/pages/sign.js b/app/core/src/main/resources/static/js/pages/sign.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pages/sign.js rename to app/core/src/main/resources/static/js/pages/sign.js diff --git a/stirling-pdf/src/main/resources/static/js/pipeline.js b/app/core/src/main/resources/static/js/pipeline.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/pipeline.js rename to app/core/src/main/resources/static/js/pipeline.js diff --git a/stirling-pdf/src/main/resources/static/js/redact.js b/app/core/src/main/resources/static/js/redact.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/redact.js rename to app/core/src/main/resources/static/js/redact.js diff --git a/stirling-pdf/src/main/resources/static/js/search.js b/app/core/src/main/resources/static/js/search.js similarity index 54% rename from stirling-pdf/src/main/resources/static/js/search.js rename to app/core/src/main/resources/static/js/search.js index c7932965c..277d722a9 100644 --- a/stirling-pdf/src/main/resources/static/js/search.js +++ b/app/core/src/main/resources/static/js/search.js @@ -56,8 +56,16 @@ document.querySelector("#navbarSearchInput").addEventListener("input", function contentWrapper.style.textDecoration = "none"; contentWrapper.style.color = "inherit"; - var originalContent = item.querySelector("div").cloneNode(true); - contentWrapper.appendChild(originalContent); + var divElement = item.querySelector("div"); + if (divElement) { + var originalContent = divElement.cloneNode(true); + contentWrapper.appendChild(originalContent); + } else { + // Fallback: create content manually if div is not found + var fallbackContent = document.createElement("div"); + fallbackContent.innerHTML = item.innerHTML; + contentWrapper.appendChild(fallbackContent); + } contentWrapper.onclick = function () { window.location.href = itemHref; @@ -77,35 +85,52 @@ document.querySelector("#navbarSearchInput").addEventListener("input", function const searchDropdown = document.getElementById('searchDropdown'); const searchInput = document.getElementById('navbarSearchInput'); -const dropdownMenu = searchDropdown.querySelector('.dropdown-menu'); -// Handle dropdown shown event -searchDropdown.addEventListener('shown.bs.dropdown', function () { - searchInput.focus(); -}); +// Check if elements exist before proceeding +if (searchDropdown && searchInput) { + const dropdownMenu = searchDropdown.querySelector('.dropdown-menu'); -// Handle hover opening -searchDropdown.addEventListener('mouseenter', function () { + // Create a single dropdown instance const dropdownInstance = new bootstrap.Dropdown(searchDropdown); - dropdownInstance.show(); - setTimeout(() => { - searchInput.focus(); - }, 100); -}); +// Handle click for mobile + searchDropdown.addEventListener('click', function (e) { + e.preventDefault(); + const isOpen = dropdownMenu.classList.contains('show'); + // Close all other open dropdowns + document.querySelectorAll('.navbar-nav .dropdown-menu.show').forEach((menu) => { + if (menu !== dropdownMenu) { + const parentDropdown = menu.closest('.dropdown'); + if (parentDropdown) { + const parentToggle = parentDropdown.querySelector('[data-bs-toggle="dropdown"]'); + if (parentToggle) { + let instance = bootstrap.Dropdown.getInstance(parentToggle); + if (!instance) { + instance = new bootstrap.Dropdown(parentToggle); + } + instance.hide(); + } + } + } + }); + if (!isOpen) { + dropdownInstance.show(); + setTimeout(() => searchInput.focus(), 150); + } else { + dropdownInstance.hide(); + } + }); -// Handle mouse leave -searchDropdown.addEventListener('mouseleave', function () { - // Check if current value is empty (including if user typed and then deleted) - if (searchInput.value.trim().length === 0) { - searchInput.blur(); - const dropdownInstance = new bootstrap.Dropdown(searchDropdown); - dropdownInstance.hide(); - } -}); + // Hide dropdown if it's open and user clicks outside + document.addEventListener('click', function(e) { + if (!searchDropdown.contains(e.target) && dropdownMenu.classList.contains('show')) { + dropdownInstance.hide(); + } + }); -searchDropdown.addEventListener('hidden.bs.dropdown', function () { - if (searchInput.value.trim().length === 0) { - searchInput.blur(); - } -}); + // Keep dropdown open if search input is clicked + searchInput.addEventListener('click', function (e) { + e.stopPropagation(); + }); + +} diff --git a/stirling-pdf/src/main/resources/static/js/settings.js b/app/core/src/main/resources/static/js/settings.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/settings.js rename to app/core/src/main/resources/static/js/settings.js diff --git a/stirling-pdf/src/main/resources/static/js/sign/signature-canvas.js b/app/core/src/main/resources/static/js/sign/signature-canvas.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/sign/signature-canvas.js rename to app/core/src/main/resources/static/js/sign/signature-canvas.js diff --git a/stirling-pdf/src/main/resources/static/js/tab-container.js b/app/core/src/main/resources/static/js/tab-container.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/tab-container.js rename to app/core/src/main/resources/static/js/tab-container.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/bootstrap.min.js b/app/core/src/main/resources/static/js/thirdParty/bootstrap.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/bootstrap.min.js rename to app/core/src/main/resources/static/js/thirdParty/bootstrap.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/bootstrap.min.js.map b/app/core/src/main/resources/static/js/thirdParty/bootstrap.min.js.map similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/bootstrap.min.js.map rename to app/core/src/main/resources/static/js/thirdParty/bootstrap.min.js.map diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/chart.umd.min.js b/app/core/src/main/resources/static/js/thirdParty/chart.umd.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/chart.umd.min.js rename to app/core/src/main/resources/static/js/thirdParty/chart.umd.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/cookieconsent-config.js b/app/core/src/main/resources/static/js/thirdParty/cookieconsent-config.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/cookieconsent-config.js rename to app/core/src/main/resources/static/js/thirdParty/cookieconsent-config.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/cookieconsent.umd.js b/app/core/src/main/resources/static/js/thirdParty/cookieconsent.umd.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/cookieconsent.umd.js rename to app/core/src/main/resources/static/js/thirdParty/cookieconsent.umd.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/fontfaceobserver.standalone.js b/app/core/src/main/resources/static/js/thirdParty/fontfaceobserver.standalone.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/fontfaceobserver.standalone.js rename to app/core/src/main/resources/static/js/thirdParty/fontfaceobserver.standalone.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/interact.min.js b/app/core/src/main/resources/static/js/thirdParty/interact.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/interact.min.js rename to app/core/src/main/resources/static/js/thirdParty/interact.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/interact.min.js.map b/app/core/src/main/resources/static/js/thirdParty/interact.min.js.map similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/interact.min.js.map rename to app/core/src/main/resources/static/js/thirdParty/interact.min.js.map diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/jquery.min.js b/app/core/src/main/resources/static/js/thirdParty/jquery.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/jquery.min.js rename to app/core/src/main/resources/static/js/thirdParty/jquery.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/jquery.validate.min.js b/app/core/src/main/resources/static/js/thirdParty/jquery.validate.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/jquery.validate.min.js rename to app/core/src/main/resources/static/js/thirdParty/jquery.validate.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/jszip.min.js b/app/core/src/main/resources/static/js/thirdParty/jszip.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/jszip.min.js rename to app/core/src/main/resources/static/js/thirdParty/jszip.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/pdf-lib.min.js b/app/core/src/main/resources/static/js/thirdParty/pdf-lib.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/pdf-lib.min.js rename to app/core/src/main/resources/static/js/thirdParty/pdf-lib.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/pdf-lib.min.js.map b/app/core/src/main/resources/static/js/thirdParty/pdf-lib.min.js.map similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/pdf-lib.min.js.map rename to app/core/src/main/resources/static/js/thirdParty/pdf-lib.min.js.map diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/popper.min.js b/app/core/src/main/resources/static/js/thirdParty/popper.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/popper.min.js rename to app/core/src/main/resources/static/js/thirdParty/popper.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/popper.min.js.map b/app/core/src/main/resources/static/js/thirdParty/popper.min.js.map similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/popper.min.js.map rename to app/core/src/main/resources/static/js/thirdParty/popper.min.js.map diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/prism.js b/app/core/src/main/resources/static/js/thirdParty/prism.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/prism.js rename to app/core/src/main/resources/static/js/thirdParty/prism.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js b/app/core/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js rename to app/core/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js diff --git a/stirling-pdf/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js.map b/app/core/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js.map similarity index 100% rename from stirling-pdf/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js.map rename to app/core/src/main/resources/static/js/thirdParty/signature_pad.umd.min.js.map diff --git a/stirling-pdf/src/main/resources/static/js/usage.js b/app/core/src/main/resources/static/js/usage.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/usage.js rename to app/core/src/main/resources/static/js/usage.js diff --git a/stirling-pdf/src/main/resources/static/js/uuid.js b/app/core/src/main/resources/static/js/uuid.js similarity index 100% rename from stirling-pdf/src/main/resources/static/js/uuid.js rename to app/core/src/main/resources/static/js/uuid.js diff --git a/stirling-pdf/src/main/resources/static/manifest.json b/app/core/src/main/resources/static/manifest.json similarity index 100% rename from stirling-pdf/src/main/resources/static/manifest.json rename to app/core/src/main/resources/static/manifest.json diff --git a/stirling-pdf/src/main/resources/static/moon.svg b/app/core/src/main/resources/static/moon.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/moon.svg rename to app/core/src/main/resources/static/moon.svg diff --git a/stirling-pdf/src/main/resources/static/mstile-144x144.png b/app/core/src/main/resources/static/mstile-144x144.png similarity index 100% rename from stirling-pdf/src/main/resources/static/mstile-144x144.png rename to app/core/src/main/resources/static/mstile-144x144.png diff --git a/stirling-pdf/src/main/resources/static/mstile-150x150.png b/app/core/src/main/resources/static/mstile-150x150.png similarity index 100% rename from stirling-pdf/src/main/resources/static/mstile-150x150.png rename to app/core/src/main/resources/static/mstile-150x150.png diff --git a/stirling-pdf/src/main/resources/static/mstile-310x150.png b/app/core/src/main/resources/static/mstile-310x150.png similarity index 100% rename from stirling-pdf/src/main/resources/static/mstile-310x150.png rename to app/core/src/main/resources/static/mstile-310x150.png diff --git a/stirling-pdf/src/main/resources/static/mstile-310x310.png b/app/core/src/main/resources/static/mstile-310x310.png similarity index 100% rename from stirling-pdf/src/main/resources/static/mstile-310x310.png rename to app/core/src/main/resources/static/mstile-310x310.png diff --git a/stirling-pdf/src/main/resources/static/mstile-70x70.png b/app/core/src/main/resources/static/mstile-70x70.png similarity index 100% rename from stirling-pdf/src/main/resources/static/mstile-70x70.png rename to app/core/src/main/resources/static/mstile-70x70.png diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/78ms-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/83pv-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/83pv-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/83pv-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/83pv-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/90ms-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/90msp-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/90pv-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Add-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Add-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-0.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-0.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-0.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-0.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-1.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-1.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-1.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-1.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-3.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-3.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-3.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-3.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-4.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-4.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-4.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-4.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-5.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-5.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-5.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-5.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-6.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-6.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-6.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-6.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-UCS2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-UCS2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-UCS2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-CNS1-UCS2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-0.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-0.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-0.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-0.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-1.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-1.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-1.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-1.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-3.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-3.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-3.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-3.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-4.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-4.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-4.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-4.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-5.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-5.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-5.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-5.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-UCS2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-UCS2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-UCS2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-GB1-UCS2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-0.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-0.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-0.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-0.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-1.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-1.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-1.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-1.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-3.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-3.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-3.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-3.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-4.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-4.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-4.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-4.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-5.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-5.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-5.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-5.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-6.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-6.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-6.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-6.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-UCS2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-UCS2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-UCS2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Japan1-UCS2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-0.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-0.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-0.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-0.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-1.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-1.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-1.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-1.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-UCS2.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-UCS2.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-UCS2.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Adobe-Korea1-UCS2.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/B5pc-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS1-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/CNS2-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETHK-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETen-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/ETenms-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Ext-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Ext-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GB-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GB-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBK2K-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBKp-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBT-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBT-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBTpc-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/GBpc-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdla-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKdlb-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKgccs-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm314-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKm471-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/HKscs-B5-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Hankaku.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Hankaku.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Hankaku.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Hankaku.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Hiragana.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Hiragana.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Hiragana.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Hiragana.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-Johab-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-HW-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCms-UHC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/KSCpc-EUC-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Katakana.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Katakana.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Katakana.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Katakana.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/LICENSE b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/LICENSE similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/LICENSE rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/LICENSE diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/NWP-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/NWP-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/NWP-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/NWP-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/NWP-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/NWP-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/NWP-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/NWP-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/RKSJ-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Roman.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/Roman.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/Roman.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/Roman.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UCS2-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF16-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniCNS-UTF8-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UCS2-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF16-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniGB-UTF8-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-HW-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UCS2-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF16-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS-UTF8-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF16-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJIS2004-UTF8-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-HW-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-HW-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-HW-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-HW-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UCS2-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UTF8-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UTF8-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UTF8-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISPro-UTF8-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX0213-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniJISX02132004-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UCS2-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF16-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF32-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-H.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-H.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-H.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-H.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/UniKS-UTF8-V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/V.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/V.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/V.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/V.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/WP-Symbol.bcmap b/app/core/src/main/resources/static/pdfjs-legacy/cmaps/WP-Symbol.bcmap similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/cmaps/WP-Symbol.bcmap rename to app/core/src/main/resources/static/pdfjs-legacy/cmaps/WP-Symbol.bcmap diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/css/debugger.css b/app/core/src/main/resources/static/pdfjs-legacy/css/debugger.css similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/css/debugger.css rename to app/core/src/main/resources/static/pdfjs-legacy/css/debugger.css diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/css/viewer-redact.css b/app/core/src/main/resources/static/pdfjs-legacy/css/viewer-redact.css similarity index 99% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/css/viewer-redact.css rename to app/core/src/main/resources/static/pdfjs-legacy/css/viewer-redact.css index a5de6cecb..b8f43829d 100644 --- a/stirling-pdf/src/main/resources/static/pdfjs-legacy/css/viewer-redact.css +++ b/app/core/src/main/resources/static/pdfjs-legacy/css/viewer-redact.css @@ -1838,7 +1838,7 @@ height: 100%; } -.annotationEditorLayer freeTextEditor .overlay.enabled { +.annotationEditorLayer .freeTextEditor .overlay.enabled { display: block; } diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/css/viewer.css b/app/core/src/main/resources/static/pdfjs-legacy/css/viewer.css similarity index 99% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/css/viewer.css rename to app/core/src/main/resources/static/pdfjs-legacy/css/viewer.css index e431a4ad2..daec237cc 100644 --- a/stirling-pdf/src/main/resources/static/pdfjs-legacy/css/viewer.css +++ b/app/core/src/main/resources/static/pdfjs-legacy/css/viewer.css @@ -1852,7 +1852,7 @@ height:100%; } -.annotationEditorLayer freeTextEditor .overlay.enabled{ +.annotationEditorLayer .freeTextEditor .overlay.enabled{ display:block; } diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/example/Welcome.pdf b/app/core/src/main/resources/static/pdfjs-legacy/example/Welcome.pdf similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/example/Welcome.pdf rename to app/core/src/main/resources/static/pdfjs-legacy/example/Welcome.pdf diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/example/Welcome_old.pdf b/app/core/src/main/resources/static/pdfjs-legacy/example/Welcome_old.pdf similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/example/Welcome_old.pdf rename to app/core/src/main/resources/static/pdfjs-legacy/example/Welcome_old.pdf diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/altText_add.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/altText_add.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/altText_add.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/altText_add.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/altText_done.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/altText_done.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/altText_done.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/altText_done.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-check.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-check.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-check.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-check.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-comment.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-comment.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-comment.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-comment.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-help.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-help.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-help.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-help.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-insert.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-insert.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-insert.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-insert.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-key.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-key.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-key.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-key.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-newparagraph.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-newparagraph.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-newparagraph.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-newparagraph.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-noicon.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-noicon.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-noicon.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-noicon.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-note.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-note.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-note.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-note.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-paperclip.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-paperclip.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-paperclip.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-paperclip.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-paragraph.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-paragraph.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-paragraph.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-paragraph.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-pushpin.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/annotation-pushpin.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/annotation-pushpin.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/annotation-pushpin.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeHighlight.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeHighlight.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeHighlight.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeHighlight.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeText.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeText.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeText.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeText.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorInk.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorInk.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorInk.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorInk.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorTextHighlight.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorTextHighlight.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/cursor-editorTextHighlight.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/cursor-editorTextHighlight.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/editor-toolbar-delete.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/editor-toolbar-delete.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/editor-toolbar-delete.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/editor-toolbar-delete.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/findbarButton-next.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/findbarButton-next.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/findbarButton-next.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/findbarButton-next.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/findbarButton-previous.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/findbarButton-previous.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/findbarButton-previous.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/findbarButton-previous.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/gv-toolbarButton-download.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/gv-toolbarButton-download.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/gv-toolbarButton-download.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/gv-toolbarButton-download.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/loading-icon.gif b/app/core/src/main/resources/static/pdfjs-legacy/images/loading-icon.gif similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/loading-icon.gif rename to app/core/src/main/resources/static/pdfjs-legacy/images/loading-icon.gif diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/loading.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/loading.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/loading.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/loading.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-documentProperties.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-documentProperties.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-documentProperties.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-documentProperties.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-firstPage.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-firstPage.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-firstPage.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-firstPage.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-handTool.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-handTool.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-handTool.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-handTool.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-lastPage.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-lastPage.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-lastPage.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-lastPage.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCcw.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCcw.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCcw.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCcw.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCw.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCw.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCw.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCw.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollHorizontal.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollHorizontal.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollHorizontal.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollHorizontal.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollPage.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollPage.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollPage.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollPage.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollVertical.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollVertical.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollVertical.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollVertical.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollWrapped.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollWrapped.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollWrapped.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollWrapped.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-selectTool.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-selectTool.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-selectTool.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-selectTool.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadEven.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadEven.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadEven.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadEven.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadNone.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadNone.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadNone.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadNone.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadOdd.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadOdd.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadOdd.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadOdd.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-bookmark.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-bookmark.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-bookmark.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-bookmark.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-currentOutlineItem.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-currentOutlineItem.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-currentOutlineItem.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-currentOutlineItem.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-download.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-download.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-download.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-download.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorFreeText.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorFreeText.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorFreeText.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorFreeText.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorHighlight.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorHighlight.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorHighlight.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorHighlight.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorInk.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorInk.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorInk.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorInk.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorStamp.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorStamp.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorStamp.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorStamp.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-home.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-home.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-home.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-home.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-menuArrow.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-menuArrow.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-menuArrow.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-menuArrow.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-openFile.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-openFile.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-openFile.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-openFile.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageDown.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageDown.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageDown.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageDown.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageUp.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageUp.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageUp.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageUp.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-presentationMode.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-presentationMode.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-presentationMode.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-presentationMode.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-print.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-print.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-print.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-print.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-search.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-search.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-search.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-search.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-secondaryToolbarToggle.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-secondaryToolbarToggle.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-secondaryToolbarToggle.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-secondaryToolbarToggle.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-sidebarToggle.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-sidebarToggle.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-sidebarToggle.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-sidebarToggle.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewAttachments.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewAttachments.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewAttachments.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewAttachments.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewLayers.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewLayers.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewLayers.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewLayers.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewOutline.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewOutline.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewOutline.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewOutline.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewThumbnail.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewThumbnail.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewThumbnail.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewThumbnail.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomIn.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomIn.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomIn.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomIn.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomOut.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomOut.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomOut.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomOut.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/treeitem-collapsed.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/treeitem-collapsed.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/treeitem-collapsed.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/treeitem-collapsed.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/images/treeitem-expanded.svg b/app/core/src/main/resources/static/pdfjs-legacy/images/treeitem-expanded.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/images/treeitem-expanded.svg rename to app/core/src/main/resources/static/pdfjs-legacy/images/treeitem-expanded.svg diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/js/viewer.mjs b/app/core/src/main/resources/static/pdfjs-legacy/js/viewer.mjs similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/js/viewer.mjs rename to app/core/src/main/resources/static/pdfjs-legacy/js/viewer.mjs diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/js/viewer.mjs.map b/app/core/src/main/resources/static/pdfjs-legacy/js/viewer.mjs.map similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/js/viewer.mjs.map rename to app/core/src/main/resources/static/pdfjs-legacy/js/viewer.mjs.map diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ach/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ach/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ach/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ach/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/af/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/af/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/af/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/af/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/an/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/an/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/an/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/an/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ar/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ar/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ar/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ar/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ast/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ast/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ast/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ast/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/az/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/az/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/az/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/az/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/be/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/be/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/be/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/be/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bg/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/bg/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bg/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/bg/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bn/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/bn/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bn/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/bn/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bo/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/bo/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bo/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/bo/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/br/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/br/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/br/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/br/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/brx/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/brx/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/brx/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/brx/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bs/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/bs/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/bs/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/bs/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ca/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ca/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ca/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ca/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/cak/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/cak/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/cak/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/cak/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ckb/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ckb/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ckb/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ckb/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/cs/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/cs/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/cs/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/cs/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/cy/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/cy/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/cy/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/cy/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/da/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/da/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/da/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/da/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/de/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/de/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/de/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/de/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/dsb/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/dsb/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/dsb/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/dsb/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/el/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/el/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/el/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/el/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/en-CA/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/en-CA/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/en-CA/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/en-CA/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/en-GB/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/en-GB/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/en-GB/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/en-GB/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/en-US/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/en-US/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/en-US/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/en-US/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/eo/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/eo/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/eo/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/eo/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-AR/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/es-AR/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-AR/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/es-AR/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-CL/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/es-CL/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-CL/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/es-CL/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-ES/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/es-ES/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-ES/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/es-ES/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-MX/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/es-MX/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/es-MX/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/es-MX/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/et/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/et/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/et/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/et/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/eu/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/eu/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/eu/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/eu/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fa/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/fa/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fa/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/fa/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ff/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ff/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ff/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ff/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fi/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/fi/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fi/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/fi/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fr/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/fr/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fr/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/fr/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fur/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/fur/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fur/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/fur/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fy-NL/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/fy-NL/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/fy-NL/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/fy-NL/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ga-IE/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ga-IE/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ga-IE/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ga-IE/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gd/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/gd/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gd/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/gd/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gl/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/gl/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gl/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/gl/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gn/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/gn/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gn/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/gn/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gu-IN/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/gu-IN/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/gu-IN/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/gu-IN/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/he/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/he/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/he/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/he/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hi-IN/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/hi-IN/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hi-IN/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/hi-IN/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hr/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/hr/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hr/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/hr/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hsb/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/hsb/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hsb/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/hsb/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hu/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/hu/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hu/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/hu/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hy-AM/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/hy-AM/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hy-AM/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/hy-AM/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hye/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/hye/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/hye/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/hye/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ia/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ia/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ia/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ia/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/id/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/id/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/id/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/id/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/is/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/is/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/is/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/is/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/it/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/it/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/it/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/it/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ja/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ja/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ja/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ja/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ka/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ka/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ka/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ka/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/kab/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/kab/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/kab/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/kab/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/kk/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/kk/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/kk/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/kk/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/km/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/km/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/km/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/km/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/kn/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/kn/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/kn/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/kn/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ko/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ko/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ko/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ko/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lij/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/lij/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lij/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/lij/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lo/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/lo/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lo/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/lo/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/locale.json b/app/core/src/main/resources/static/pdfjs-legacy/locale/locale.json similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/locale.json rename to app/core/src/main/resources/static/pdfjs-legacy/locale/locale.json diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lt/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/lt/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lt/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/lt/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ltg/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ltg/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ltg/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ltg/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lv/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/lv/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/lv/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/lv/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/meh/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/meh/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/meh/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/meh/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/mk/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/mk/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/mk/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/mk/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/mr/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/mr/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/mr/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/mr/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ms/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ms/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ms/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ms/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/my/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/my/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/my/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/my/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/nb-NO/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/nb-NO/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/nb-NO/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/nb-NO/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ne-NP/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ne-NP/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ne-NP/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ne-NP/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/nl/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/nl/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/nl/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/nl/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/nn-NO/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/nn-NO/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/nn-NO/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/nn-NO/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/oc/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/oc/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/oc/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/oc/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pa-IN/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/pa-IN/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pa-IN/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/pa-IN/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pl/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/pl/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pl/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/pl/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pt-BR/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/pt-BR/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pt-BR/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/pt-BR/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pt-PT/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/pt-PT/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/pt-PT/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/pt-PT/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/rm/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/rm/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/rm/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/rm/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ro/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ro/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ro/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ro/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ru/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ru/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ru/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ru/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sat/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sat/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sat/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sat/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sc/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sc/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sc/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sc/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/scn/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/scn/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/scn/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/scn/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sco/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sco/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sco/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sco/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/si/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/si/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/si/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/si/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sk/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sk/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sk/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sk/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/skr/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/skr/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/skr/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/skr/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sl/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sl/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sl/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sl/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/son/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/son/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/son/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/son/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sq/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sq/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sq/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sq/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sr/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sr/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sr/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sr/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sv-SE/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/sv-SE/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/sv-SE/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/sv-SE/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/szl/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/szl/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/szl/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/szl/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ta/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ta/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ta/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ta/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/te/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/te/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/te/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/te/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/tg/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/tg/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/tg/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/tg/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/th/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/th/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/th/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/th/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/tl/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/tl/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/tl/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/tl/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/tr/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/tr/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/tr/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/tr/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/trs/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/trs/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/trs/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/trs/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/uk/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/uk/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/uk/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/uk/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ur/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/ur/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/ur/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/ur/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/uz/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/uz/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/uz/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/uz/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/vi/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/vi/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/vi/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/vi/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/wo/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/wo/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/wo/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/wo/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/xh/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/xh/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/xh/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/xh/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/zh-CN/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/zh-CN/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/zh-CN/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/zh-CN/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/zh-TW/viewer.ftl b/app/core/src/main/resources/static/pdfjs-legacy/locale/zh-TW/viewer.ftl similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/locale/zh-TW/viewer.ftl rename to app/core/src/main/resources/static/pdfjs-legacy/locale/zh-TW/viewer.ftl diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.mjs b/app/core/src/main/resources/static/pdfjs-legacy/pdf.mjs similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.mjs rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.mjs diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.mjs.map b/app/core/src/main/resources/static/pdfjs-legacy/pdf.mjs.map similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.mjs.map rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.mjs.map diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs b/app/core/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs.map b/app/core/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs.map similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs.map rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.sandbox.mjs.map diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.worker.entry.js b/app/core/src/main/resources/static/pdfjs-legacy/pdf.worker.entry.js similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.worker.entry.js rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.worker.entry.js diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs b/app/core/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs.map b/app/core/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs.map similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs.map rename to app/core/src/main/resources/static/pdfjs-legacy/pdf.worker.mjs.map diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitDingbats.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitDingbats.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitDingbats.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitDingbats.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixed.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixed.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixed.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixed.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBold.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBold.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBold.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBold.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBoldItalic.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBoldItalic.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBoldItalic.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedBoldItalic.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedItalic.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedItalic.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedItalic.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitFixedItalic.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerif.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerif.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerif.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerif.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBold.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBold.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBold.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBold.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBoldItalic.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBoldItalic.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBoldItalic.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifBoldItalic.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifItalic.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifItalic.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifItalic.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSerifItalic.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSymbol.pfb b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSymbol.pfb similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSymbol.pfb rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/FoxitSymbol.pfb diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_FOXIT b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_FOXIT similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_FOXIT rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_FOXIT diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_LIBERATION b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_LIBERATION similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_LIBERATION rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LICENSE_LIBERATION diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Bold.ttf b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Bold.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Bold.ttf rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Bold.ttf diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-BoldItalic.ttf b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-BoldItalic.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-BoldItalic.ttf rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-BoldItalic.ttf diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Italic.ttf b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Italic.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Italic.ttf rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Italic.ttf diff --git a/stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Regular.ttf b/app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Regular.ttf similarity index 100% rename from stirling-pdf/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Regular.ttf rename to app/core/src/main/resources/static/pdfjs-legacy/standard_fonts/LiberationSans-Regular.ttf diff --git a/stirling-pdf/src/main/resources/static/rainbow.svg b/app/core/src/main/resources/static/rainbow.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/rainbow.svg rename to app/core/src/main/resources/static/rainbow.svg diff --git a/stirling-pdf/src/main/resources/static/safari-pinned-tab.svg b/app/core/src/main/resources/static/safari-pinned-tab.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/safari-pinned-tab.svg rename to app/core/src/main/resources/static/safari-pinned-tab.svg diff --git a/stirling-pdf/src/main/resources/static/site.webmanifest b/app/core/src/main/resources/static/site.webmanifest similarity index 100% rename from stirling-pdf/src/main/resources/static/site.webmanifest rename to app/core/src/main/resources/static/site.webmanifest diff --git a/stirling-pdf/src/main/resources/static/sun.svg b/app/core/src/main/resources/static/sun.svg similarity index 100% rename from stirling-pdf/src/main/resources/static/sun.svg rename to app/core/src/main/resources/static/sun.svg diff --git a/stirling-pdf/src/main/resources/templates/about.html b/app/core/src/main/resources/templates/about.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/about.html rename to app/core/src/main/resources/templates/about.html diff --git a/stirling-pdf/src/main/resources/templates/account.html b/app/core/src/main/resources/templates/account.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/account.html rename to app/core/src/main/resources/templates/account.html diff --git a/stirling-pdf/src/main/resources/templates/adminSettings.html b/app/core/src/main/resources/templates/adminSettings.html similarity index 98% rename from stirling-pdf/src/main/resources/templates/adminSettings.html rename to app/core/src/main/resources/templates/adminSettings.html index 0d14525c1..4c2a7988b 100644 --- a/stirling-pdf/src/main/resources/templates/adminSettings.html +++ b/app/core/src/main/resources/templates/adminSettings.html @@ -206,7 +206,7 @@
@@ -214,7 +214,7 @@
@@ -222,7 +222,7 @@
@@ -279,7 +279,7 @@
@@ -287,7 +287,7 @@
diff --git a/stirling-pdf/src/main/resources/templates/auto-split-pdf.html b/app/core/src/main/resources/templates/auto-split-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/auto-split-pdf.html rename to app/core/src/main/resources/templates/auto-split-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/change-creds.html b/app/core/src/main/resources/templates/change-creds.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/change-creds.html rename to app/core/src/main/resources/templates/change-creds.html diff --git a/stirling-pdf/src/main/resources/templates/convert/eml-to-pdf.html b/app/core/src/main/resources/templates/convert/eml-to-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/eml-to-pdf.html rename to app/core/src/main/resources/templates/convert/eml-to-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/convert/file-to-pdf.html b/app/core/src/main/resources/templates/convert/file-to-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/file-to-pdf.html rename to app/core/src/main/resources/templates/convert/file-to-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/convert/html-to-pdf.html b/app/core/src/main/resources/templates/convert/html-to-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/html-to-pdf.html rename to app/core/src/main/resources/templates/convert/html-to-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/convert/img-to-pdf.html b/app/core/src/main/resources/templates/convert/img-to-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/img-to-pdf.html rename to app/core/src/main/resources/templates/convert/img-to-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/convert/markdown-to-pdf.html b/app/core/src/main/resources/templates/convert/markdown-to-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/markdown-to-pdf.html rename to app/core/src/main/resources/templates/convert/markdown-to-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-csv.html b/app/core/src/main/resources/templates/convert/pdf-to-csv.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-csv.html rename to app/core/src/main/resources/templates/convert/pdf-to-csv.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-html.html b/app/core/src/main/resources/templates/convert/pdf-to-html.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-html.html rename to app/core/src/main/resources/templates/convert/pdf-to-html.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-img.html b/app/core/src/main/resources/templates/convert/pdf-to-img.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-img.html rename to app/core/src/main/resources/templates/convert/pdf-to-img.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-markdown.html b/app/core/src/main/resources/templates/convert/pdf-to-markdown.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-markdown.html rename to app/core/src/main/resources/templates/convert/pdf-to-markdown.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-pdfa.html b/app/core/src/main/resources/templates/convert/pdf-to-pdfa.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-pdfa.html rename to app/core/src/main/resources/templates/convert/pdf-to-pdfa.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-presentation.html b/app/core/src/main/resources/templates/convert/pdf-to-presentation.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-presentation.html rename to app/core/src/main/resources/templates/convert/pdf-to-presentation.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-text.html b/app/core/src/main/resources/templates/convert/pdf-to-text.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-text.html rename to app/core/src/main/resources/templates/convert/pdf-to-text.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-word.html b/app/core/src/main/resources/templates/convert/pdf-to-word.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-word.html rename to app/core/src/main/resources/templates/convert/pdf-to-word.html diff --git a/stirling-pdf/src/main/resources/templates/convert/pdf-to-xml.html b/app/core/src/main/resources/templates/convert/pdf-to-xml.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/pdf-to-xml.html rename to app/core/src/main/resources/templates/convert/pdf-to-xml.html diff --git a/stirling-pdf/src/main/resources/templates/convert/url-to-pdf.html b/app/core/src/main/resources/templates/convert/url-to-pdf.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/convert/url-to-pdf.html rename to app/core/src/main/resources/templates/convert/url-to-pdf.html diff --git a/stirling-pdf/src/main/resources/templates/crop.html b/app/core/src/main/resources/templates/crop.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/crop.html rename to app/core/src/main/resources/templates/crop.html diff --git a/stirling-pdf/src/main/resources/templates/database.html b/app/core/src/main/resources/templates/database.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/database.html rename to app/core/src/main/resources/templates/database.html diff --git a/stirling-pdf/src/main/resources/templates/edit-table-of-contents.html b/app/core/src/main/resources/templates/edit-table-of-contents.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/edit-table-of-contents.html rename to app/core/src/main/resources/templates/edit-table-of-contents.html diff --git a/stirling-pdf/src/main/resources/templates/error.html b/app/core/src/main/resources/templates/error.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/error.html rename to app/core/src/main/resources/templates/error.html diff --git a/stirling-pdf/src/main/resources/templates/extract-page.html b/app/core/src/main/resources/templates/extract-page.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/extract-page.html rename to app/core/src/main/resources/templates/extract-page.html diff --git a/stirling-pdf/src/main/resources/templates/fragments/card.html b/app/core/src/main/resources/templates/fragments/card.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/fragments/card.html rename to app/core/src/main/resources/templates/fragments/card.html diff --git a/stirling-pdf/src/main/resources/templates/fragments/common.html b/app/core/src/main/resources/templates/fragments/common.html similarity index 74% rename from stirling-pdf/src/main/resources/templates/fragments/common.html rename to app/core/src/main/resources/templates/fragments/common.html index 38e71f04f..78f0d5662 100644 --- a/stirling-pdf/src/main/resources/templates/fragments/common.html +++ b/app/core/src/main/resources/templates/fragments/common.html @@ -23,6 +23,134 @@ @@ -250,6 +378,8 @@ window.stirlingPDF.uploadLimit = /*[[${@uploadLimitService.getUploadLimit()}]]*/ 0; window.stirlingPDF.uploadLimitExceededSingular = /*[[#{uploadLimitExceededSingular}]]*/ 'is too large. Maximum allowed size is'; window.stirlingPDF.uploadLimitExceededPlural = /*[[#{uploadLimitExceededPlural}]]*/ 'are too large. Maximum allowed size is'; + window.stirlingPDF.pdfCorruptedMessage = /*[[#{error.pdfInvalid}]]*/ 'The PDF file "{0}" appears to be corrupted or has an invalid structure. Please try using the \'Repair PDF\' feature to fix the file before proceeding.'; + window.stirlingPDF.tryRepairMessage = /*[[#{error.tryRepair}]]*/ 'Try using the Repair PDF feature to fix corrupted files.'; })(); @@ -287,10 +417,10 @@ Browse
-
-
-
-
+
+ + +

@@ -325,4 +455,4 @@ window.stirlingPDF.GoogleDriveAppId = /*[[${@GoogleDriveConfig.getAppId()}]]*/ null;
- \ No newline at end of file + diff --git a/stirling-pdf/src/main/resources/templates/fragments/errorBanner.html b/app/core/src/main/resources/templates/fragments/errorBanner.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/fragments/errorBanner.html rename to app/core/src/main/resources/templates/fragments/errorBanner.html diff --git a/stirling-pdf/src/main/resources/templates/fragments/errorBannerPerPage.html b/app/core/src/main/resources/templates/fragments/errorBannerPerPage.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/fragments/errorBannerPerPage.html rename to app/core/src/main/resources/templates/fragments/errorBannerPerPage.html diff --git a/stirling-pdf/src/main/resources/templates/fragments/featureGroupHeader.html b/app/core/src/main/resources/templates/fragments/featureGroupHeader.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/fragments/featureGroupHeader.html rename to app/core/src/main/resources/templates/fragments/featureGroupHeader.html diff --git a/stirling-pdf/src/main/resources/templates/fragments/featureGroupHeaderLegacy.html b/app/core/src/main/resources/templates/fragments/featureGroupHeaderLegacy.html similarity index 100% rename from stirling-pdf/src/main/resources/templates/fragments/featureGroupHeaderLegacy.html rename to app/core/src/main/resources/templates/fragments/featureGroupHeaderLegacy.html diff --git a/stirling-pdf/src/main/resources/templates/fragments/footer.html b/app/core/src/main/resources/templates/fragments/footer.html similarity index 95% rename from stirling-pdf/src/main/resources/templates/fragments/footer.html rename to app/core/src/main/resources/templates/fragments/footer.html index 324f550d9..2d8465bf5 100644 --- a/stirling-pdf/src/main/resources/templates/fragments/footer.html +++ b/app/core/src/main/resources/templates/fragments/footer.html @@ -1,7 +1,7 @@ -