Compare commits

..

4 Commits

Author SHA1 Message Date
Anthony Stirling
d797d700db Update licenses-update.yml 2025-01-15 19:31:48 +00:00
Anthony Stirling
ff1086b0d5 Update licenses-update.yml 2025-01-15 19:31:02 +00:00
Anthony Stirling
eb3c3cace0 Update build.gradle 2025-01-15 19:22:14 +00:00
Anthony Stirling
b2d1f20ebe Update licenses-update.yml 2025-01-15 19:11:57 +00:00
194 changed files with 11119 additions and 15486 deletions

2
.github/CODEOWNERS vendored
View File

@@ -1,2 +1,2 @@
# All PRs to V1 must be approved by Frooodle # All PRs to V1 must be approved by Frooodle
* @Frooodle @reecebrowne @Ludy87 @DarioGii @ConnorYoh * @Frooodle @reecebrowne @Ludy87 @DarioGii

View File

@@ -1,34 +1,15 @@
# Description of Changes # Description
Please provide a summary of the changes, including: Please provide a summary of the changes, including relevant motivation and context.
- What was changed
- Why the change was made
- Any challenges encountered
Closes #(issue_number) Closes #(issue_number)
---
## Checklist ## Checklist
### General
- [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have 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 performed a self-review of my own code - [ ] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [ ] My changes generate no new warnings - [ ] 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/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR)
### 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.

6
.github/release.yml vendored
View File

@@ -1,4 +1,10 @@
changelog: changelog:
exclude:
labels:
- Documentation
- Test
- Github
categories: categories:
- title: Bug Fixes - title: Bug Fixes
labels: labels:

51
.github/scripts/check_duplicates.py vendored Normal file
View File

@@ -0,0 +1,51 @@
import sys
def find_duplicate_keys(file_path):
"""
Finds duplicate keys in a properties file and returns their occurrences.
This function reads a properties file, identifies any keys that occur more than
once, and returns a dictionary with these keys and the line numbers of their occurrences.
Parameters:
file_path (str): The path to the properties file to be checked.
Returns:
dict: A dictionary where each key is a duplicated key in the file, and the value is a list
of line numbers where the key occurs.
"""
with open(file_path, "r", encoding="utf-8") as file:
lines = file.readlines()
keys = {}
duplicates = {}
for line_number, line in enumerate(lines, start=1):
line = line.strip()
if line and not line.startswith("#") and "=" in line:
key = line.split("=", 1)[0].strip()
if key in keys:
# If the key already exists, add the current line number
duplicates.setdefault(key, []).append(line_number)
# Also add the first instance of the key if not already done
if keys[key] not in duplicates[key]:
duplicates[key].insert(0, keys[key])
else:
# Store the line number of the first instance of the key
keys[key] = line_number
return duplicates
if __name__ == "__main__":
failed = False
for ar in sys.argv[1:]:
duplicates = find_duplicate_keys(ar)
if duplicates:
for key, lines in duplicates.items():
lines_str = ", ".join(map(str, lines))
print(f"{key} duplicated in {ar} on lines {lines_str}")
failed = True
if failed:
sys.exit(1)

View File

@@ -11,8 +11,6 @@ adjusting the format.
Usage: Usage:
python check_language_properties.py --reference-file <path_to_reference_file> --branch <branch_name> [--actor <actor_name>] [--files <list_of_changed_files>] python check_language_properties.py --reference-file <path_to_reference_file> --branch <branch_name> [--actor <actor_name>] [--files <list_of_changed_files>]
""" """
# Sample for Windows:
# python .github/scripts/check_language_properties.py --reference-file src\main\resources\messages_en_GB.properties --branch "" --files src\main\resources\messages_de_DE.properties src\main\resources\messages_uk_UA.properties
import copy import copy
import glob import glob
@@ -21,60 +19,25 @@ import argparse
import re import re
def find_duplicate_keys(file_path):
"""
Identifies duplicate keys in a .properties file.
:param file_path: Path to the .properties file.
:return: List of tuples (key, first_occurrence_line, duplicate_line).
"""
keys = {}
duplicates = []
with open(file_path, "r", encoding="utf-8") as file:
for line_number, line in enumerate(file, start=1):
stripped_line = line.strip()
# Skip empty lines and comments
if not stripped_line or stripped_line.startswith("#"):
continue
# Split the line into key and value
if "=" in stripped_line:
key, _ = stripped_line.split("=", 1)
key = key.strip()
# Check if the key already exists
if key in keys:
duplicates.append((key, keys[key], line_number))
else:
keys[key] = line_number
return duplicates
# Maximum size for properties files (e.g., 200 KB) # Maximum size for properties files (e.g., 200 KB)
MAX_FILE_SIZE = 200 * 1024 MAX_FILE_SIZE = 200 * 1024
def parse_properties_file(file_path): def parse_properties_file(file_path):
""" """Parses a .properties file and returns a list of objects (including comments, empty lines, and line numbers)."""
Parses a .properties file and returns a structured list of its contents.
:param file_path: Path to the .properties file.
:return: List of dictionaries representing each line in the file.
"""
properties_list = [] properties_list = []
with open(file_path, "r", encoding="utf-8") as file: with open(file_path, "r", encoding="utf-8") as file:
for line_number, line in enumerate(file, start=1): for line_number, line in enumerate(file, start=1):
stripped_line = line.strip() stripped_line = line.strip()
# Handle empty lines # Empty lines
if not stripped_line: if not stripped_line:
properties_list.append( properties_list.append(
{"line_number": line_number, "type": "empty", "content": ""} {"line_number": line_number, "type": "empty", "content": ""}
) )
continue continue
# Handle comments # Comments
if stripped_line.startswith("#"): if stripped_line.startswith("#"):
properties_list.append( properties_list.append(
{ {
@@ -85,7 +48,7 @@ def parse_properties_file(file_path):
) )
continue continue
# Handle key-value pairs # Key-value pairs
match = re.match(r"^([^=]+)=(.*)$", line) match = re.match(r"^([^=]+)=(.*)$", line)
if match: if match:
key, value = match.groups() key, value = match.groups()
@@ -102,14 +65,9 @@ def parse_properties_file(file_path):
def write_json_file(file_path, updated_properties): def write_json_file(file_path, updated_properties):
"""
Writes updated properties back to the file in their original format.
:param file_path: Path to the .properties file.
:param updated_properties: List of updated properties to write.
"""
updated_lines = {entry["line_number"]: entry for entry in updated_properties} updated_lines = {entry["line_number"]: entry for entry in updated_properties}
# Sort lines by their numbers and retain comments and empty lines # Sort by line numbers and retain comments and empty lines
all_lines = sorted(set(updated_lines.keys())) all_lines = sorted(set(updated_lines.keys()))
original_format = [] original_format = []
@@ -128,8 +86,8 @@ def write_json_file(file_path, updated_properties):
# Replace entries with those from the current JSON # Replace entries with those from the current JSON
original_format.append(entry) original_format.append(entry)
# Write the updated content back to the file # Write back in the original format
with open(file_path, "w", encoding="utf-8", newline="\n") as file: with open(file_path, "w", encoding="utf-8") as file:
for entry in original_format: for entry in original_format:
if entry["type"] == "comment": if entry["type"] == "comment":
file.write(f"{entry['content']}\n") file.write(f"{entry['content']}\n")
@@ -140,12 +98,6 @@ def write_json_file(file_path, updated_properties):
def update_missing_keys(reference_file, file_list, branch=""): def update_missing_keys(reference_file, file_list, branch=""):
"""
Updates missing keys in the translation files based on the reference file.
:param reference_file: Path to the reference .properties file.
:param file_list: List of translation files to update.
:param branch: Branch where the files are located.
"""
reference_properties = parse_properties_file(reference_file) reference_properties = parse_properties_file(reference_file)
for file_path in file_list: for file_path in file_list:
basename_current_file = os.path.basename(os.path.join(branch, file_path)) basename_current_file = os.path.basename(os.path.join(branch, file_path))
@@ -212,14 +164,8 @@ def check_for_differences(reference_file, file_list, branch, actor):
basename_current_file = os.path.basename(os.path.join(branch, file_path)) basename_current_file = os.path.basename(os.path.join(branch, file_path))
if ( if (
basename_current_file == basename_reference_file basename_current_file == basename_reference_file
or ( or not file_path.startswith(
# only local windows command os.path.join("src", "main", "resources", "messages_")
not file_path.startswith(
os.path.join("", "src", "main", "resources", "messages_")
)
and not file_path.startswith(
os.path.join(os.getcwd(), "src", "main", "resources", "messages_")
)
) )
or not file_path.endswith(".properties") or not file_path.endswith(".properties")
or not basename_current_file.startswith("messages_") or not basename_current_file.startswith("messages_")
@@ -291,24 +237,6 @@ def check_for_differences(reference_file, file_list, branch, actor):
) )
else: else:
report.append("2. **Test Status:** ✅ **_Passed_**") report.append("2. **Test Status:** ✅ **_Passed_**")
if find_duplicate_keys(os.path.join(branch, file_path)):
has_differences = True
output = "\n".join(
[
f" - `{key}`: first at line {first}, duplicate at `line {duplicate}`"
for key, first, duplicate in find_duplicate_keys(
os.path.join(branch, file_path)
)
]
)
report.append("3. **Test Status:** ❌ **_Failed_**")
report.append(" - **Issue:**")
report.append(" - duplicate entries were found:")
report.append(output)
else:
report.append("3. **Test Status:** ✅ **_Passed_**")
report.append("") report.append("")
report.append("---") report.append("---")
report.append("") report.append("")
@@ -347,12 +275,6 @@ if __name__ == "__main__":
required=True, required=True,
help="Branch name.", help="Branch name.",
) )
parser.add_argument(
"--check-file",
type=str,
required=False,
help="List of changed files, separated by spaces.",
)
parser.add_argument( parser.add_argument(
"--files", "--files",
nargs="+", nargs="+",
@@ -371,14 +293,11 @@ if __name__ == "__main__":
file_list = args.files file_list = args.files
if file_list is None: if file_list is None:
if args.check_file: file_list = glob.glob(
file_list = [args.check_file] os.path.join(
else: os.getcwd(), "src", "main", "resources", "messages_*.properties"
file_list = glob.glob(
os.path.join(
os.getcwd(), "src", "main", "resources", "messages_*.properties"
)
) )
)
update_missing_keys(args.reference_file, file_list) update_missing_keys(args.reference_file, file_list)
else: else:
check_for_differences(args.reference_file, file_list, args.branch, args.actor) check_for_differences(args.reference_file, file_list, args.branch, args.actor)

85
.github/scripts/check_tabulator.py vendored Normal file
View File

@@ -0,0 +1,85 @@
"""check_tabulator.py"""
import argparse
import sys
def check_tabs(file_path):
"""
Checks for tabs in the specified file.
Args:
file_path (str): The path to the file to be checked.
Returns:
bool: True if tabs are found, False otherwise.
"""
with open(file_path, "r", encoding="utf-8") as file:
content = file.read()
if "\t" in content:
print(f"Tab found in {file_path}")
return True
return False
def replace_tabs_with_spaces(file_path, replace_with=" "):
"""
Replaces tabs with a specified number of spaces in the file.
Args:
file_path (str): The path to the file where tabs will be replaced.
replace_with (str): The character(s) to replace tabs with. Defaults to two spaces.
"""
with open(file_path, "r", encoding="utf-8") as file:
content = file.read()
updated_content = content.replace("\t", replace_with)
with open(file_path, "w", encoding="utf-8") as file:
file.write(updated_content)
def main():
"""
Main function to replace tabs with spaces in the provided files.
The replacement character and files to check are taken from command line arguments.
"""
# Create ArgumentParser instance
parser = argparse.ArgumentParser(
description="Replace tabs in files with specified characters."
)
# Define optional argument `--replace_with`
parser.add_argument(
"--replace_with",
default=" ",
help="Character(s) to replace tabs with. Default is two spaces.",
)
# Define argument for file paths
parser.add_argument("files", metavar="FILE", nargs="+", help="Files to process.")
# Parse arguments
args = parser.parse_args()
# Extract replacement characters and files from the parsed arguments
replace_with = args.replace_with
files_checked = args.files
error = False
for file_path in files_checked:
if check_tabs(file_path):
replace_tabs_with_spaces(file_path, replace_with)
error = True
if error:
print("Error: Originally found tabs in HTML files, now replaced.")
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
main()

View File

@@ -27,8 +27,7 @@ jobs:
github.event.comment.user.login == 'LaserKaspar' || github.event.comment.user.login == 'LaserKaspar' ||
github.event.comment.user.login == 'sbplat' || github.event.comment.user.login == 'sbplat' ||
github.event.comment.user.login == 'reecebrowne' || github.event.comment.user.login == 'reecebrowne' ||
github.event.comment.user.login == 'DarioGii' || github.event.comment.user.login == 'DarioGii'
github.event.comment.user.login == 'ConnorYoh'
) )
outputs: outputs:
pr_number: ${{ steps.get-pr.outputs.pr_number }} pr_number: ${{ steps.get-pr.outputs.pr_number }}
@@ -37,7 +36,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -82,7 +81,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -94,7 +93,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "17" java-version: "17"
distribution: "temurin" distribution: "temurin"
@@ -120,7 +119,7 @@ jobs:
password: ${{ secrets.DOCKER_HUB_API }} password: ${{ secrets.DOCKER_HUB_API }}
- name: Build and push PR-specific image - name: Build and push PR-specific image
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile

View File

@@ -21,7 +21,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -34,7 +34,7 @@ jobs:
- name: Cleanup PR deployment - name: Cleanup PR deployment
id: cleanup id: cleanup
run: | run: |
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH' CLEANUP_STATUS=$(ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH'
if [ -d "/stirling/PR-${{ github.event.pull_request.number }}" ]; then if [ -d "/stirling/PR-${{ github.event.pull_request.number }}" ]; then
echo "Found PR directory, proceeding with cleanup..." echo "Found PR directory, proceeding with cleanup..."
@@ -57,3 +57,29 @@ jobs:
echo "NO_CLEANUP_NEEDED" echo "NO_CLEANUP_NEEDED"
fi fi
ENDSSH ENDSSH
)
if [[ $CLEANUP_STATUS == *"PERFORMED_CLEANUP"* ]]; then
echo "cleanup_performed=true" >> $GITHUB_OUTPUT
else
echo "cleanup_performed=false" >> $GITHUB_OUTPUT
fi
- name: Post cleanup notice to PR
if: steps.cleanup.outputs.cleanup_performed == 'true'
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { GITHUB_REPOSITORY } = process.env;
const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/');
const prNumber = context.issue.number;
const commentBody = `## 🧹 Deployment Cleanup\n\n` +
`The test deployment for this PR has been cleaned up.`;
await github.rest.issues.createComment({
owner: repoOwner,
repo: repoName,
issue_number: prNumber,
body: commentBody
});

View File

@@ -13,7 +13,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit

View File

@@ -24,7 +24,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -32,7 +32,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK ${{ matrix.jdk-version }} - name: Set up JDK ${{ matrix.jdk-version }}
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: ${{ matrix.jdk-version }} java-version: ${{ matrix.jdk-version }}
distribution: "temurin" distribution: "temurin"
@@ -58,35 +58,6 @@ jobs:
build/reports/problems/ build/reports/problems/
retention-days: 3 retention-days: 3
check-licence:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
with:
java-version: "17"
distribution: "adopt"
- name: check the licenses for compatibility
run: ./gradlew clean checkLicense
- name: FAILED - check the licenses for compatibility
if: failure()
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: dependencies-without-allowed-license.json
path: |
build/reports/dependency-license/dependencies-without-allowed-license.json
retention-days: 3
docker-compose-tests: docker-compose-tests:
# if: github.event_name == 'push' && github.ref == 'refs/heads/main' || # if: github.event_name == 'push' && github.ref == 'refs/heads/main' ||
# (github.event_name == 'pull_request' && # (github.event_name == 'pull_request' &&
@@ -106,7 +77,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -114,7 +85,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Java 17 - name: Set up Java 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "17" java-version: "17"
distribution: "adopt" distribution: "adopt"
@@ -124,21 +95,20 @@ jobs:
- name: Install Docker Compose - name: Install Docker Compose
run: | run: |
sudo curl -SL "https://github.com/docker/compose/releases/download/v2.32.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo curl -SL "https://github.com/docker/compose/releases/download/v2.32.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
- name: Set up Python - name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with: with:
python-version: "3.12" python-version: "3.12"
cache: 'pip' # caching pip dependencies
- name: Pip requirements - name: Pip requirements
run: | run: |
pip install --require-hashes -r ./testing/cucumber/requirements.txt pip install --require-hashes -r ./cucumber/requirements.txt
- name: Run Docker Compose Tests - name: Run Docker Compose Tests
run: | run: |
chmod +x ./testing/test_webpages.sh chmod +x ./cucumber/test_webpages.sh
chmod +x ./testing/test.sh chmod +x ./test.sh
./testing/test.sh "${{ github.event.pull_request.user.login == 'dependabot[bot]' }}" ./test.sh

View File

@@ -18,7 +18,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python - name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with: with:
python-version: "3.12" python-version: "3.12"
@@ -58,7 +58,7 @@ jobs:
run: | run: |
echo "Fetching PR changed files..." echo "Fetching PR changed files..."
echo "Getting list of changed files from PR..." echo "Getting list of changed files from PR..."
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt # Filter only matching property files gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]+\.properties$' > changed_files.txt # Filter only matching property files
- name: Determine reference file test - name: Determine reference file test
id: determine-file id: determine-file
@@ -99,7 +99,7 @@ jobs:
// Filter for relevant files based on the PR changes // Filter for relevant files based on the PR changes
const changedFiles = files const changedFiles = files
.map(file => file.filename) .map(file => file.filename)
.filter(file => /^src\/main\/resources\/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$/.test(file)); .filter(file => /^src\/main\/resources\/messages_[a-zA-Z_]+\.properties$/.test(file));
console.log("Changed files:", changedFiles); console.log("Changed files:", changedFiles);

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit

View File

@@ -18,39 +18,30 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- name: Generate GitHub App Token - name: Generate GitHub App Token
id: generate-token id: generate-token
uses: actions/create-github-app-token@136412a57a7081aa63c935a2cc2918f76c34f514 # v1.11.2 uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
with: with:
app-id: ${{ secrets.GH_APP_ID }} app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Check out code - name: Check out code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "17" java-version: "17"
distribution: "adopt" distribution: "adopt"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2 - uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- name: check the licenses for compatibility - name: Run Gradle Command
run: ./gradlew clean checkLicense run: ./gradlew clean generateLicenseReport
- name: FAILED - check the licenses for compatibility
if: failure()
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: dependencies-without-allowed-license.json
path: |
build/reports/dependency-license/dependencies-without-allowed-license.json
retention-days: 3
- name: Move and Rename License File - name: Move and Rename License File
run: | run: |

View File

@@ -15,7 +15,7 @@ jobs:
issues: write issues: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run Labeler - name: Run Labeler
uses: crazy-max/ghaction-github-labeler@31674a3852a9074f2086abcf1c53839d466a47e7 # v5.2.0 uses: crazy-max/ghaction-github-labeler@b54af0c25861143e7c8813d7cbbf46d2c341680c # v5.1.0
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
yaml-file: .github/labels.yml yaml-file: .github/labels.yml

View File

@@ -16,7 +16,7 @@ jobs:
versionMac: ${{ steps.versionNumberMac.outputs.versionNumberMac }} versionMac: ${{ steps.versionNumberMac.outputs.versionNumberMac }}
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -51,14 +51,14 @@ jobs:
file_suffix: "" file_suffix: ""
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 21 - name: Set up JDK 21
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "21" java-version: "21"
distribution: "temurin" distribution: "temurin"
@@ -101,7 +101,7 @@ jobs:
file_suffix: "" file_suffix: ""
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -130,8 +130,8 @@ jobs:
include: include:
- os: windows-latest - os: windows-latest
platform: win- platform: win-
- os: macos-latest # - os: macos-latest
platform: mac- # platform: mac-
# - os: ubuntu-latest # - os: ubuntu-latest
# platform: linux- # platform: linux-
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -139,14 +139,14 @@ jobs:
contents: write contents: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 21 - name: Set up JDK 21
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "21" java-version: "21"
distribution: "temurin" distribution: "temurin"
@@ -168,7 +168,6 @@ jobs:
env: env:
DOCKER_ENABLE_SECURITY: false DOCKER_ENABLE_SECURITY: false
STIRLING_PDF_DESKTOP_UI: true STIRLING_PDF_DESKTOP_UI: true
BROWSER_OPEN: true
# Rename and collect artifacts based on OS # Rename and collect artifacts based on OS
- name: Prepare artifacts - name: Prepare artifacts
@@ -203,14 +202,14 @@ jobs:
include: include:
- os: windows-latest - os: windows-latest
platform: win- platform: win-
- os: macos-latest # - os: macos-latest
platform: mac- # platform: mac-
# - os: ubuntu-latest # - os: ubuntu-latest
# platform: linux- # platform: linux-
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -271,7 +270,7 @@ jobs:
contents: write contents: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit

View File

@@ -2,50 +2,31 @@ name: Pre-commit
on: on:
workflow_dispatch: workflow_dispatch:
schedule:
- cron: "0 0 * * 1"
permissions: permissions:
contents: read contents: read
jobs: jobs:
pre-commit: pre-commit:
if: ${{ github.event.pull_request.user.login != 'dependabot[bot]' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: write contents: write
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- name: Generate GitHub App Token
id: generate-token
uses: actions/create-github-app-token@136412a57a7081aa63c935a2cc2918f76c34f514 # v1.11.2
with:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Get GitHub App User ID
id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.generate-token.outputs.app-slug }}[bot]" --jq .id)" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
- id: committer
run: |
echo "string=${{ steps.generate-token.outputs.app-slug }}[bot] <${{ steps.get-user-id.outputs.user-id }}+${{ steps.generate-token.outputs.app-slug }}[bot]@users.noreply.github.com>" >> "$GITHUB_OUTPUT"
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Python - name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with: with:
python-version: 3.12 python-version: 3.12
cache: 'pip' # caching pip dependencies
- name: Run Pre-Commit Hooks - name: Run Pre-Commit Hooks
run: | run: |
pip install --require-hashes -r ./.github/scripts/requirements_pre_commit.txt pip install --require-hashes -r ./.github/scripts/requirements_pre_commit.txt
@@ -53,25 +34,25 @@ jobs:
continue-on-error: true continue-on-error: true
- name: Set up git config - name: Set up git config
run: | run: |
git config --global user.name ${{ steps.generate-token.outputs.app-slug }}[bot] git config --global user.name "github-actions[bot]"
git config --global user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.generate-token.outputs.app-slug }}[bot]@users.noreply.github.com" git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: git add - name: git add
run: | run: |
git add . git add .
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV git diff --staged --quiet || git commit -m ":file_folder: pre-commit
> Made via .github/workflows/pre_commit.yml" || echo "pre-commit: no changes"
- name: Create Pull Request - name: Create Pull Request
if: env.CHANGES_DETECTED == 'true'
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with: with:
token: ${{ steps.generate-token.outputs.token }} token: ${{ secrets.GITHUB_TOKEN }}
commit-message: ":file_folder: pre-commit" commit-message: "ci: 🤖 format everything with pre-commit"
committer: ${{ steps.committer.outputs.string }} committer: GitHub Action <action@github.com>
author: ${{ steps.committer.outputs.string }} author: GitHub Action <action@github.com>
signoff: true signoff: true
branch: pre-commit branch: pre-commit
title: "🤖 format everything with pre-commit by <${{ steps.generate-token.outputs.app-slug }}>" title: "🤖 format everything with pre-commit by <github-actions[bot]>"
body: | body: |
Auto-generated by [create-pull-request][1] with **${{ steps.generate-token.outputs.app-slug }}** Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request [1]: https://github.com/peter-evans/create-pull-request
draft: false draft: false

View File

@@ -18,14 +18,14 @@ jobs:
id-token: write id-token: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "17" java-version: "17"
distribution: "temurin" distribution: "temurin"
@@ -89,7 +89,7 @@ jobs:
- name: Build and push main Dockerfile - name: Build and push main Dockerfile
id: build-push-regular id: build-push-regular
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0
with: with:
builder: ${{ steps.buildx.outputs.name }} builder: ${{ steps.buildx.outputs.name }}
context: . context: .
@@ -134,7 +134,7 @@ jobs:
- name: Build and push Dockerfile-ultra-lite - name: Build and push Dockerfile-ultra-lite
id: build-push-lite id: build-push-lite
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0
if: github.ref != 'refs/heads/main' if: github.ref != 'refs/heads/main'
with: with:
context: . context: .
@@ -165,7 +165,7 @@ jobs:
- name: Build and push main Dockerfile fat - name: Build and push main Dockerfile fat
id: build-push-fat id: build-push-fat
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0
if: github.ref != 'refs/heads/main' if: github.ref != 'refs/heads/main'
with: with:
builder: ${{ steps.buildx.outputs.name }} builder: ${{ steps.buildx.outputs.name }}

View File

@@ -23,14 +23,14 @@ jobs:
version: ${{ steps.versionNumber.outputs.versionNumber }} version: ${{ steps.versionNumber.outputs.versionNumber }}
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "17" java-version: "17"
distribution: "temurin" distribution: "temurin"
@@ -83,7 +83,7 @@ jobs:
file_suffix: "" file_suffix: ""
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -161,7 +161,7 @@ jobs:
file_suffix: "" file_suffix: ""
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit

View File

@@ -34,7 +34,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -74,6 +74,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@@ -1,78 +0,0 @@
on:
push:
branches:
- master
pull_request:
branches: [ "main" ]
workflow_dispatch:
permissions:
pull-requests: read
actions: read
name: Run Sonarqube
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
with:
java-version: '17'
distribution: 'temurin'
- name: Cache SonarCloud packages
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Gradle packages
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Build and analyze with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
DOCKER_ENABLE_SECURITY: true
STIRLING_PDF_DESKTOP_UI: true
run: |
./gradlew clean build sonar \
-Dsonar.projectKey=Stirling-Tools_Stirling-PDF \
-Dsonar.organization=stirling-tools \
-Dsonar.host.url=https://sonarcloud.io \
-Dsonar.log.level=DEBUG \
--info
- name: Upload Problems Report on Failure
if: failure()
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: gradle-problems-report
path: build/reports/problems/problems-report.html
retention-days: 7
- name: Upload Sonar Logs on Failure
if: failure()
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: sonar-logs
path: |
.scannerwork/report-task.txt
build/sonar/
retention-days: 7

View File

@@ -16,12 +16,12 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- name: 30 days stale issues - name: 30 days stale issues
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30 days-before-stale: 30

View File

@@ -14,14 +14,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: "17" java-version: "17"
distribution: "temurin" distribution: "temurin"

View File

@@ -1,145 +1,62 @@
name: Sync Files name: Sync Files
on: on:
workflow_dispatch:
push: push:
branches: branches:
- main - main
paths: paths:
- "build.gradle" - "build.gradle"
- "README.md"
- "src/main/resources/messages_*.properties" - "src/main/resources/messages_*.properties"
- "src/main/resources/static/3rdPartyLicenses.json"
- "scripts/ignore_translation.toml" - "scripts/ignore_translation.toml"
permissions: permissions:
contents: read contents: read
jobs: jobs:
read_bot_entries: sync-readme:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: permissions:
userName: ${{ steps.get-user-id.outputs.user_name }} contents: write
userEmail: ${{ steps.get-user-id.outputs.user_email }} pull-requests: write
committer: ${{ steps.committer.outputs.committer }}
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- name: Generate GitHub App Token
id: generate-token
uses: actions/create-github-app-token@136412a57a7081aa63c935a2cc2918f76c34f514 # v1.11.2
with:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Get GitHub App User ID
id: get-user-id
run: |
USER_NAME="${{ steps.generate-token.outputs.app-slug }}[bot]"
USER_ID=$(gh api "/users/$USER_NAME" --jq .id)
USER_EMAIL="$USER_ID+$USER_NAME@users.noreply.github.com"
echo "user_name=$USER_NAME" >> "$GITHUB_OUTPUT"
echo "user_email=$USER_EMAIL" >> "$GITHUB_OUTPUT"
echo "user-id=$USER_ID" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
- id: committer
run: |
COMMITTER="${{ steps.get-user-id.outputs.user_name }} <${{ steps.get-user-id.outputs.user_email }}>"
echo "committer=$COMMITTER" >> "$GITHUB_OUTPUT"
sync-files:
needs: ["read_bot_entries"]
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
with:
egress-policy: audit
- name: Generate GitHub App Token
id: generate-token
uses: actions/create-github-app-token@136412a57a7081aa63c935a2cc2918f76c34f514 # v1.11.2
with:
app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python - name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with: with:
python-version: "3.12" python-version: "3.12"
cache: 'pip' # caching pip dependencies
- name: Sync translation property files
run: |
python .github/scripts/check_language_properties.py --reference-file "src/main/resources/messages_en_GB.properties" --branch main
- name: Set up git config
run: |
git config --global user.name ${{ needs.read_bot_entries.outputs.userName }}
git config --global user.email ${{ needs.read_bot_entries.outputs.userEmail }}
- name: Run git add
run: |
git add src/main/resources/messages_*.properties
git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "no changes"
- name: Install dependencies - name: Install dependencies
run: pip install --require-hashes -r ./.github/scripts/requirements_sync_readme.txt run: pip install --require-hashes -r ./.github/scripts/requirements_sync_readme.txt
- name: Sync README
- name: Sync README.md run: python scripts/counter_translation.py
- name: Set up git config
run: | run: |
python scripts/counter_translation.py git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Run git add - name: Run git add
run: | run: |
git add README.md git add .
git diff --staged --quiet || git commit -m ":memo: Sync README.md" || echo "no changes" git diff --staged --quiet || git commit -m ":memo: Sync README
> Made via sync_files.yml" || echo "no changes"
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with: with:
token: ${{ steps.generate-token.outputs.token }} token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update files commit-message: Update files
committer: ${{ needs.read_bot_entries.outputs.committer }} committer: GitHub Action <action@github.com>
author: ${{ needs.read_bot_entries.outputs.committer }} author: GitHub Action <action@github.com>
signoff: true signoff: true
branch: sync_readme branch: sync_readme
title: ":globe_with_meridians: Sync Translations + Update README Progress Table + Update Verification Metadata" title: ":memo: Update README: Translation Progress Table"
body: | body: |
### Description of Changes Auto-generated by [create-pull-request][1]
This Pull Request was automatically generated to synchronize updates to translation files, verification metadata, and documentation. Below are the details of the changes made:
#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language files.
- Highlighted any missing or incomplete translations.
#### **2. Update README.md**
- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported languages.
- Included up-to-date statistics on translation coverage.
#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.
---
Auto-generated by [create-pull-request][1].
[1]: https://github.com/peter-evans/create-pull-request [1]: https://github.com/peter-evans/create-pull-request
draft: false draft: false
delete-branch: true delete-branch: true
labels: github-actions labels: Documentation,Translation,github-actions
sign-commits: true sign-commits: true
add-paths: |
README.md
src/main/resources/messages_*.properties

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
@@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with: with:
java-version: '17' java-version: '17'
distribution: 'temurin' distribution: 'temurin'
@@ -46,7 +46,7 @@ jobs:
password: ${{ secrets.DOCKER_HUB_API }} password: ${{ secrets.DOCKER_HUB_API }}
- name: Build and push test image - name: Build and push test image
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
@@ -105,14 +105,14 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run TestDriver.ai - name: Run TestDriver.ai
uses: testdriverai/action@f0d0f45fdd684db628baa843fe9313f3ca3a8aa8 #1.1.3 uses: testdriverai/action@47e87c5d50beeeb3da624b2d9b5c1391269d6d22 #1.0.0
with: with:
key: ${{secrets.TESTDRIVER_API_KEY}} key: ${{secrets.TESTDRIVER_API_KEY}}
prerun: | prerun: |
@@ -122,7 +122,7 @@ jobs:
Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--load-extension=$(pwd)/node_modules/dashcam-chrome/build", "http://${{ secrets.VPS_HOST }}:1337" Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--load-extension=$(pwd)/node_modules/dashcam-chrome/build", "http://${{ secrets.VPS_HOST }}:1337"
Start-Sleep -Seconds 20 Start-Sleep -Seconds 20
prompt: | prompt: |
1. /run testing/testdriver/test.yml 1. /run testdriver/test.yml
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FORCE_COLOR: "3" FORCE_COLOR: "3"
@@ -134,7 +134,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with: with:
egress-policy: audit egress-policy: audit

View File

@@ -0,0 +1,72 @@
name: Update Translations
on:
push:
branches: ["main"]
paths:
- "src/main/resources/messages_en_GB.properties"
permissions:
contents: read
jobs:
update-translations-main:
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: "3.12"
- name: Run Python script to check files
id: run-check
run: |
echo "Running Python script to check files..."
python .github/scripts/check_language_properties.py \
--reference-file src/main/resources/messages_en_GB.properties \
--branch main
- name: Set up git config
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Add translation keys
run: |
git add src/main/resources/messages_*.properties
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
- name: Create Pull Request
id: cpr
if: env.CHANGES_DETECTED == 'true'
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "Update translation files"
committer: GitHub Action <action@github.com>
author: GitHub Action <action@github.com>
signoff: true
branch: update_translation_files
title: "Update translation files"
add-paths: |
src/main/resources/messages_*.properties
body: |
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
draft: false
delete-branch: true
labels: Translation,github-actions
sign-commits: true

3
.gitignore vendored
View File

@@ -21,11 +21,9 @@ pipeline/finishedFolders/
customFiles/ customFiles/
configs/ configs/
watchedFolders/ watchedFolders/
clientWebUI/
!cucumber/ !cucumber/
!cucumber/exampleFiles/ !cucumber/exampleFiles/
!cucumber/exampleFiles/example_html.zip !cucumber/exampleFiles/example_html.zip
exampleYmlFiles/stirling/
# Gradle # Gradle
.gradle .gradle
@@ -140,7 +138,6 @@ venv.bak/
# VS Code # VS Code
/.vscode/**/* /.vscode/**/*
!/.vscode/settings.json !/.vscode/settings.json
!/.vscode/extensions.json
# IntelliJ IDEA # IntelliJ IDEA
.idea/ .idea/

View File

@@ -6,10 +6,10 @@ repos:
args: args:
- --fix - --fix
- --line-length=127 - --line-length=127
files: ^((\.github/scripts|scripts)/.+)?[^/]+\.py$ files: ^((.github/scripts|scripts)/.+)?[^/]+\.py$
exclude: (split_photos.py) exclude: (split_photos.py)
- id: ruff-format - id: ruff-format
files: ^((\.github/scripts|scripts)/.+)?[^/]+\.py$ files: ^((.github/scripts|scripts)/.+)?[^/]+\.py$
exclude: (split_photos.py) exclude: (split_photos.py)
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.3.0 rev: v2.3.0
@@ -19,18 +19,39 @@ repos:
- --ignore-words-list= - --ignore-words-list=
- --skip="./.*,*.csv,*.json,*.ambr" - --skip="./.*,*.csv,*.json,*.ambr"
- --quiet-level=2 - --quiet-level=2
files: \.(html|css|js|py|md)$ files: \.(properties|html|css|js|py|md)$
exclude: (.vscode|.devcontainer|src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js) exclude: (.vscode|.devcontainer|src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js)
- repo: https://github.com/gitleaks/gitleaks - repo: https://github.com/gitleaks/gitleaks
rev: v8.22.0 rev: v8.22.0
hooks: hooks:
- id: gitleaks - id: gitleaks
- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
- id: shellcheck
files: ^.*(\.bash|\.sh|\.ksh|\.zsh)$
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v5.0.0
hooks: hooks:
- id: end-of-file-fixer - id: end-of-file-fixer
files: ^.*(\.js|\.java|\.py|\.yml)$ files: ^.*(\.js|\.java|\.py|\.yml)$
exclude: ^(.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js|\.github/workflows/.*$) exclude: ^(.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js$)
- id: trailing-whitespace - id: trailing-whitespace
files: ^.*(\.js|\.java|\.py|\.yml)$ files: ^.*(\.js|\.java|\.py|\.yml)$
exclude: ^(.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js|\.github/workflows/.*$) exclude: ^(.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js$)
- repo: local
hooks:
- id: check-duplicate-properties-keys
name: Check Duplicate Properties Keys
entry: python .github/scripts/check_duplicates.py
language: python
files: ^(src)/.+\.properties$
- id: check-html-tabs
name: Check HTML for tabs
description: Ensures HTML/CSS/JS files do not contain tab characters
# args: ["--replace_with= "]
entry: python .github/scripts/check_tabulator.py
language: python
exclude: ^(.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js$)
files: ^.*(\.html|\.css|\.js)$

View File

@@ -1,24 +0,0 @@
{
"recommendations": [
"elagil.pre-commit-helper", // Support for pre-commit hooks to enforce code quality
"josevseb.google-java-format-for-vs-code", // Google Java code formatter to follow the Google Java Style Guide
"ms-python.black-formatter", // Python code formatter using Black
"ms-python.flake8", // Flake8 linter for Python to enforce code quality
"ms-python.python", // Official Microsoft Python extension with IntelliSense, debugging, and Jupyter support
// "ms-vscode-remote.remote-containers", // Support for remote development with containers (Docker, Dev Containers)
// "ms-vscode-remote.vscode-remote-extensionpack", // Remote Development Pack for SSH, WSL, and Containers
"Oracle.oracle-java", // Oracle Java extension with additional features for Java development
"redhat.java", // Java support by Red Hat with IntelliSense, debugging, and code navigation
"shengchen.vscode-checkstyle", // Checkstyle integration for Java code quality checks
"streetsidesoftware.code-spell-checker", // Spell checker for code to avoid typos
"vmware.vscode-boot-dev-pack", // Developer tools for Spring Boot by VMware
"vmware.vscode-spring-boot", // Spring Boot tools by VMware for enhanced Spring development
"vscjava.vscode-gradle", // Gradle extension for build and automation support
"vscjava.vscode-java-debug", // Debugging support for Java projects
"vscjava.vscode-java-dependency", // Java dependency management within VS Code
"vscjava.vscode-java-pack", // Java Extension Pack with essential Java tools for VS Code
"vscjava.vscode-java-test", // Java test framework for running and debugging tests in VS Code
"vscjava.vscode-spring-boot-dashboard", // Spring Boot dashboard for managing and visualizing Spring Boot applications
"vscjava.vscode-spring-initializr" // Support for Spring Initializr to create new Spring projects
]
}

View File

@@ -39,16 +39,6 @@ Stirling-PDF is built using:
2. Install Docker and JDK17 if not already installed. 2. Install Docker and JDK17 if not already installed.
3. Install a recommended Java IDE such as Eclipse, IntelliJ, or VSCode 3. Install a recommended Java IDE such as Eclipse, IntelliJ, or VSCode
1. Only VSCode
1. Open VS Code.
2. When prompted, install the recommended extensions.
3. Alternatively, open the command palette (`Ctrl + Shift + P` or `Cmd + Shift + P` on macOS) and run:
```sh
Extensions: Show Recommended Extensions
```
4. Install the required extensions from the list.
4. Lombok Setup 4. Lombok Setup
Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, don't support Lombok out of the box. To set up Lombok in your development environment: Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, don't support Lombok out of the box. To set up Lombok in your development environment:

View File

@@ -25,13 +25,7 @@ LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, conver
# Set Environment Variables # Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \ ENV DOCKER_ENABLE_SECURITY=false \
VERSION_TAG=$VERSION_TAG \ VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions \ JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \
-XX:MaxRAMPercentage=75 \
-XX:InitiatingHeapOccupancyPercent=20 \
-XX:+G1PeriodicGCInvokesConcurrent \
-XX:G1PeriodicGCInterval=10000 \
-XX:+UseStringDeduplication \
-XX:G1PeriodicGCSystemLoadThreshold=70" \
HOME=/home/stirlingpdfuser \ HOME=/home/stirlingpdfuser \
PUID=1000 \ PUID=1000 \
PGID=1000 \ PGID=1000 \

View File

@@ -25,13 +25,7 @@ ARG VERSION_TAG
# Set Environment Variables # Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \ ENV DOCKER_ENABLE_SECURITY=false \
VERSION_TAG=$VERSION_TAG \ VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions \ JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \
-XX:MaxRAMPercentage=75 \
-XX:InitiatingHeapOccupancyPercent=20 \
-XX:+G1PeriodicGCInvokesConcurrent \
-XX:G1PeriodicGCInterval=10000 \
-XX:+UseStringDeduplication \
-XX:G1PeriodicGCSystemLoadThreshold=70" \
HOME=/home/stirlingpdfuser \ HOME=/home/stirlingpdfuser \
PUID=1000 \ PUID=1000 \
PGID=1000 \ PGID=1000 \

View File

@@ -7,13 +7,7 @@ ARG VERSION_TAG
ENV DOCKER_ENABLE_SECURITY=false \ ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \ HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \ VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions \ JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \
-XX:MaxRAMPercentage=75 \
-XX:InitiatingHeapOccupancyPercent=20 \
-XX:+G1PeriodicGCInvokesConcurrent \
-XX:G1PeriodicGCInterval=10000 \
-XX:+UseStringDeduplication \
-XX:G1PeriodicGCSystemLoadThreshold=70" \
PUID=1000 \ PUID=1000 \
PGID=1000 \ PGID=1000 \
UMASK=022 UMASK=022

View File

@@ -18,7 +18,9 @@ Any SVG flags are fine; most of the current ones were sourced from [here](https:
For example, to add Polish, you would add: For example, to add Polish, you would add:
```html ```html
<a th:if="${#lists.isEmpty(@languages) or #lists.contains(@languages, 'pl_PL')}" class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="pl_PL"> <img th:src="@{'/images/flags/pl.svg'}" alt="icon" width="20" height="15"> Polski</a> <a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="pl_PL">
<img src="images/flags/pl.svg" alt="icon" width="20" height="15"> Polski
</a>
``` ```
The `data-bs-language-code` is the code used to reference the file in the next step. The `data-bs-language-code` is the code used to reference the file in the next step.
@@ -58,13 +60,3 @@ ignore = [
- After adding the new tags to `messages_en_GB.properties`, add and translate them in the respective language file (e.g., `messages_pl_PL.properties`). - After adding the new tags to `messages_en_GB.properties`, add and translate them in the respective language file (e.g., `messages_pl_PL.properties`).
Make sure to place the entry under the correct language section. This helps maintain the accuracy of translation progress statistics and ensures that the translation tool or scripts do not misinterpret the completion rate. Make sure to place the entry under the correct language section. This helps maintain the accuracy of translation progress statistics and ensures that the translation tool or scripts do not misinterpret the completion rate.
### Use this code to perform a local check
#### Windows command
```ps
python .github/scripts/check_language_properties.py --reference-file src\main\resources\messages_en_GB.properties --branch "" --files src\main\resources\messages_pl_PL.properties
python .github/scripts/check_language_properties.py --reference-file src\main\resources\messages_en_GB.properties --branch "" --check-file src\main\resources\messages_pl_PL.properties
```

View File

@@ -113,50 +113,49 @@ Visit our comprehensive documentation at [docs.stirlingpdf.com](https://docs.sti
## Supported Languages ## Supported Languages
Stirling-PDF currently supports 39 languages! Stirling-PDF currently supports 38 languages!
| Language | Progress | | Language | Progress |
| -------------------------------------------- | -------------------------------------- | | -------------------------------------------- | -------------------------------------- |
| Arabic (العربية) (ar_AR) | ![89%](https://geps.dev/progress/89) | | Arabic (العربية) (ar_AR) | ![91%](https://geps.dev/progress/91) |
| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![88%](https://geps.dev/progress/88) | | Azerbaijani (Azərbaycan Dili) (az_AZ) | ![89%](https://geps.dev/progress/89) |
| Basque (Euskara) (eu_ES) | ![51%](https://geps.dev/progress/51) | | Basque (Euskara) (eu_ES) | ![51%](https://geps.dev/progress/51) |
| Bulgarian (Български) (bg_BG) | ![85%](https://geps.dev/progress/85) | | Bulgarian (Български) (bg_BG) | ![86%](https://geps.dev/progress/86) |
| Catalan (Català) (ca_CA) | ![80%](https://geps.dev/progress/80) | | Catalan (Català) (ca_CA) | ![81%](https://geps.dev/progress/81) |
| Croatian (Hrvatski) (hr_HR) | ![87%](https://geps.dev/progress/87) | | Croatian (Hrvatski) (hr_HR) | ![88%](https://geps.dev/progress/88) |
| Czech (Česky) (cs_CZ) | ![98%](https://geps.dev/progress/98) | | Czech (Česky) (cs_CZ) | ![87%](https://geps.dev/progress/87) |
| Danish (Dansk) (da_DK) | ![85%](https://geps.dev/progress/85) | | Danish (Dansk) (da_DK) | ![87%](https://geps.dev/progress/87) |
| Dutch (Nederlands) (nl_NL) | ![85%](https://geps.dev/progress/85) | | Dutch (Nederlands) (nl_NL) | ![86%](https://geps.dev/progress/86) |
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| French (Français) (fr_FR) | ![96%](https://geps.dev/progress/96) | | French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) |
| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) | | German (Deutsch) (de_DE) | ![96%](https://geps.dev/progress/96) |
| Greek (Ελληνικά) (el_GR) | ![98%](https://geps.dev/progress/98) | | Greek (Ελληνικά) (el_GR) | ![87%](https://geps.dev/progress/87) |
| Hindi (हिंदी) (hi_IN) | ![98%](https://geps.dev/progress/98) | | Hindi (हिंदी) (hi_IN) | ![85%](https://geps.dev/progress/85) |
| Hungarian (Magyar) (hu_HU) | ![95%](https://geps.dev/progress/95) | | Hungarian (Magyar) (hu_HU) | ![97%](https://geps.dev/progress/97) |
| Indonesian (Bahasa Indonesia) (id_ID) | ![86%](https://geps.dev/progress/86) | | Indonesian (Bahasa Indonesia) (id_ID) | ![87%](https://geps.dev/progress/87) |
| Irish (Gaeilge) (ga_IE) | ![98%](https://geps.dev/progress/98) | | Irish (Gaeilge) (ga_IE) | ![80%](https://geps.dev/progress/80) |
| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | | Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
| Japanese (日本語) (ja_JP) | ![93%](https://geps.dev/progress/93) | | Japanese (日本語) (ja_JP) | ![90%](https://geps.dev/progress/90) |
| Korean (한국어) (ko_KR) | ![99%](https://geps.dev/progress/99) | | Korean (한국어) (ko_KR) | ![86%](https://geps.dev/progress/86) |
| Norwegian (Norsk) (no_NB) | ![79%](https://geps.dev/progress/79) | | Norwegian (Norsk) (no_NB) | ![80%](https://geps.dev/progress/80) |
| Persian (فارسی) (fa_IR) | ![94%](https://geps.dev/progress/94) | | Persian (فارسی) (fa_IR) | ![95%](https://geps.dev/progress/95) |
| Polish (Polski) (pl_PL) | ![86%](https://geps.dev/progress/86) | | Polish (Polski) (pl_PL) | ![87%](https://geps.dev/progress/87) |
| Portuguese (Português) (pt_PT) | ![97%](https://geps.dev/progress/97) | | Portuguese (Português) (pt_PT) | ![98%](https://geps.dev/progress/98) |
| Portuguese Brazilian (Português) (pt_BR) | ![97%](https://geps.dev/progress/97) | | Portuguese Brazilian (Português) (pt_BR) | ![98%](https://geps.dev/progress/98) |
| Romanian (Română) (ro_RO) | ![81%](https://geps.dev/progress/81) | | Romanian (Română) (ro_RO) | ![82%](https://geps.dev/progress/82) |
| Russian (Русский) (ru_RU) | ![98%](https://geps.dev/progress/98) | | Russian (Русский) (ru_RU) | ![87%](https://geps.dev/progress/87) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![64%](https://geps.dev/progress/64) | | Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![64%](https://geps.dev/progress/64) |
| Simplified Chinese (简体中文) (zh_CN) | ![89%](https://geps.dev/progress/89) | | Simplified Chinese (简体中文) (zh_CN) | ![90%](https://geps.dev/progress/90) |
| Slovakian (Slovensky) (sk_SK) | ![74%](https://geps.dev/progress/74) | | Slovakian (Slovensky) (sk_SK) | ![75%](https://geps.dev/progress/75) |
| Slovenian (Slovenščina) (sl_SI) | ![97%](https://geps.dev/progress/97) | | Spanish (Español) (es_ES) | ![88%](https://geps.dev/progress/88) |
| Spanish (Español) (es_ES) | ![87%](https://geps.dev/progress/87) | | Swedish (Svenska) (sv_SE) | ![88%](https://geps.dev/progress/88) |
| Swedish (Svenska) (sv_SE) | ![87%](https://geps.dev/progress/87) | | Thai (ไทย) (th_TH) | ![87%](https://geps.dev/progress/87) |
| Thai (ไทย) (th_TH) | ![86%](https://geps.dev/progress/86) | | Tibetan (བོད་ཡིག་) (zh_BO) | ![96%](https://geps.dev/progress/96) |
| Tibetan (བོད་ཡིག་) (zh_BO) | ![95%](https://geps.dev/progress/95) | | Traditional Chinese (繁體中文) (zh_TW) | ![99%](https://geps.dev/progress/99) |
| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) | | Turkish (Türkçe) (tr_TR) | ![83%](https://geps.dev/progress/83) |
| Turkish (Türkçe) (tr_TR) | ![82%](https://geps.dev/progress/82) | | Ukrainian (Українська) (uk_UA) | ![73%](https://geps.dev/progress/73) |
| Ukrainian (Українська) (uk_UA) | ![72%](https://geps.dev/progress/72) | | Vietnamese (Tiếng Việt) (vi_VN) | ![80%](https://geps.dev/progress/80) |
| Vietnamese (Tiếng Việt) (vi_VN) | ![79%](https://geps.dev/progress/79) |
## Stirling PDF Enterprise ## Stirling PDF Enterprise

View File

@@ -1,164 +0,0 @@
{
"allowedLicenses": [
{
"moduleName": ".*",
"moduleLicense": "BSD License"
},
{
"moduleName": ".*",
"moduleLicense": "The BSD License"
},
{
"moduleName": ".*",
"moduleLicense": "BSD-2-Clause"
},
{
"moduleName": ".*",
"moduleLicense": "BSD 2-Clause License"
},
{
"moduleName": ".*",
"moduleLicense": "The 2-Clause BSD License"
},
{
"moduleName": ".*",
"moduleLicense": "BSD-3-Clause"
},
{
"moduleName": ".*",
"moduleLicense": "The BSD 3-Clause License (BSD3)"
},
{
"moduleName": ".*",
"moduleLicense": "BSD-4 License"
},
{
"moduleName": ".*",
"moduleLicense": "MIT"
},
{
"moduleName": ".*",
"moduleLicense": "MIT License"
},
{
"moduleName": ".*",
"moduleLicense": "The MIT License"
},
{
"moduleName": "com.github.jai-imageio:jai-imageio-core",
"moduleLicense": "LICENSE.txt"
},
{
"moduleName": "com.github.jai-imageio:jai-imageio-jpeg2000",
"moduleLicense": "LICENSE-JJ2000.txt, LICENSE-Sun.txt"
},
{
"moduleName": ".*",
"moduleLicense": "Apache 2"
},
{
"moduleName": ".*",
"moduleLicense": "Apache 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Apache-2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Apache-2.0 License"
},
{
"moduleName": ".*",
"moduleLicense": "Apache License 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Apache License Version 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Apache License, Version 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "The Apache License, Version 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "The Apache Software License, Version 2.0"
},
{
"moduleName": "com.nimbusds:oauth2-oidc-sdk",
"moduleLicense": "\"Apache License, version 2.0\";link=\"https://www.apache.org/licenses/LICENSE-2.0.html\""
},
{
"moduleName": ".*",
"moduleLicense": "MPL 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "UnboundID SCIM2 SDK Free Use License"
},
{
"moduleName": ".*",
"moduleLicense": "GPL2 w/ CPE"
},
{
"moduleName": ".*",
"moduleLicense": "GPLv2+CE"
},
{
"moduleName": ".*",
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
},
{
"moduleName": "com.martiansoftware:jsap",
"moduleLicense": "LGPL"
},
{
"moduleName": "org.hibernate.orm:hibernate-core",
"moduleLicense": "GNU Library General Public License v2.1 or later"
},
{
"moduleName": ".*",
"moduleLicense": "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0"
},
{
"moduleName": ".*",
"moduleLicense": "Eclipse Public License - v 1.0"
},
{
"moduleName": ".*",
"moduleLicense": "Eclipse Public License v. 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Eclipse Public License - v 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Eclipse Public License - Version 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Eclipse Public License, Version 2.0"
},
{
"moduleName": ".*",
"moduleLicense": "Ubuntu Font Licence 1.0"
},
{
"moduleName": ".*",
"moduleLicense": "Bouncy Castle Licence"
},
{
"moduleName": ".*",
"moduleLicense": "Public Domain, per Creative Commons CC0"
},
{
"moduleName": ".*",
"moduleLicense": "The W3C License"
}
]
}

View File

@@ -5,28 +5,30 @@ plugins {
id "org.springdoc.openapi-gradle-plugin" version "1.8.0" id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
id "io.swagger.swaggerhub" version "1.3.2" id "io.swagger.swaggerhub" version "1.3.2"
id "edu.sc.seis.launch4j" version "3.0.6" id "edu.sc.seis.launch4j" version "3.0.6"
id "com.diffplug.spotless" version "7.0.2" id "com.diffplug.spotless" version "7.0.1"
id "com.github.jk1.dependency-license-report" version "2.9" id "com.github.jk1.dependency-license-report" version "2.9"
//id "nebula.lint" version "19.0.3" //id "nebula.lint" version "19.0.3"
id("org.panteleyev.jpackageplugin") version "1.6.0" id("org.panteleyev.jpackageplugin") version "1.6.0"
id "org.sonarqube" version "6.0.1.5171"
} }
import com.github.jk1.license.render.* import com.github.jk1.license.render.*
ext { ext {
springBootVersion = "3.4.1" springBootVersion = "3.4.1"
pdfboxVersion = "3.0.4" pdfboxVersion = "3.0.3"
logbackVersion = "1.5.7" logbackVersion = "1.5.7"
imageioVersion = "3.12.0" imageioVersion = "3.12.0"
lombokVersion = "1.18.36" lombokVersion = "1.18.36"
bouncycastleVersion = "1.80" bouncycastleVersion = "1.79"
springSecuritySamlVersion = "6.4.2" springSecuritySamlVersion = "6.4.2"
openSamlVersion = "4.3.2" openSamlVersion = "4.3.2"
} }
group = "stirling.software" group = "stirling.software"
version = "0.40.1" version = "0.37.0"
java { java {
// 17 is lowest but we support and recommend 21 // 17 is lowest but we support and recommend 21
@@ -35,13 +37,14 @@ java {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url = "https://build.shibboleth.net/maven/releases" } maven { url "https://jitpack.io" }
maven { url = "https://maven.pkg.github.com/jcefmaven/jcefmaven" } maven { url "https://build.shibboleth.net/maven/releases" }
maven { url "https://maven.pkg.github.com/jcefmaven/jcefmaven" }
} }
licenseReport { licenseReport {
renderers = [new JsonReportRenderer()] renderers = [new JsonReportRenderer()]
allowedLicensesFile = new File("$projectDir/allowed-licenses.json")
} }
sourceSets { sourceSets {
@@ -65,7 +68,7 @@ sourceSets {
} }
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
exclude "stirling/software/SPDF/UI/impl/**" exclude "stirling/software/SPDF/UI/impl/**"
} }
} }
@@ -110,15 +113,18 @@ def getMacVersion(String version) {
jpackage { jpackage {
input = "build/libs" input = "build/libs"
destination = "${projectDir}/build/jpackage"
mainJar = "Stirling-PDF-${project.version}.jar"
appName = "Stirling-PDF" appName = "Stirling-PDF"
appVersion = project.version appVersion = project.version
vendor = "Stirling-Software" vendor = "Stirling-Software"
appDescription = "Stirling PDF - Your Local PDF Editor" appDescription = "Stirling PDF - Your Local PDF Editor"
mainJar = "Stirling-PDF-${project.version}.jar"
mainClass = "org.springframework.boot.loader.launch.JarLauncher"
icon = "src/main/resources/static/favicon.ico" icon = "src/main/resources/static/favicon.ico"
verbose = true
// mainClass = "org.springframework.boot.loader.launch.JarLauncher"
// JVM Options // JVM Options
javaOptions = [ javaOptions = [
@@ -126,21 +132,23 @@ jpackage {
"-DSTIRLING_PDF_DESKTOP_UI=true", "-DSTIRLING_PDF_DESKTOP_UI=true",
"-Djava.awt.headless=false", "-Djava.awt.headless=false",
"-Dapple.awt.UIElement=true", "-Dapple.awt.UIElement=true",
"--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.desktop/java.awt.event=ALL-UNNAMED", "--add-opens", "java.desktop/java.awt.event=ALL-UNNAMED",
"--add-opens=java.desktop/sun.awt=ALL-UNNAMED", "--add-opens", "java.desktop/sun.awt=ALL-UNNAMED"
"--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED",
"--add-opens=java.desktop/sun.awt.windows=ALL-UNNAMED",
"--add-opens=java.desktop/sun.lwawt=ALL-UNNAMED",
"--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED",
] ]
verbose = true
destination = "${projectDir}/build/jpackage"
// Windows-specific configuration // Windows-specific configuration
windows { windows {
launcherAsService = false launcherAsService = false
appVersion = project.version appVersion = project.version
winConsole = false winConsole = false
winMenu = true // Creates start menu entry winMenu = true // Creates start menu entry
winShortcut = true // Creates desktop shortcut winShortcut = true // Creates desktop shortcut
winShortcutPrompt = true // Lets user choose whether to create shortcuts winShortcutPrompt = true // Lets user choose whether to create shortcuts
@@ -156,7 +164,7 @@ jpackage {
// macOS-specific configuration // macOS-specific configuration
mac { mac {
appVersion = getMacVersion(project.version.toString()) appVersion = getMacVersion(project.version.toString())
icon = "src/main/resources/static/favicon.icns" icon = "src/main/resources/static/favicon.icns"
type = "dmg" type = "dmg"
macPackageIdentifier = "com.stirling.software.pdf" macPackageIdentifier = "com.stirling.software.pdf"
@@ -180,7 +188,7 @@ jpackage {
// Linux-specific configuration // Linux-specific configuration
linux { linux {
appVersion = project.version appVersion = project.version
icon = "src/main/resources/static/favicon.png" icon = "src/main/resources/static/favicon.png"
type = "deb" // Can also use "rpm" for Red Hat-based systems type = "deb" // Can also use "rpm" for Red Hat-based systems
@@ -228,9 +236,9 @@ launch4j {
outfile="Stirling-PDF.exe" outfile="Stirling-PDF.exe"
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') { if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
headerType = "gui" headerType = "gui"
} else { } else {
headerType = "console" headerType = "console"
} }
jarTask = tasks.bootJar jarTask = tasks.bootJar
@@ -238,11 +246,13 @@ launch4j {
downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe" downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') { if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
variables=["BROWSER_OPEN=true", "STIRLING_PDF_DESKTOP_UI=true"] variables=["BROWSER_OPEN=true", "STIRLING_PDF_DESKTOP_UI=true"]
} else { } else {
variables=["BROWSER_OPEN=true"] variables=["BROWSER_OPEN=true"]
} }
jreMinVersion="17" jreMinVersion="17"
mutexName="Stirling-PDF" mutexName="Stirling-PDF"
@@ -264,22 +274,11 @@ spotless {
importOrder("java", "javax", "org", "com", "net", "io") importOrder("java", "javax", "org", "com", "net", "io")
toggleOffOn() toggleOffOn()
trimTrailingWhitespace() trimTrailingWhitespace()
leadingTabsToSpaces() indentWithSpaces()
endWithNewline() endWithNewline()
} }
} }
sonar {
properties {
property "sonar.projectKey", "Stirling-Tools_Stirling-PDF"
property "sonar.organization", "stirling-tools"
property "sonar.exclusions", "**/build-wrapper-dump.json, src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.coverage.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.cpd.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
}
}
//gradleLint { //gradleLint {
// rules=['unused-dependency'] // rules=['unused-dependency']
// } // }
@@ -294,23 +293,26 @@ configurations.all {
} }
dependencies { dependencies {
if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") { if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") {
implementation "me.friwi:jcefmaven:127.3.1" implementation "me.friwi:jcefmaven:127.3.1"
implementation "org.openjfx:javafx-controls:21" implementation "org.openjfx:javafx-controls:21"
implementation "org.openjfx:javafx-swing:21" implementation "org.openjfx:javafx-swing:21"
} }
//security updates //security updates
implementation "org.springframework:spring-webmvc:6.2.2" implementation "org.springframework:spring-webmvc:6.2.1"
implementation("io.github.pixee:java-security-toolkit:1.2.1") implementation("io.github.pixee:java-security-toolkit:1.2.1")
// implementation "org.yaml:snakeyaml:2.2"
implementation 'com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4'
// Exclude Tomcat and include Jetty // Exclude Tomcat and include Jetty
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion" implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion" implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
implementation 'com.posthog.java:posthog:1.2.0' implementation 'com.posthog.java:posthog:1.1.1'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
@@ -320,20 +322,20 @@ dependencies {
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion" implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion" implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
implementation "org.springframework.session:spring-session-core:$springBootVersion" implementation "org.springframework.session:spring-session-core:$springBootVersion"
implementation "org.springframework:spring-jdbc:6.2.2" implementation "org.springframework:spring-jdbc:6.2.1"
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5' implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
// Don't upgrade h2database // Don't upgrade h2database
runtimeOnly "com.h2database:h2:2.3.232" runtimeOnly "com.h2database:h2:2.3.232"
runtimeOnly "org.postgresql:postgresql:42.7.5" runtimeOnly "org.postgresql:postgresql:42.7.4"
constraints { constraints {
implementation "org.opensaml:opensaml-core:$openSamlVersion" implementation "org.opensaml:opensaml-core:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion" implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion" implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
} }
implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion" implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
// implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion' // implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion'
implementation 'com.coveo:saml-client:5.0.0' implementation 'com.coveo:saml-client:5.0.0'
@@ -377,8 +379,6 @@ dependencies {
implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") { implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") {
exclude group: "commons-logging", module: "commons-logging" exclude group: "commons-logging", module: "commons-logging"
} }
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") { implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") {
exclude group: "commons-logging", module: "commons-logging" exclude group: "commons-logging", module: "commons-logging"
@@ -405,8 +405,8 @@ dependencies {
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0" implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
implementation "com.fathzer:javaluator:3.0.5" implementation "com.fathzer:javaluator:3.0.5"
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' implementation 'org.jsoup:jsoup:1.18.3'
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion") developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
compileOnly "org.projectlombok:lombok:$lombokVersion" compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion"
@@ -430,13 +430,13 @@ task writeVersion {
} }
swaggerhubUpload { swaggerhubUpload {
// dependsOn = generateOpenApiDocs // Depends on your task generating Swagger docs //dependsOn generateOpenApiDocs // Depends on your task generating Swagger docs
api = "Stirling-PDF" // The name of your API on SwaggerHub api "Stirling-PDF" // The name of your API on SwaggerHub
owner = "Frooodle" // Your SwaggerHub username (or organization name) owner "Frooodle" // Your SwaggerHub username (or organization name)
version = project.version // The version of your API version project.version // The version of your API
inputFile = "./SwaggerDoc.json" // The path to your Swagger docs inputFile "./SwaggerDoc.json" // The path to your Swagger docs
token = "${System.getenv("SWAGGERHUB_API_KEY")}" // Your SwaggerHub API key, passed as an environment variable token "${System.getenv("SWAGGERHUB_API_KEY")}" // Your SwaggerHub API key, passed as an environment variable
oas = "3.0.0" // The version of the OpenAPI Specification you"re using oas "3.0.0" // The version of the OpenAPI Specification you"re using
} }
jar { jar {

View File

@@ -204,12 +204,4 @@ Feature: API Validation
Then the response status code should be 200 Then the response status code should be 200
And the response file should have size greater than 100 And the response file should have size greater than 100
And the response file should have extension ".pdf" And the response file should have extension ".pdf"
Scenario: Convert PDF to Markdown format
Given I generate a PDF file as "fileInput"
And the pdf contains 3 pages with random text
When I send the API request to the endpoint "/api/v1/convert/pdf/markdown"
Then the response status code should be 200
And the response file should have size greater than 100
And the response file should have extension ".md"

View File

@@ -2,16 +2,17 @@
# Function to check a single webpage # Function to check a single webpage
check_webpage() { check_webpage() {
local url=$(echo "$1" | tr -d '\r') # Remove carriage returns local url=$1
local base_url=$(echo "$2" | tr -d '\r') local base_url=${2:-"http://localhost:8080"}
local full_url="${base_url}${url}" local full_url="${base_url}${url}"
local timeout=10 local timeout=10
echo -n "Testing $full_url ... " echo -n "Testing $full_url ... "
# Use curl to fetch the page with timeout # Use curl to fetch the page with timeout
response=$(curl -s -w "\n%{http_code}" --max-time $timeout "$full_url") response=$(curl -s -w "\n%{http_code}" --max-time $timeout "$full_url")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "FAILED - Connection error or timeout $full_url " echo "FAILED - Connection error or timeout"
return 1 return 1
fi fi
@@ -26,7 +27,7 @@ check_webpage() {
fi fi
# Check if response contains HTML # Check if response contains HTML
if ! printf '%s' "$BODY" | grep -q "<!DOCTYPE html>\|<html"; then if ! echo "$BODY" | grep -q "<!DOCTYPE html>\|<html"; then
echo "FAILED - Response is not HTML" echo "FAILED - Response is not HTML"
return 1 return 1
fi fi
@@ -45,12 +46,11 @@ test_all_urls() {
echo "Starting webpage tests..." echo "Starting webpage tests..."
echo "Base URL: $base_url" echo "Base URL: $base_url"
echo "Number of lines: $(wc -l < "$url_file")"
echo "----------------------------------------" echo "----------------------------------------"
while IFS= read -r url || [ -n "$url" ]; do while IFS= read -r url || [ -n "$url" ]; do
# Skip empty lines and comments # Skip empty lines
[[ -z "$url" || "$url" =~ ^#.*$ ]] && continue [ -z "$url" ] && continue
((total_count++)) ((total_count++))
if ! check_webpage "$url" "$base_url"; then if ! check_webpage "$url" "$base_url"; then
@@ -60,7 +60,7 @@ test_all_urls() {
local end_time=$(date +%s) local end_time=$(date +%s)
local duration=$((end_time - start_time)) local duration=$((end_time - start_time))
echo "----------------------------------------" echo "----------------------------------------"
echo "Test Summary:" echo "Test Summary:"
echo "Total tests: $total_count" echo "Total tests: $total_count"
@@ -71,44 +71,18 @@ test_all_urls() {
return $failed_count return $failed_count
} }
# Print usage information
usage() {
echo "Usage: $0 [-f url_file] [-b base_url]"
echo "Options:"
echo " -f url_file Path to file containing URLs to test (required)"
echo " -b base_url Base URL to prepend to test URLs (default: http://localhost:8080)"
exit 1
}
# Main execution # Main execution
main() { main() {
local url_file="" local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local base_url="http://localhost:8080" local url_file="${script_dir}/webpage_urls.txt"
# Parse command line options
while getopts ":f:b:h" opt; do
case $opt in
f) url_file="$OPTARG" ;;
b) base_url="$OPTARG" ;;
h) usage ;;
\?) echo "Invalid option -$OPTARG" >&2; usage ;;
esac
done
# Check if URL file is provided
if [ -z "$url_file" ]; then
echo "Error: URL file is required"
usage
fi
# Check if URL file exists
if [ ! -f "$url_file" ]; then if [ ! -f "$url_file" ]; then
echo "Error: URL list file not found: $url_file" echo "Error: URL list file not found: $url_file"
exit 1 exit 1
fi fi
# Run tests using the URL list # Run tests using the URL list
if test_all_urls "$url_file" "$base_url"; then if test_all_urls "$url_file"; then
echo "All webpage tests passed!" echo "All webpage tests passed!"
exit 0 exit 0
else else

View File

@@ -12,6 +12,7 @@
/extract-page /extract-page
/pdf-to-single-page /pdf-to-single-page
/img-to-pdf /img-to-pdf
/markdown-to-pdf
/pdf-to-img /pdf-to-img
/pdf-to-text /pdf-to-text
/pdf-to-csv /pdf-to-csv

View File

@@ -1,6 +1,6 @@
services: services:
stirling-pdf: stirling-pdf:
container_name: Stirling-PDF-Security-Fat-with-login container_name: Stirling-PDF-Security-Fat
image: stirlingtools/stirling-pdf:latest-fat image: stirlingtools/stirling-pdf:latest-fat
deploy: deploy:
resources: resources:

View File

@@ -75,7 +75,7 @@ def write_readme(progress_list: list[tuple[str, int]]) -> None:
f"![{value}%](https://geps.dev/progress/{value})", f"![{value}%](https://geps.dev/progress/{value})",
) )
with open("README.md", "w", encoding="utf-8", newline="\n") as file: with open("README.md", "w", encoding="utf-8") as file:
file.writelines(content) file.writelines(content)
@@ -196,7 +196,7 @@ def compare_files(
) )
) )
ignore_translation = convert_to_multiline(sort_ignore_translation) ignore_translation = convert_to_multiline(sort_ignore_translation)
with open(ignore_translation_file, "w", encoding="utf-8", newline="\n") as file: with open(ignore_translation_file, "w", encoding="utf-8") as file:
file.write(tomlkit.dumps(ignore_translation)) file.write(tomlkit.dumps(ignore_translation))
unique_data = list(set(result_list)) unique_data = list(set(result_list))

View File

@@ -24,6 +24,7 @@ ignore = [
[cs_CZ] [cs_CZ]
ignore = [ ignore = [
'language.direction', 'language.direction',
'pipeline.header',
'text', 'text',
] ]
@@ -49,7 +50,6 @@ ignore = [
'pipeline.title', 'pipeline.title',
'pipelineOptions.pipelineHeader', 'pipelineOptions.pipelineHeader',
'pro', 'pro',
'redact.zoom',
'sponsor', 'sponsor',
'text', 'text',
'validateSignature.cert.bits', 'validateSignature.cert.bits',
@@ -210,11 +210,6 @@ ignore = [
'watermark.type.1', 'watermark.type.1',
] ]
[sl_SI]
ignore = [
'language.direction',
]
[sr_LATN_RS] [sr_LATN_RS]
ignore = [ ignore = [
'language.direction', 'language.direction',

View File

@@ -25,7 +25,7 @@ public class EEAppConfig {
@Bean(name = "runningEE") @Bean(name = "runningEE")
public boolean runningEnterpriseEdition() { public boolean runningEnterpriseEdition() {
return licenseKeyChecker.getEnterpriseEnabledResult(); return licenseKeyChecker.getEnterpriseEnabledResult();
} }
@Bean(name = "SSOAutoLogin") @Bean(name = "SSOAutoLogin")

View File

@@ -4,7 +4,6 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -75,11 +74,6 @@ public class AppConfig {
: "null"; : "null";
} }
@Bean(name = "languages")
public List<String> languages() {
return applicationProperties.getUi().getLanguages();
}
@Bean(name = "navBarText") @Bean(name = "navBarText")
public String navBarText() { public String navBarText() {
String defaultNavBar = String defaultNavBar =

View File

@@ -9,200 +9,135 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.*; import java.util.Arrays;
import java.util.List;
import org.simpleyaml.configuration.comments.CommentType;
import org.simpleyaml.configuration.file.YamlFile;
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/**
* A naive, line-based approach to merging "settings.yml" with "settings.yml.template" while
* preserving exact whitespace, blank lines, and inline comments -- but we only rewrite the file if
* the merged content actually differs.
*/
@Slf4j @Slf4j
public class ConfigInitializer { public class ConfigInitializer {
public void ensureConfigExists() throws IOException, URISyntaxException { public void ensureConfigExists() throws IOException, URISyntaxException {
// 1) If settings file doesn't exist, create from template // Define the path to the external config directory
Path destPath = Paths.get(InstallationPathConfig.getSettingsPath()); Path destPath = Paths.get(InstallationPathConfig.getSettingsPath());
// Check if the file already exists
if (Files.notExists(destPath)) { if (Files.notExists(destPath)) {
// Ensure the destination directory exists
Files.createDirectories(destPath.getParent()); Files.createDirectories(destPath.getParent());
// Copy the resource from classpath to the external directory
try (InputStream in = try (InputStream in =
getClass().getClassLoader().getResourceAsStream("settings.yml.template")) { getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
if (in == null) { if (in != null) {
Files.copy(in, destPath);
} else {
throw new FileNotFoundException( throw new FileNotFoundException(
"Resource file not found: settings.yml.template"); "Resource file not found: settings.yml.template");
} }
Files.copy(in, destPath);
} }
log.info("Created settings file from template"); log.info("Created settings file from template");
} else { } else {
// 2) Merge existing file with the template
// Define the path to the config settings file
Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath()); Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath());
URL templateResource = getClass().getClassLoader().getResource("settings.yml.template"); // Load the template resource
if (templateResource == null) { URL settingsTemplateResource =
getClass().getClassLoader().getResource("settings.yml.template");
if (settingsTemplateResource == null) {
throw new IOException("Resource not found: settings.yml.template"); throw new IOException("Resource not found: settings.yml.template");
} }
// Copy template to a temp location so we can read lines // Create a temporary file to copy the resource content
Path tempTemplatePath = Files.createTempFile("settings.yml", ".template"); Path tempTemplatePath = Files.createTempFile("settings.yml", ".template");
try (InputStream in = templateResource.openStream()) {
try (InputStream in = settingsTemplateResource.openStream()) {
Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING); Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING);
} }
// 2a) Read lines from both files final YamlFile settingsTemplateFile = new YamlFile(tempTemplatePath.toFile());
List<String> templateLines = Files.readAllLines(tempTemplatePath); DumperOptions yamlOptionsSettingsTemplateFile =
List<String> mainLines = Files.readAllLines(settingsPath); ((SimpleYamlImplementation) settingsTemplateFile.getImplementation())
.getDumperOptions();
yamlOptionsSettingsTemplateFile.setSplitLines(false);
settingsTemplateFile.loadWithComments();
// 2b) Merge lines final YamlFile settingsFile = new YamlFile(settingsPath.toFile());
List<String> mergedLines = mergeYamlLinesWithTemplate(templateLines, mainLines); DumperOptions yamlOptionsSettingsFile =
((SimpleYamlImplementation) settingsFile.getImplementation())
.getDumperOptions();
yamlOptionsSettingsFile.setSplitLines(false);
settingsFile.loadWithComments();
// 2c) Only write if there's an actual difference // Load headers and comments
if (!mergedLines.equals(mainLines)) { String header = settingsTemplateFile.getHeader();
Files.write(settingsPath, mergedLines);
log.info("Settings file updated based on template changes."); // Create a new file for temporary settings
} else { final YamlFile tempSettingFile = new YamlFile(settingsPath.toFile());
log.info("No changes detected; settings file left as-is."); DumperOptions yamlOptionsTempSettingFile =
((SimpleYamlImplementation) tempSettingFile.getImplementation())
.getDumperOptions();
yamlOptionsTempSettingFile.setSplitLines(false);
tempSettingFile.createNewFile(true);
tempSettingFile.setHeader(header);
// Get all keys from the template
List<String> keys =
Arrays.asList(settingsTemplateFile.getKeys(true).toArray(new String[0]));
for (String key : keys) {
if (!key.contains(".")) {
// Add blank lines and comments to specific sections
tempSettingFile
.path(key)
.comment(settingsTemplateFile.getComment(key))
.blankLine();
continue;
}
// Copy settings from the template to the settings.yml file
changeConfigItemFromCommentToKeyValue(
settingsTemplateFile, settingsFile, tempSettingFile, key);
} }
Files.deleteIfExists(tempTemplatePath); // Save the settings.yml file
tempSettingFile.save();
} }
// 3) Ensure custom settings file exists // Create custom settings file if it doesn't exist
Path customSettingsPath = Paths.get(InstallationPathConfig.getCustomSettingsPath()); Path customSettingsPath = Paths.get(InstallationPathConfig.getCustomSettingsPath());
if (!Files.exists(customSettingsPath)) { if (!Files.exists(customSettingsPath)) {
Files.createFile(customSettingsPath); Files.createFile(customSettingsPath);
} }
} }
/** private void changeConfigItemFromCommentToKeyValue(
* Merge logic that: - Reads the template lines block-by-block (where a "block" = a key and all final YamlFile settingsTemplateFile,
* the lines that belong to it), - If the main file has that key, we keep the main file's block final YamlFile settingsFile,
* (preserving whitespace + inline comments). - Otherwise, we insert the template's block. - We final YamlFile tempSettingFile,
* also remove keys from main that no longer exist in the template. String path) {
* if (settingsFile.get(path) == null && settingsTemplateFile.get(path) != null) {
* @param templateLines lines from settings.yml.template // If the key is only in the template, add it to the temporary settings with comments
* @param mainLines lines from the existing settings.yml tempSettingFile
* @return merged lines .path(path)
*/ .set(settingsTemplateFile.get(path))
private List<String> mergeYamlLinesWithTemplate( .comment(settingsTemplateFile.getComment(path, CommentType.BLOCK))
List<String> templateLines, List<String> mainLines) { .commentSide(settingsTemplateFile.getComment(path, CommentType.SIDE));
} else if (settingsFile.get(path) != null && settingsTemplateFile.get(path) != null) {
// 1) Parse template lines into an ordered map: path -> Block // If the key is in both, update the temporary settings with the main settings' value
LinkedHashMap<String, Block> templateBlocks = parseYamlBlocks(templateLines); // and comments
tempSettingFile
// 2) Parse main lines into a map: path -> Block .path(path)
LinkedHashMap<String, Block> mainBlocks = parseYamlBlocks(mainLines); .set(settingsFile.get(path))
.comment(settingsTemplateFile.getComment(path, CommentType.BLOCK))
// 3) Build the final list by iterating template blocks in order .commentSide(settingsTemplateFile.getComment(path, CommentType.SIDE));
List<String> merged = new ArrayList<>(); } else {
for (Map.Entry<String, Block> entry : templateBlocks.entrySet()) { // Log if the key is not found in both YAML files
String path = entry.getKey(); log.info("Key not found in both YAML files: " + path);
Block templateBlock = entry.getValue();
if (mainBlocks.containsKey(path)) {
// If main has the same block, prefer main's lines
merged.addAll(mainBlocks.get(path).lines);
} else {
// Otherwise, add the template block
merged.addAll(templateBlock.lines);
}
} }
return merged;
}
/**
* Parse a list of lines into a map of "path -> Block" where "Block" is all lines that belong to
* that key (including subsequent indented lines). Very naive approach that may not work with
* advanced YAML.
*/
private LinkedHashMap<String, Block> parseYamlBlocks(List<String> lines) {
LinkedHashMap<String, Block> blocks = new LinkedHashMap<>();
Block currentBlock = null;
String currentPath = null;
for (String line : lines) {
if (isLikelyKeyLine(line)) {
// Found a new "key: ..." line
if (currentBlock != null && currentPath != null) {
blocks.put(currentPath, currentBlock);
}
currentBlock = new Block();
currentBlock.lines.add(line);
currentPath = computePathForLine(line);
} else {
// Continuation of current block (comments, blank lines, sub-lines)
if (currentBlock == null) {
// If file starts with comments/blank lines, treat as "header block" with path
// ""
currentBlock = new Block();
currentPath = "";
}
currentBlock.lines.add(line);
}
}
if (currentBlock != null && currentPath != null) {
blocks.put(currentPath, currentBlock);
}
return blocks;
}
/**
* Checks if the line is likely "key:" or "key: value", ignoring comments/blank. Skips lines
* starting with "-" or "#".
*/
private boolean isLikelyKeyLine(String line) {
String trimmed = line.trim();
if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith("-")) {
return false;
}
int colonIdx = trimmed.indexOf(':');
return (colonIdx > 0); // someKey:
}
// For a line like "security: ", returns "security" or "security.enableLogin"
// by looking at indentation. Very naive.
private static final Deque<String> pathStack = new ArrayDeque<>();
private static int currentIndentLevel = 0;
private String computePathForLine(String line) {
// count leading spaces
int leadingSpaces = 0;
for (char c : line.toCharArray()) {
if (c == ' ') leadingSpaces++;
else break;
}
// assume 2 spaces = 1 indent
int indentLevel = leadingSpaces / 2;
String trimmed = line.trim();
int colonIdx = trimmed.indexOf(':');
String keyName = trimmed.substring(0, colonIdx).trim();
// pop stack until we match the new indent level
while (currentIndentLevel >= indentLevel && !pathStack.isEmpty()) {
pathStack.pop();
currentIndentLevel--;
}
// push the new key
pathStack.push(keyName);
currentIndentLevel = indentLevel;
// build path by reversing the stack
String[] arr = pathStack.toArray(new String[0]);
List<String> reversed = Arrays.asList(arr);
Collections.reverse(reversed);
return String.join(".", reversed);
}
/**
* Simple holder for the lines that comprise a "block" (i.e. a key and its subsequent lines).
*/
private static class Block {
List<String> lines = new ArrayList<>();
} }
} }

View File

@@ -126,7 +126,6 @@ public class EndpointConfiguration {
addEndpointToGroup("Convert", "url-to-pdf"); addEndpointToGroup("Convert", "url-to-pdf");
addEndpointToGroup("Convert", "markdown-to-pdf"); addEndpointToGroup("Convert", "markdown-to-pdf");
addEndpointToGroup("Convert", "pdf-to-csv"); addEndpointToGroup("Convert", "pdf-to-csv");
addEndpointToGroup("Convert", "pdf-to-markdown");
// Adding endpoints to "Security" group // Adding endpoints to "Security" group
addEndpointToGroup("Security", "add-password"); addEndpointToGroup("Security", "add-password");
@@ -244,7 +243,6 @@ public class EndpointConfiguration {
addEndpointToGroup("Java", REMOVE_BLANKS); addEndpointToGroup("Java", REMOVE_BLANKS);
addEndpointToGroup("Java", "pdf-to-text"); addEndpointToGroup("Java", "pdf-to-text");
addEndpointToGroup("Java", "remove-image-pdf"); addEndpointToGroup("Java", "remove-image-pdf");
addEndpointToGroup("Java", "pdf-to-markdown");
// Javascript // Javascript
addEndpointToGroup("Javascript", "pdf-organizer"); addEndpointToGroup("Javascript", "pdf-organizer");
@@ -260,11 +258,9 @@ public class EndpointConfiguration {
// Weasyprint dependent endpoints // Weasyprint dependent endpoints
addEndpointToGroup("Weasyprint", "html-to-pdf"); addEndpointToGroup("Weasyprint", "html-to-pdf");
addEndpointToGroup("Weasyprint", "url-to-pdf"); addEndpointToGroup("Weasyprint", "url-to-pdf");
addEndpointToGroup("Weasyprint", "markdown-to-pdf");
// Pdftohtml dependent endpoints // Pdftohtml dependent endpoints
addEndpointToGroup("Pdftohtml", "pdf-to-html"); addEndpointToGroup("Pdftohtml", "pdf-to-html");
addEndpointToGroup("Pdftohtml", "pdf-to-markdown");
// disabled for now while we resolve issues // disabled for now while we resolve issues
disableEndpoint("pdf-to-pdfa"); disableEndpoint("pdf-to-pdfa");

View File

@@ -7,10 +7,8 @@ import org.springframework.context.annotation.Configuration;
import com.posthog.java.PostHog; import com.posthog.java.PostHog;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
@Configuration @Configuration
@Slf4j
public class PostHogConfig { public class PostHogConfig {
@Value("${posthog.api.key}") @Value("${posthog.api.key}")
@@ -23,11 +21,7 @@ public class PostHogConfig {
@Bean @Bean
public PostHog postHogClient() { public PostHog postHogClient() {
postHogClient = postHogClient = new PostHog.Builder(posthogApiKey).host(posthogHost).build();
new PostHog.Builder(posthogApiKey)
.host(posthogHost)
.logger(new PostHogLoggerImpl())
.build();
return postHogClient; return postHogClient;
} }

View File

@@ -1,42 +0,0 @@
package stirling.software.SPDF.config;
import org.springframework.stereotype.Component;
import com.posthog.java.PostHogLogger;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class PostHogLoggerImpl implements PostHogLogger {
@Override
public void debug(String message) {
log.debug(message);
}
@Override
public void info(String message) {
log.info(message);
}
@Override
public void warn(String message) {
log.warn(message);
}
@Override
public void error(String message) {
log.error(message);
}
@Override
public void error(String message, Throwable throwable) {
if (message.contains("Error sending events to PostHog")) {
log.warn(
"Error sending metrics, Likely caused by no internet connection. Non Blocking");
} else {
log.error(message, throwable);
}
}
}

View File

@@ -33,11 +33,7 @@ public class DatabaseConfig {
public DatabaseConfig( public DatabaseConfig(
ApplicationProperties applicationProperties, ApplicationProperties applicationProperties,
@Qualifier("runningEE") boolean runningEE) { @Qualifier("runningEE") boolean runningEE) {
DATASOURCE_DEFAULT_URL = DATASOURCE_DEFAULT_URL = "jdbc:h2:file:" + InstallationPathConfig.getConfigPath() + File.separator + "stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE";
"jdbc:h2:file:"
+ InstallationPathConfig.getConfigPath()
+ File.separator
+ "stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE";
this.applicationProperties = applicationProperties; this.applicationProperties = applicationProperties;
this.runningEE = runningEE; this.runningEE = runningEE;
} }

View File

@@ -2,9 +2,7 @@ package stirling.software.SPDF.controller.api;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@@ -28,14 +26,11 @@ public class AdditionalLanguageJsController {
@Hidden @Hidden
@GetMapping(value = "/additionalLanguageCode.js", produces = "application/javascript") @GetMapping(value = "/additionalLanguageCode.js", produces = "application/javascript")
public void generateAdditionalLanguageJs(HttpServletResponse response) throws IOException { public void generateAdditionalLanguageJs(HttpServletResponse response) throws IOException {
Set<String> supportedLanguages = languageService.getSupportedLanguages(); List<String> supportedLanguages = languageService.getSupportedLanguages();
response.setContentType("application/javascript"); response.setContentType("application/javascript");
PrintWriter writer = response.getWriter(); PrintWriter writer = response.getWriter();
// Erstelle das JavaScript dynamisch // Erstelle das JavaScript dynamisch
writer.println( writer.println("const supportedLanguages = " + toJsonArray(supportedLanguages) + ";");
"const supportedLanguages = "
+ toJsonArray(new ArrayList<>(supportedLanguages))
+ ";");
// Generiere die `getDetailedLanguageCode`-Funktion // Generiere die `getDetailedLanguageCode`-Funktion
writer.println( writer.println(
""" """

View File

@@ -1,194 +0,0 @@
package stirling.software.SPDF.controller.api;
import java.io.IOException;
import java.util.*;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.encryption.PDEncryption;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
@RestController
@RequestMapping("/api/v1/analysis")
@Tag(name = "Analysis", description = "Analysis APIs")
public class AnalysisController {
@PostMapping(value = "/page-count", consumes = "multipart/form-data")
@Operation(
summary = "Get PDF page count",
description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO")
public Map<String, Integer> getPageCount(@ModelAttribute PDFFile file) throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
return Map.of("pageCount", document.getNumberOfPages());
}
}
@PostMapping(value = "/basic-info", consumes = "multipart/form-data")
@Operation(
summary = "Get basic PDF information",
description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO")
public Map<String, Object> getBasicInfo(@ModelAttribute PDFFile file) throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
Map<String, Object> info = new HashMap<>();
info.put("pageCount", document.getNumberOfPages());
info.put("pdfVersion", document.getVersion());
info.put("fileSize", file.getFileInput().getSize());
return info;
}
}
@PostMapping(value = "/document-properties", consumes = "multipart/form-data")
@Operation(
summary = "Get PDF document properties",
description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO")
public Map<String, String> getDocumentProperties(@ModelAttribute PDFFile file)
throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
PDDocumentInformation info = document.getDocumentInformation();
Map<String, String> properties = new HashMap<>();
properties.put("title", info.getTitle());
properties.put("author", info.getAuthor());
properties.put("subject", info.getSubject());
properties.put("keywords", info.getKeywords());
properties.put("creator", info.getCreator());
properties.put("producer", info.getProducer());
properties.put("creationDate", info.getCreationDate().toString());
properties.put("modificationDate", info.getModificationDate().toString());
return properties;
}
}
@PostMapping(value = "/page-dimensions", consumes = "multipart/form-data")
@Operation(
summary = "Get page dimensions for all pages",
description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO")
public List<Map<String, Float>> getPageDimensions(@ModelAttribute PDFFile file)
throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
List<Map<String, Float>> dimensions = new ArrayList<>();
PDPageTree pages = document.getPages();
for (PDPage page : pages) {
Map<String, Float> pageDim = new HashMap<>();
pageDim.put("width", page.getBBox().getWidth());
pageDim.put("height", page.getBBox().getHeight());
dimensions.add(pageDim);
}
return dimensions;
}
}
@PostMapping(value = "/form-fields", consumes = "multipart/form-data")
@Operation(
summary = "Get form field information",
description =
"Returns count and details of form fields. Input:PDF Output:JSON Type:SISO")
public Map<String, Object> getFormFields(@ModelAttribute PDFFile file) throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
Map<String, Object> formInfo = new HashMap<>();
PDAcroForm form = document.getDocumentCatalog().getAcroForm();
if (form != null) {
formInfo.put("fieldCount", form.getFields().size());
formInfo.put("hasXFA", form.hasXFA());
formInfo.put("isSignaturesExist", form.isSignaturesExist());
} else {
formInfo.put("fieldCount", 0);
formInfo.put("hasXFA", false);
formInfo.put("isSignaturesExist", false);
}
return formInfo;
}
}
@PostMapping(value = "/annotation-info", consumes = "multipart/form-data")
@Operation(
summary = "Get annotation information",
description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO")
public Map<String, Object> getAnnotationInfo(@ModelAttribute PDFFile file) throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
Map<String, Object> annotInfo = new HashMap<>();
int totalAnnotations = 0;
Map<String, Integer> annotationTypes = new HashMap<>();
for (PDPage page : document.getPages()) {
for (PDAnnotation annot : page.getAnnotations()) {
totalAnnotations++;
String subType = annot.getSubtype();
annotationTypes.merge(subType, 1, Integer::sum);
}
}
annotInfo.put("totalCount", totalAnnotations);
annotInfo.put("typeBreakdown", annotationTypes);
return annotInfo;
}
}
@PostMapping(value = "/font-info", consumes = "multipart/form-data")
@Operation(
summary = "Get font information",
description =
"Returns list of fonts used in the document. Input:PDF Output:JSON Type:SISO")
public Map<String, Object> getFontInfo(@ModelAttribute PDFFile file) throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
Map<String, Object> fontInfo = new HashMap<>();
Set<String> fontNames = new HashSet<>();
for (PDPage page : document.getPages()) {
for (COSName font : page.getResources().getFontNames()) {
fontNames.add(font.getName());
}
}
fontInfo.put("fontCount", fontNames.size());
fontInfo.put("fonts", fontNames);
return fontInfo;
}
}
@PostMapping(value = "/security-info", consumes = "multipart/form-data")
@Operation(
summary = "Get security information",
description =
"Returns encryption and permission details. Input:PDF Output:JSON Type:SISO")
public Map<String, Object> getSecurityInfo(@ModelAttribute PDFFile file) throws IOException {
try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) {
Map<String, Object> securityInfo = new HashMap<>();
PDEncryption encryption = document.getEncryption();
if (encryption != null) {
securityInfo.put("isEncrypted", true);
securityInfo.put("keyLength", encryption.getLength());
// Get permissions
Map<String, Boolean> permissions = new HashMap<>();
permissions.put("canPrint", document.getCurrentAccessPermission().canPrint());
permissions.put("canModify", document.getCurrentAccessPermission().canModify());
permissions.put(
"canExtractContent",
document.getCurrentAccessPermission().canExtractContent());
permissions.put(
"canModifyAnnotations",
document.getCurrentAccessPermission().canModifyAnnotations());
securityInfo.put("permissions", permissions);
} else {
securityInfo.put("isEncrypted", false);
}
return securityInfo;
}
}
}

View File

@@ -13,7 +13,6 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest; import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
import stirling.software.SPDF.service.CustomPDDocumentFactory; import stirling.software.SPDF.service.CustomPDDocumentFactory;
import stirling.software.SPDF.utils.FileToPdf; import stirling.software.SPDF.utils.FileToPdf;
@@ -28,16 +27,12 @@ public class ConvertHtmlToPDF {
private final CustomPDDocumentFactory pdfDocumentFactory; private final CustomPDDocumentFactory pdfDocumentFactory;
private final ApplicationProperties applicationProperties;
@Autowired @Autowired
public ConvertHtmlToPDF( public ConvertHtmlToPDF(
CustomPDDocumentFactory pdfDocumentFactory, CustomPDDocumentFactory pdfDocumentFactory,
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled, @Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
ApplicationProperties applicationProperties) {
this.pdfDocumentFactory = pdfDocumentFactory; this.pdfDocumentFactory = pdfDocumentFactory;
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled; this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
this.applicationProperties = applicationProperties;
} }
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf") @PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
@@ -59,17 +54,12 @@ public class ConvertHtmlToPDF {
|| (!originalFilename.endsWith(".html") && !originalFilename.endsWith(".zip"))) { || (!originalFilename.endsWith(".html") && !originalFilename.endsWith(".zip"))) {
throw new IllegalArgumentException("File must be either .html or .zip format."); throw new IllegalArgumentException("File must be either .html or .zip format.");
} }
boolean disableSanitize =
Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
byte[] pdfBytes = byte[] pdfBytes =
FileToPdf.convertHtmlToPdf( FileToPdf.convertHtmlToPdf(
request, request,
fileInput.getBytes(), fileInput.getBytes(),
originalFilename, originalFilename,
bookAndHtmlFormatsInstalled, bookAndHtmlFormatsInstalled);
disableSanitize);
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes); pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);

View File

@@ -23,7 +23,6 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.GeneralFile; import stirling.software.SPDF.model.api.GeneralFile;
import stirling.software.SPDF.service.CustomPDDocumentFactory; import stirling.software.SPDF.service.CustomPDDocumentFactory;
import stirling.software.SPDF.utils.FileToPdf; import stirling.software.SPDF.utils.FileToPdf;
@@ -38,16 +37,12 @@ public class ConvertMarkdownToPdf {
private final CustomPDDocumentFactory pdfDocumentFactory; private final CustomPDDocumentFactory pdfDocumentFactory;
private final ApplicationProperties applicationProperties;
@Autowired @Autowired
public ConvertMarkdownToPdf( public ConvertMarkdownToPdf(
CustomPDDocumentFactory pdfDocumentFactory, CustomPDDocumentFactory pdfDocumentFactory,
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled, @Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
ApplicationProperties applicationProperties) {
this.pdfDocumentFactory = pdfDocumentFactory; this.pdfDocumentFactory = pdfDocumentFactory;
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled; this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
this.applicationProperties = applicationProperties;
} }
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf") @PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
@@ -81,16 +76,12 @@ public class ConvertMarkdownToPdf {
String htmlContent = renderer.render(document); String htmlContent = renderer.render(document);
boolean disableSanitize =
Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
byte[] pdfBytes = byte[] pdfBytes =
FileToPdf.convertHtmlToPdf( FileToPdf.convertHtmlToPdf(
null, null,
htmlContent.getBytes(), htmlContent.getBytes(),
"converted.html", "converted.html",
bookAndHtmlFormatsInstalled, bookAndHtmlFormatsInstalled);
disableSanitize);
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes); pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
String outputFilename = String outputFilename =
originalFilename.replaceFirst("[.][^.]+$", "") originalFilename.replaceFirst("[.][^.]+$", "")

View File

@@ -44,13 +44,6 @@ public class ConverterWebController {
return "convert/markdown-to-pdf"; return "convert/markdown-to-pdf";
} }
@GetMapping("/pdf-to-markdown")
@Hidden
public String convertPdfToMarkdownForm(Model model) {
model.addAttribute("currentPage", "pdf-to-markdown");
return "convert/pdf-to-markdown";
}
@GetMapping("/url-to-pdf") @GetMapping("/url-to-pdf")
@Hidden @Hidden
public String convertURLToPdfForm(Model model) { public String convertURLToPdfForm(Model model) {

View File

@@ -36,9 +36,8 @@ public class DatabaseWebController {
} }
List<FileInfo> backupList = databaseService.getBackupList(); List<FileInfo> backupList = databaseService.getBackupList();
model.addAttribute("backupFiles", backupList); model.addAttribute("backupFiles", backupList);
String dbVersion = databaseService.getH2Version(); model.addAttribute("databaseVersion", databaseService.getH2Version());
model.addAttribute("databaseVersion", dbVersion); if ("Unknown".equalsIgnoreCase(databaseService.getH2Version())) {
if ("Unknown".equalsIgnoreCase(dbVersion)) {
model.addAttribute("infoMessage", "notSupported"); model.addAttribute("infoMessage", "notSupported");
} }
return "database"; return "database";

View File

@@ -55,10 +55,7 @@ public class GeneralWebController {
List<String> pipelineConfigs = new ArrayList<>(); List<String> pipelineConfigs = new ArrayList<>();
List<Map<String, String>> pipelineConfigsWithNames = new ArrayList<>(); List<Map<String, String>> pipelineConfigsWithNames = new ArrayList<>();
if (new File(InstallationPathConfig.getPipelineDefaultWebUIConfigsDir()).exists()) { if (new File(InstallationPathConfig.getPipelineDefaultWebUIConfigsDir()).exists()) {
try (Stream<Path> paths = try (Stream<Path> paths = Files.walk(Paths.get(InstallationPathConfig.getPipelineDefaultWebUIConfigsDir()))) {
Files.walk(
Paths.get(
InstallationPathConfig.getPipelineDefaultWebUIConfigsDir()))) {
List<Path> jsonFiles = List<Path> jsonFiles =
paths.filter(Files::isRegularFile) paths.filter(Files::isRegularFile)
.filter(p -> p.toString().endsWith(".json")) .filter(p -> p.toString().endsWith(".json"))

View File

@@ -74,12 +74,6 @@ public class HomeWebController {
return "redirect:/"; return "redirect:/";
} }
@GetMapping("/home-legacy")
public String homeLegacy(Model model) {
model.addAttribute("currentPage", "home-legacy");
return "home-legacy";
}
@GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE) @GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody @ResponseBody
@Hidden @Hidden

View File

@@ -265,8 +265,7 @@ public class ApplicationProperties {
return getKeycloak(); return getKeycloak();
default: default:
throw new UnsupportedProviderException( throw new UnsupportedProviderException(
"Logout from the provider is not supported? Report it at" "Logout from the provider is not supported? Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
+ " https://github.com/Stirling-Tools/Stirling-PDF/issues");
} }
} }
} }
@@ -284,7 +283,6 @@ public class ApplicationProperties {
private Boolean enableAlphaFunctionality; private Boolean enableAlphaFunctionality;
private String enableAnalytics; private String enableAnalytics;
private Datasource datasource; private Datasource datasource;
private Boolean disableSanitize;
} }
@Data @Data
@@ -314,10 +312,10 @@ public class ApplicationProperties {
@Override @Override
public String toString() { public String toString() {
return """ return """
Driver { Driver {
driverName='%s' driverName='%s'
} }
""" """
.formatted(driverName); .formatted(driverName);
} }
} }
@@ -327,7 +325,6 @@ public class ApplicationProperties {
private String appName; private String appName;
private String homeDescription; private String homeDescription;
private String appNameNavbar; private String appNameNavbar;
private List<String> languages;
public String getAppName() { public String getAppName() {
return appName != null && appName.trim().length() > 0 ? appName : null; return appName != null && appName.trim().length() > 0 ? appName : null;

View File

@@ -1,32 +0,0 @@
package stirling.software.SPDF.model.api.converters;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
import stirling.software.SPDF.utils.PDFToFile;
@RestController
@Tag(name = "Convert", description = "Convert APIs")
@RequestMapping("/api/v1/convert")
public class ConvertPDFToMarkdown {
@PostMapping(consumes = "multipart/form-data", value = "/pdf/markdown")
@Operation(
summary = "Convert PDF to Markdown",
description =
"This endpoint converts a PDF file to Markdown format. Input:PDF Output:Markdown Type:SISO")
public ResponseEntity<byte[]> processPdfToMarkdown(@ModelAttribute PDFFile request)
throws Exception {
MultipartFile inputFile = request.getFileInput();
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToMarkdown(inputFile);
}
}

View File

@@ -26,7 +26,7 @@ public class OptimizePdfRequest extends PDFFile {
@Schema( @Schema(
description = description =
"Whether to normalize the PDF content for better compatibility. Default is false.", "Whether to normalize the PDF content for better compatibility. Default is true.",
defaultValue = "false") defaultValue = "true")
private Boolean normalize = false; private Boolean normalize = true;
} }

View File

@@ -1,56 +1,41 @@
package stirling.software.SPDF.service; package stirling.software.SPDF.service;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.ArrayList;
import java.util.HashSet; import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
@Service @Service
@Slf4j
public class LanguageService { public class LanguageService {
private final ApplicationProperties applicationProperties;
private final PathMatchingResourcePatternResolver resourcePatternResolver = private final PathMatchingResourcePatternResolver resourcePatternResolver =
new PathMatchingResourcePatternResolver(); new PathMatchingResourcePatternResolver();
public LanguageService(ApplicationProperties applicationProperties) { public List<String> getSupportedLanguages() {
this.applicationProperties = applicationProperties; List<String> supportedLanguages = new ArrayList<>();
}
public Set<String> getSupportedLanguages() {
try { try {
Resource[] resources = Resource[] resources =
resourcePatternResolver.getResources("classpath*:messages_*.properties"); resourcePatternResolver.getResources("classpath*:messages_*.properties");
for (Resource resource : resources) {
return Arrays.stream(resources) if (resource.exists() && resource.isReadable()) {
.map(Resource::getFilename) String filename = resource.getFilename();
.filter( if (filename != null
filename -> && filename.startsWith("messages_")
filename != null && filename.endsWith(".properties")) {
&& filename.startsWith("messages_") String languageCode =
&& filename.endsWith(".properties")) filename.replace("messages_", "").replace(".properties", "");
.map(filename -> filename.replace("messages_", "").replace(".properties", "")) supportedLanguages.add(languageCode);
.filter( }
languageCode -> { }
Set<String> allowedLanguages = }
new HashSet<>(applicationProperties.getUi().getLanguages());
return allowedLanguages.isEmpty()
|| allowedLanguages.contains(languageCode)
|| "en_GB".equals(languageCode);
})
.collect(Collectors.toSet());
} catch (IOException e) { } catch (IOException e) {
log.error("Error retrieving supported languages", e); e.printStackTrace();
return new HashSet<>();
} }
return supportedLanguages;
} }
} }

View File

@@ -39,7 +39,7 @@ public class MetricsAggregatorService {
if (method == null || uri == null) { if (method == null || uri == null) {
return; return;
} }
if (!"GET".equals(method) && !"POST".equals(method)) { if (!method.equals("GET") && !method.equals("POST")) {
return; return;
} }
// Skip URIs that are 2 characters or shorter // Skip URIs that are 2 characters or shorter

View File

@@ -26,8 +26,7 @@ public class FileToPdf {
HTMLToPdfRequest request, HTMLToPdfRequest request,
byte[] fileBytes, byte[] fileBytes,
String fileName, String fileName,
boolean htmlFormatsInstalled, boolean htmlFormatsInstalled)
boolean disableSanitize)
throws IOException, InterruptedException { throws IOException, InterruptedException {
Path tempOutputFile = Files.createTempFile("output_", ".pdf"); Path tempOutputFile = Files.createTempFile("output_", ".pdf");
@@ -37,13 +36,12 @@ public class FileToPdf {
if (fileName.endsWith(".html")) { if (fileName.endsWith(".html")) {
tempInputFile = Files.createTempFile("input_", ".html"); tempInputFile = Files.createTempFile("input_", ".html");
String sanitizedHtml = String sanitizedHtml =
sanitizeHtmlContent( sanitizeHtmlContent(new String(fileBytes, StandardCharsets.UTF_8));
new String(fileBytes, StandardCharsets.UTF_8), disableSanitize);
Files.write(tempInputFile, sanitizedHtml.getBytes(StandardCharsets.UTF_8)); Files.write(tempInputFile, sanitizedHtml.getBytes(StandardCharsets.UTF_8));
} else if (fileName.endsWith(".zip")) { } else if (fileName.endsWith(".zip")) {
tempInputFile = Files.createTempFile("input_", ".zip"); tempInputFile = Files.createTempFile("input_", ".zip");
Files.write(tempInputFile, fileBytes); Files.write(tempInputFile, fileBytes);
sanitizeHtmlFilesInZip(tempInputFile, disableSanitize); sanitizeHtmlFilesInZip(tempInputFile);
} else { } else {
throw new IllegalArgumentException("Unsupported file format: " + fileName); throw new IllegalArgumentException("Unsupported file format: " + fileName);
} }
@@ -91,12 +89,11 @@ public class FileToPdf {
return pdfBytes; return pdfBytes;
} }
private static String sanitizeHtmlContent(String htmlContent, boolean disableSanitize) { private static String sanitizeHtmlContent(String htmlContent) {
return (!disableSanitize) ? CustomHtmlSanitizer.sanitize(htmlContent) : htmlContent; return CustomHtmlSanitizer.sanitize(htmlContent);
} }
private static void sanitizeHtmlFilesInZip(Path zipFilePath, boolean disableSanitize) private static void sanitizeHtmlFilesInZip(Path zipFilePath) throws IOException {
throws IOException {
Path tempUnzippedDir = Files.createTempDirectory("unzipped_"); Path tempUnzippedDir = Files.createTempDirectory("unzipped_");
try (ZipInputStream zipIn = try (ZipInputStream zipIn =
ZipSecurity.createHardenedInputStream( ZipSecurity.createHardenedInputStream(
@@ -109,7 +106,7 @@ public class FileToPdf {
if (entry.getName().toLowerCase().endsWith(".html") if (entry.getName().toLowerCase().endsWith(".html")
|| entry.getName().toLowerCase().endsWith(".htm")) { || entry.getName().toLowerCase().endsWith(".htm")) {
String content = new String(zipIn.readAllBytes(), StandardCharsets.UTF_8); String content = new String(zipIn.readAllBytes(), StandardCharsets.UTF_8);
String sanitizedContent = sanitizeHtmlContent(content, disableSanitize); String sanitizedContent = sanitizeHtmlContent(content);
Files.write(filePath, sanitizedContent.getBytes(StandardCharsets.UTF_8)); Files.write(filePath, sanitizedContent.getBytes(StandardCharsets.UTF_8));
} else { } else {
Files.copy(zipIn, filePath); Files.copy(zipIn, filePath);

View File

@@ -9,17 +9,15 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import org.simpleyaml.configuration.file.YamlFile;
import org.simpleyaml.configuration.file.YamlFileWrapper;
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.fathzer.soft.javaluator.DoubleEvaluator; import com.fathzer.soft.javaluator.DoubleEvaluator;
@@ -287,10 +285,7 @@ public class GeneralUtils {
String[] rangeParts = part.split("-"); String[] rangeParts = part.split("-");
try { try {
int start = Integer.parseInt(rangeParts[0]); int start = Integer.parseInt(rangeParts[0]);
int end = int end = Integer.parseInt(rangeParts[1]);
(rangeParts.length > 1 && !rangeParts[1].isEmpty())
? Integer.parseInt(rangeParts[1])
: totalPages;
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
if (i >= 1 && i <= totalPages) { if (i >= 1 && i <= totalPages) {
partResult.add(i - 1 + offset); partResult.add(i - 1 + offset);
@@ -348,208 +343,41 @@ public class GeneralUtils {
public static void saveKeyToConfig(String id, String key, boolean autoGenerated) public static void saveKeyToConfig(String id, String key, boolean autoGenerated)
throws IOException { throws IOException {
doSaveKeyToConfig(id, (key == null ? "" : key), autoGenerated); Path path =
Paths.get(
InstallationPathConfig
.getSettingsPath()); // Target the configs/settings.yml
final YamlFile settingsYml = new YamlFile(path.toFile());
DumperOptions yamlOptionssettingsYml =
((SimpleYamlImplementation) settingsYml.getImplementation()).getDumperOptions();
yamlOptionssettingsYml.setSplitLines(false);
settingsYml.loadWithComments();
YamlFileWrapper writer = settingsYml.path(id).set(key);
if (autoGenerated) {
writer.comment("# Automatically Generated Settings (Do Not Edit Directly)");
}
settingsYml.save();
} }
public static void saveKeyToConfig(String id, boolean key, boolean autoGenerated) public static void saveKeyToConfig(String id, boolean key, boolean autoGenerated)
throws IOException { throws IOException {
doSaveKeyToConfig(id, String.valueOf(key), autoGenerated); Path path = Paths.get(InstallationPathConfig.getSettingsPath());
}
/*------------------------------------------------------------------------* final YamlFile settingsYml = new YamlFile(path.toFile());
* Internal Implementation Details * DumperOptions yamlOptionssettingsYml =
*------------------------------------------------------------------------*/ ((SimpleYamlImplementation) settingsYml.getImplementation()).getDumperOptions();
yamlOptionssettingsYml.setSplitLines(false);
/** settingsYml.loadWithComments();
* Actually performs the line-based update for the given path (e.g. "security.csrfDisabled") to
* a new string value (e.g. "true"), possibly marking it as auto-generated.
*/
private static void doSaveKeyToConfig(String fullPath, String newValue, boolean autoGenerated)
throws IOException {
// 1) Load the file (settings.yml)
Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath());
if (!Files.exists(settingsPath)) {
log.warn("Settings file not found at {}, creating a new empty file...", settingsPath);
Files.createDirectories(settingsPath.getParent());
Files.createFile(settingsPath);
}
List<String> lines = Files.readAllLines(settingsPath);
// 2) Build a map of "nestedKeyPath -> lineIndex" by parsing indentation YamlFileWrapper writer = settingsYml.path(id).set(key);
// Also track each line's indentation so we can preserve it when rewriting.
Map<String, LineInfo> pathToLine = parseNestedYamlKeys(lines);
// 3) If the path is found, rewrite its line. Else, append at the bottom (no indentation).
boolean changed = false;
if (pathToLine.containsKey(fullPath)) {
// Rewrite existing line
LineInfo info = pathToLine.get(fullPath);
String oldLine = lines.get(info.lineIndex);
String newLine =
rewriteLine(oldLine, info.indentSpaces, fullPath, newValue, autoGenerated);
if (!newLine.equals(oldLine)) {
lines.set(info.lineIndex, newLine);
changed = true;
}
} else {
// Append a new line at the bottom, with zero indentation
String appended = fullPath + ": " + newValue;
if (autoGenerated) {
appended += " # Automatically Generated Settings (Do Not Edit Directly)";
}
lines.add(appended);
changed = true;
}
// 4) If changed, write back to file
if (changed) {
Files.write(settingsPath, lines);
log.info(
"Updated '{}' to '{}' (autoGenerated={}) in {}",
fullPath,
newValue,
autoGenerated,
settingsPath);
} else {
log.info("No changes for '{}' (already set to '{}').", fullPath, newValue);
}
}
/** A small record-like class that holds: - lineIndex - indentSpaces */
private static class LineInfo {
int lineIndex;
int indentSpaces;
public LineInfo(int lineIndex, int indentSpaces) {
this.lineIndex = lineIndex;
this.indentSpaces = indentSpaces;
}
}
/**
* Parse the YAML lines to build a map: "full.nested.key" -> (lineIndex, indentSpaces). We do a
* naive indentation-based path stacking: - 2 spaces = 1 indent level - lines that start with
* fewer or equal indentation pop the stack - lines that look like "key:" or "key: value" cause
* a push
*/
private static Map<String, LineInfo> parseNestedYamlKeys(List<String> lines) {
Map<String, LineInfo> result = new HashMap<>();
// We'll maintain a stack of (keyName, indentLevel).
// Each line that looks like "myKey:" or "myKey: value" is a new "child" of the top of the
// stack if indent is deeper.
Deque<String> pathStack = new ArrayDeque<>();
Deque<Integer> indentStack = new ArrayDeque<>();
indentStack.push(-1); // sentinel
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
String trimmed = line.trim();
// skip blank lines, comment lines, or list items
if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith("-")) {
continue;
}
// check if there's a colon
int colonIdx = trimmed.indexOf(':');
if (colonIdx <= 0) { // must have at least one char before ':'
continue;
}
// parse out key
String keyPart = trimmed.substring(0, colonIdx).trim();
if (keyPart.isEmpty()) {
continue;
}
// count leading spaces for indentation
int leadingSpaces = countLeadingSpaces(line);
int indentLevel = leadingSpaces / 2; // assume 2 spaces per level
// pop from stack until we get to a shallower indentation
while (indentStack.peek() != null && indentStack.peek() >= indentLevel) {
indentStack.pop();
pathStack.pop();
}
// push the new key
pathStack.push(keyPart);
indentStack.push(indentLevel);
// build the full path
String[] arr = pathStack.toArray(new String[0]);
List<String> reversed = Arrays.asList(arr);
Collections.reverse(reversed);
String fullPath = String.join(".", reversed);
// store line info
result.put(fullPath, new LineInfo(i, leadingSpaces));
}
return result;
}
/**
* Rewrite a single line to set a new value, preserving indentation and (optionally) the
* existing or auto-generated inline comment.
*
* <p>For example, oldLine might be: " csrfDisabled: false # set to 'true' to disable CSRF
* protection" newValue = "true" autoGenerated = false
*
* <p>We'll produce something like: " csrfDisabled: true # set to 'true' to disable CSRF
* protection"
*/
private static String rewriteLine(
String oldLine, int indentSpaces, String path, String newValue, boolean autoGenerated) {
// We'll keep the exact leading indentation (indentSpaces).
// Then "key: newValue". We'll try to preserve any existing inline comment unless
// autoGenerated is true.
// 1) Extract leading spaces from the old line (just in case they differ from indentSpaces).
int actualLeadingSpaces = countLeadingSpaces(oldLine);
String leading = oldLine.substring(0, actualLeadingSpaces);
// 2) Remove leading spaces from the rest
String trimmed = oldLine.substring(actualLeadingSpaces);
// 3) Check for existing comment
int hashIndex = trimmed.indexOf('#');
String lineWithoutComment =
(hashIndex >= 0) ? trimmed.substring(0, hashIndex).trim() : trimmed.trim();
String oldComment = (hashIndex >= 0) ? trimmed.substring(hashIndex).trim() : "";
// 4) Rebuild "key: newValue"
// The "key" here is everything before ':' in lineWithoutComment
int colonIdx = lineWithoutComment.indexOf(':');
String existingKey =
(colonIdx >= 0)
? lineWithoutComment.substring(0, colonIdx).trim()
: path; // fallback if line is malformed
StringBuilder sb = new StringBuilder();
sb.append(leading); // restore original leading spaces
// "key: newValue"
sb.append(existingKey).append(": ").append(newValue);
// 5) If autoGenerated, add/replace comment
if (autoGenerated) { if (autoGenerated) {
sb.append(" # Automatically Generated Settings (Do Not Edit Directly)"); writer.comment("# Automatically Generated Settings (Do Not Edit Directly)");
} else {
// preserve the old comment if it exists
if (!oldComment.isEmpty()) {
sb.append(" ").append(oldComment);
}
} }
return sb.toString(); settingsYml.save();
}
private static int countLeadingSpaces(String line) {
int count = 0;
for (char c : line.toCharArray()) {
if (c == ' ') count++;
else break;
}
return count;
} }
public static String generateMachineFingerprint() { public static String generateMachineFingerprint() {
@@ -587,7 +415,9 @@ public class GeneralUtils {
for (byte b : hash) { for (byte b : hash) {
fingerprint.append(String.format("%02x", b)); fingerprint.append(String.format("%02x", b));
} }
return fingerprint.toString(); return fingerprint.toString();
} catch (Exception e) { } catch (Exception e) {
return "GenericID"; return "GenericID";
} }

View File

@@ -20,9 +20,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;
import com.vladsch.flexmark.util.data.MutableDataSet;
import io.github.pixee.security.Filenames; import io.github.pixee.security.Filenames;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -31,123 +28,6 @@ import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@Slf4j @Slf4j
public class PDFToFile { public class PDFToFile {
public ResponseEntity<byte[]> processPdfToMarkdown(MultipartFile inputFile)
throws IOException, InterruptedException {
if (!"application/pdf".equals(inputFile.getContentType())) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
MutableDataSet options =
new MutableDataSet()
.set(
FlexmarkHtmlConverter.MAX_BLANK_LINES,
2) // Control max consecutive blank lines
.set(
FlexmarkHtmlConverter.MAX_TRAILING_BLANK_LINES,
1) // Control trailing blank lines
.set(
FlexmarkHtmlConverter.SETEXT_HEADINGS,
true) // Use Setext headings for h1 and h2
.set(
FlexmarkHtmlConverter.OUTPUT_UNKNOWN_TAGS,
false) // Don't output HTML for unknown tags
.set(
FlexmarkHtmlConverter.TYPOGRAPHIC_QUOTES,
true) // Convert quotation marks
.set(
FlexmarkHtmlConverter.BR_AS_PARA_BREAKS,
true) // Convert <br> to paragraph breaks
.set(FlexmarkHtmlConverter.CODE_INDENT, " "); // Indent for code blocks
FlexmarkHtmlConverter htmlToMarkdownConverter =
FlexmarkHtmlConverter.builder(options).build();
String originalPdfFileName = Filenames.toSimpleFileName(inputFile.getOriginalFilename());
String pdfBaseName = originalPdfFileName;
if (originalPdfFileName.contains(".")) {
pdfBaseName = originalPdfFileName.substring(0, originalPdfFileName.lastIndexOf('.'));
}
Path tempInputFile = null;
Path tempOutputDir = null;
byte[] fileBytes;
String fileName = "temp.file";
try {
tempInputFile = Files.createTempFile("input_", ".pdf");
inputFile.transferTo(tempInputFile);
tempOutputDir = Files.createTempDirectory("output_");
List<String> command =
new ArrayList<>(
Arrays.asList(
"pdftohtml",
"-s",
"-noframes",
"-c",
tempInputFile.toString(),
pdfBaseName));
ProcessExecutorResult returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML)
.runCommandWithOutputHandling(command, tempOutputDir.toFile());
// Process HTML files to Markdown
File[] outputFiles = Objects.requireNonNull(tempOutputDir.toFile().listFiles());
List<File> markdownFiles = new ArrayList<>();
// Convert HTML files to Markdown
for (File outputFile : outputFiles) {
if (outputFile.getName().endsWith(".html")) {
String html = Files.readString(outputFile.toPath());
String markdown = htmlToMarkdownConverter.convert(html);
String mdFileName = outputFile.getName().replace(".html", ".md");
File mdFile = new File(tempOutputDir.toFile(), mdFileName);
Files.writeString(mdFile.toPath(), markdown);
markdownFiles.add(mdFile);
}
}
// If there's only one markdown file, return it directly
if (markdownFiles.size() == 1) {
fileName = pdfBaseName + ".md";
fileBytes = Files.readAllBytes(markdownFiles.get(0).toPath());
} else {
// Multiple files - create a zip
fileName = pdfBaseName + "ToMarkdown.zip";
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
// Add markdown files
for (File mdFile : markdownFiles) {
ZipEntry mdEntry = new ZipEntry(mdFile.getName());
zipOutputStream.putNextEntry(mdEntry);
Files.copy(mdFile.toPath(), zipOutputStream);
zipOutputStream.closeEntry();
}
// Add images and other assets
for (File file : outputFiles) {
if (!file.getName().endsWith(".html") && !file.getName().endsWith(".md")) {
ZipEntry assetEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(assetEntry);
Files.copy(file.toPath(), zipOutputStream);
zipOutputStream.closeEntry();
}
}
}
fileBytes = byteArrayOutputStream.toByteArray();
}
} finally {
if (tempInputFile != null) Files.deleteIfExists(tempInputFile);
if (tempOutputDir != null) FileUtils.deleteDirectory(tempOutputDir.toFile());
}
return WebResponseUtils.bytesToWebResponse(
fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
}
public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile) public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile)
throws IOException, InterruptedException { throws IOException, InterruptedException {
if (!"application/pdf".equals(inputFile.getContentType())) { if (!"application/pdf".equals(inputFile.getContentType())) {

View File

@@ -138,7 +138,6 @@ analytics.settings=يمكنك تغيير إعدادات الإحصائيات ف
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=المفضلة navbar.favorite=المفضلة
navbar.recent=New and recently updated
navbar.darkmode=الوضع الداكن navbar.darkmode=الوضع الداكن
navbar.language=اللغات navbar.language=اللغات
navbar.settings=إعدادات navbar.settings=إعدادات
@@ -266,15 +265,6 @@ home.viewPdf.title=عرض PDF
home.viewPdf.desc=عرض وتعليق وإضافة نص أو صور home.viewPdf.desc=عرض وتعليق وإضافة نص أو صور
viewPdf.tags=عرض,قراءة,تعليق,نص,صورة 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.multiTool.title=أداة متعددة PDF home.multiTool.title=أداة متعددة PDF
home.multiTool.desc=دمج الصفحات وتدويرها وإعادة ترتيبها وإزالتها home.multiTool.desc=دمج الصفحات وتدويرها وإعادة ترتيبها وإزالتها
multiTool.tags=أداة متعددة,عملية متعددة,واجهة مستخدم,النقر والسحب,واجهة أمامية,جانب العميل multiTool.tags=أداة متعددة,عملية متعددة,واجهة مستخدم,النقر والسحب,واجهة أمامية,جانب العميل
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown إلى PDF
home.MarkdownToPDF.desc=يحول أي ملف Markdown إلى PDF home.MarkdownToPDF.desc=يحول أي ملف Markdown إلى PDF
MarkdownToPDF.tags=لغة الترميز,محتوى الويب,تحويل,تحويل MarkdownToPDF.tags=لغة الترميز,محتوى الويب,تحويل,تحويل
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=الحصول على جميع المعلومات عن PDF home.getPdfInfo.title=الحصول على جميع المعلومات عن PDF
home.getPdfInfo.desc=يجمع أي وكل المعلومات الممكنة عن ملفات PDF home.getPdfInfo.desc=يجمع أي وكل المعلومات الممكنة عن ملفات PDF
@@ -659,11 +646,6 @@ MarkdownToPDF.help=العمل قيد التقدم
MarkdownToPDF.credit=يستخدم WeasyPrint MarkdownToPDF.credit=يستخدم WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL إلى PDF URLToPDF.title=URL إلى PDF

View File

@@ -138,7 +138,6 @@ analytics.settings=Analitikanın parametrlərini config/settings.yml faylından
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Sevimlilər navbar.favorite=Sevimlilər
navbar.recent=New and recently updated
navbar.darkmode=Qaranlıq Tema navbar.darkmode=Qaranlıq Tema
navbar.language=Dillər navbar.language=Dillər
navbar.settings=Parametrlər navbar.settings=Parametrlər
@@ -266,15 +265,6 @@ home.viewPdf.title=PDF-ə bax
home.viewPdf.desc=Bax, sitat götür, mətn və ya şəkil əlavə et home.viewPdf.desc=Bax, sitat götür, mətn və ya şəkil əlavə et
viewPdf.tags=bax,oxu,sitat götür,mətn,şəkil viewPdf.tags=bax,oxu,sitat götür,mətn,şəkil
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.multiTool.title=PDF Multi-alət home.multiTool.title=PDF Multi-alət
home.multiTool.desc=Səhifələri Birləşdir, Çevir, Yenidən Sırala, Böl və Sil home.multiTool.desc=Səhifələri Birləşdir, Çevir, Yenidən Sırala, Böl və Sil
multiTool.tags=Multi-alət,Çoxlu əməliyyat,UI,tut-sürüşdür,front end,istifadəçi-tərəf,interaktiv,qarşılıqlı,yerini dəyiş,sil,köçür,böl multiTool.tags=Multi-alət,Çoxlu əməliyyat,UI,tut-sürüşdür,front end,istifadəçi-tərəf,interaktiv,qarşılıqlı,yerini dəyiş,sil,köçür,böl
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown-dan PDF-ə
home.MarkdownToPDF.desc=Hər hansı Markdown faylını PDF-ə çevirir home.MarkdownToPDF.desc=Hər hansı Markdown faylını PDF-ə çevirir
MarkdownToPDF.tags=işarələmə,web-məzmun,dəyişmə,çevirmə MarkdownToPDF.tags=işarələmə,web-məzmun,dəyişmə,çevirmə
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=PDF-in Bütün Məlumatları home.getPdfInfo.title=PDF-in Bütün Məlumatları
home.getPdfInfo.desc=PDF barədə mümkün olan bütün məlumatları əldə edir home.getPdfInfo.desc=PDF barədə mümkün olan bütün məlumatları əldə edir
@@ -659,11 +646,6 @@ MarkdownToPDF.help=İş davam edir
MarkdownToPDF.credit=WeasyPrint İstifadə Edir MarkdownToPDF.credit=WeasyPrint İstifadə Edir
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL-i PDF-ə URLToPDF.title=URL-i PDF-ə

View File

@@ -138,7 +138,6 @@ analytics.settings=Можете да промените настройките
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Любими navbar.favorite=Любими
navbar.recent=New and recently updated
navbar.darkmode=Тъмна тема navbar.darkmode=Тъмна тема
navbar.language=Езици navbar.language=Езици
navbar.settings=Настройки navbar.settings=Настройки
@@ -266,15 +265,6 @@ home.viewPdf.title=Преглед на PDF
home.viewPdf.desc=Преглеждайте, коментирайте, добавяйте текст или изображения home.viewPdf.desc=Преглеждайте, коментирайте, добавяйте текст или изображения
viewPdf.tags=преглед,четене,анотиране,текст,изображение 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.multiTool.title=PDF Мулти инструмент home.multiTool.title=PDF Мулти инструмент
home.multiTool.desc=Обединяване, завъртане, пренареждане и премахване на страници home.multiTool.desc=Обединяване, завъртане, пренареждане и премахване на страници
multiTool.tags=Мултиинструмент,Мулти операции,UI,плъзгане с щракване,потребителска част,страна на клиента,интерактивен,неразрешим,преместване multiTool.tags=Мултиинструмент,Мулти операции,UI,плъзгане с щракване,потребителска част,страна на клиента,интерактивен,неразрешим,преместване
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown към PDF
home.MarkdownToPDF.desc=Преобразува всеки Markdown файл към PDF home.MarkdownToPDF.desc=Преобразува всеки Markdown файл към PDF
MarkdownToPDF.tags=маркиране,уеб-съдържание,трансформация,преобразуване MarkdownToPDF.tags=маркиране,уеб-съдържание,трансформация,преобразуване
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Вземете ЦЯЛАТА информация от PDF home.getPdfInfo.title=Вземете ЦЯЛАТА информация от PDF
home.getPdfInfo.desc=Взима всяка възможна информация от PDF файлове home.getPdfInfo.desc=Взима всяка възможна информация от PDF файлове
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Работата е в ход
MarkdownToPDF.credit=Използва WeasyPrint MarkdownToPDF.credit=Използва WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL към PDF URLToPDF.title=URL към PDF

View File

@@ -138,7 +138,6 @@ analytics.settings=Pots canviar la configuració de les analítiques al fitxer c
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favorits navbar.favorite=Favorits
navbar.recent=New and recently updated
navbar.darkmode=Mode Fosc navbar.darkmode=Mode Fosc
navbar.language=Idiomes navbar.language=Idiomes
navbar.settings=Opcions navbar.settings=Opcions
@@ -266,15 +265,6 @@ home.viewPdf.title=Visualitza PDF
home.viewPdf.desc=Visualitza, anota, afegeix text o imatges home.viewPdf.desc=Visualitza, anota, afegeix text o imatges
viewPdf.tags=view,read,annotate,text,image viewPdf.tags=view,read,annotate,text,image
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.multiTool.title=Eina Multifunció de PDF home.multiTool.title=Eina Multifunció de PDF
home.multiTool.desc=Fusiona, Rota, Reorganitza i Esborra pàgines home.multiTool.desc=Fusiona, Rota, Reorganitza i Esborra pàgines
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown a PDF
home.MarkdownToPDF.desc=Converteix qualsevol fitxer Markdown a PDF home.MarkdownToPDF.desc=Converteix qualsevol fitxer Markdown a PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert MarkdownToPDF.tags=markup,web-content,transformation,convert
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Obteniu Tota la Informació sobre el PDF home.getPdfInfo.title=Obteniu Tota la Informació sobre el PDF
home.getPdfInfo.desc=Recupera tota la informació possible sobre els PDFs home.getPdfInfo.desc=Recupera tota la informació possible sobre els PDFs
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Work in progress
MarkdownToPDF.credit=Uses WeasyPrint MarkdownToPDF.credit=Uses WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL a PDF URLToPDF.title=URL a PDF

File diff suppressed because it is too large Load Diff

View File

@@ -138,7 +138,6 @@ analytics.settings=Du kan ændre analytics-indstillingerne i config/settings.yml
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favoritter navbar.favorite=Favoritter
navbar.recent=New and recently updated
navbar.darkmode=Mørk Tilstand navbar.darkmode=Mørk Tilstand
navbar.language=Sprog navbar.language=Sprog
navbar.settings=Indstillinger navbar.settings=Indstillinger
@@ -266,15 +265,6 @@ home.viewPdf.title=Se PDF
home.viewPdf.desc=Se, annotér, tilføj tekst eller billeder home.viewPdf.desc=Se, annotér, tilføj tekst eller billeder
viewPdf.tags=se,læs,annotér,tekst,billede viewPdf.tags=se,læs,annotér,tekst,billede
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.multiTool.title=PDF Multi Værktøj home.multiTool.title=PDF Multi Værktøj
home.multiTool.desc=Flet, Rotér, Omarrangér og Fjern sider home.multiTool.desc=Flet, Rotér, Omarrangér og Fjern sider
multiTool.tags=Multi Værktøj,Multi operation,UI,klik træk,front end,klient side,interaktiv,interagerbar,flyt multiTool.tags=Multi Værktøj,Multi operation,UI,klik træk,front end,klient side,interaktiv,interagerbar,flyt
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown til PDF
home.MarkdownToPDF.desc=Konverterer enhver Markdown-fil til PDF home.MarkdownToPDF.desc=Konverterer enhver Markdown-fil til PDF
MarkdownToPDF.tags=markup,webindhold,transformation,konvertér MarkdownToPDF.tags=markup,webindhold,transformation,konvertér
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Få ALLE Oplysninger om PDF home.getPdfInfo.title=Få ALLE Oplysninger om PDF
home.getPdfInfo.desc=Henter alle mulige oplysninger om PDF'er home.getPdfInfo.desc=Henter alle mulige oplysninger om PDF'er
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Arbejde i gang
MarkdownToPDF.credit=Bruger WeasyPrint MarkdownToPDF.credit=Bruger WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL Til PDF URLToPDF.title=URL Til PDF

View File

@@ -82,7 +82,7 @@ pages=Seiten
loading=Laden... loading=Laden...
addToDoc=In Dokument hinzufügen addToDoc=In Dokument hinzufügen
reset=Zurücksetzen reset=Zurücksetzen
apply=Anwenden apply=Apply
legal.privacy=Datenschutz legal.privacy=Datenschutz
legal.terms=AGB legal.terms=AGB
@@ -138,7 +138,6 @@ analytics.settings=Sie können die Einstellungen für die Analytics in der confi
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favoriten navbar.favorite=Favoriten
navbar.recent=Neu und kürzlich aktualisiert
navbar.darkmode=Dunkler Modus navbar.darkmode=Dunkler Modus
navbar.language=Sprachen navbar.language=Sprachen
navbar.settings=Einstellungen navbar.settings=Einstellungen
@@ -250,7 +249,7 @@ database.backupCreated=Datenbanksicherung erfolgreich
database.fileNotFound=Datei nicht gefunden database.fileNotFound=Datei nicht gefunden
database.fileNullOrEmpty=Datei darf nicht null oder leer sein database.fileNullOrEmpty=Datei darf nicht null oder leer sein
database.failedImportFile=Dateiimport fehlgeschlagen database.failedImportFile=Dateiimport fehlgeschlagen
database.notSupported=Diese Funktion ist für deine Datenbankverbindung nicht verfügbar. database.notSupported=This function is not available for your database connection.
session.expired=Ihre Sitzung ist abgelaufen. Bitte laden Sie die Seite neu und versuchen Sie es erneut. session.expired=Ihre Sitzung ist abgelaufen. Bitte laden Sie die Seite neu und versuchen Sie es erneut.
session.refreshPage=Seite aktualisieren session.refreshPage=Seite aktualisieren
@@ -266,22 +265,13 @@ home.viewPdf.title=PDF anzeigen
home.viewPdf.desc=Anzeigen, Kommentieren, Text oder Bilder hinzufügen home.viewPdf.desc=Anzeigen, Kommentieren, Text oder Bilder hinzufügen
viewPdf.tags=anzeigen,lesen,kommentieren,text,bild viewPdf.tags=anzeigen,lesen,kommentieren,text,bild
home.setFavorites=Favoriten festlegen
home.hideFavorites=Favoriten ausblenden
home.showFavorites=Favoriten anzeigen
home.legacyHomepage=Alte Homepage
home.newHomePage=Probieren Sie unsere neue Homepage aus!
home.alphabetical=Alphabetisch
home.globalPopularity=Beliebtheit
home.sortBy=Sort by:
home.multiTool.title=PDF-Multitool home.multiTool.title=PDF-Multitool
home.multiTool.desc=Seiten zusammenführen, drehen, neu anordnen und entfernen home.multiTool.desc=Seiten zusammenführen, drehen, neu anordnen und entfernen
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
home.merge.title=Zusammenführen home.merge.title=Zusammenführen
home.merge.desc=Mehrere PDF-Dateien zu einer einzigen zusammenführen home.merge.desc=Mehrere PDF-Dateien zu einer einzigen zusammenführen
merge.tags=zusammenführen,seitenvorgänge,back end,serverseitig merge.tags=zusammenführen,seitenvorgänge,back end,serverseite
home.split.title=Aufteilen home.split.title=Aufteilen
home.split.desc=PDFs in mehrere Dokumente aufteilen home.split.desc=PDFs in mehrere Dokumente aufteilen
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown zu PDF
home.MarkdownToPDF.desc=Konvertiert jede Markdown-Datei zu PDF home.MarkdownToPDF.desc=Konvertiert jede Markdown-Datei zu PDF
MarkdownToPDF.tags=markup,web-content,transformation,konvertieren MarkdownToPDF.tags=markup,web-content,transformation,konvertieren
home.PDFToMarkdown.title=PDF zu Markdown
home.PDFToMarkdown.desc=Konvertiert jedes PDF in Markdown
PDFToMarkdown.tags=markup,web inhalt,transformation,konvertieren,md
home.getPdfInfo.title=Alle Informationen anzeigen home.getPdfInfo.title=Alle Informationen anzeigen
home.getPdfInfo.desc=Erfasst alle möglichen Informationen in einer PDF home.getPdfInfo.desc=Erfasst alle möglichen Informationen in einer PDF
@@ -489,9 +476,9 @@ home.autoRedact.title=Automatisch zensieren/schwärzen
home.autoRedact.desc=Automatisches Zensieren (Schwärzen) von Text in einer PDF-Datei basierend auf dem eingegebenen Text home.autoRedact.desc=Automatisches Zensieren (Schwärzen) von Text in einer PDF-Datei basierend auf dem eingegebenen Text
autoRedact.tags=zensieren,schwärzen autoRedact.tags=zensieren,schwärzen
home.redact.title=Manuell zensieren/schwärzen home.redact.title=Manual Redaction
home.redact.desc=Zensiere (Schwärze) eine PDF-Datei durch Auswählen von Text, gezeichneten Formen und/oder ausgewählten Seite(n) home.redact.desc=Redacts a PDF based on selected text, drawn shapes and/or selected page(s)
redact.tags=zensieren,schwärzen,verstecken,verdunkeln,schwarz,markieren,verbergen,manuell redact.tags=Redact,Hide,black out,black,marker,hidden,manual
home.tableExtraxt.title=Tabelle extrahieren home.tableExtraxt.title=Tabelle extrahieren
home.tableExtraxt.desc=Tabelle aus PDF in CSV extrahieren home.tableExtraxt.desc=Tabelle aus PDF in CSV extrahieren
@@ -599,30 +586,30 @@ autoRedact.convertPDFToImageLabel=PDF in PDF-Bild konvertieren (zum Entfernen vo
autoRedact.submitButton=Zensieren autoRedact.submitButton=Zensieren
#redact #redact
redact.title=Manuelles Zensieren (Schwärzen) redact.title=Manual Redaction
redact.header=Manuelles Zensieren (Schwärzen) redact.header=Manual Redaction
redact.submit=Zensieren redact.submit=Redact
redact.textBasedRedaction=Textbasiertes Zensieren redact.textBasedRedaction=Text based Redaction
redact.pageBasedRedaction=Seitenweises Zensieren redact.pageBasedRedaction=Page-based Redaction
redact.convertPDFToImageLabel=Konvertiere PDF zu einem Bild (Zum Entfernen von Text hinter der Box verwenden) redact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
redact.pageRedactionNumbers.title=Seiten redact.pageRedactionNumbers.title=Pages
redact.pageRedactionNumbers.placeholder=(z.B. 1,2,8 oder 4,7,12-16 oder 2n-1) redact.pageRedactionNumbers.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
redact.redactionColor.title=Zensurfarbe redact.redactionColor.title=Redaction Color
redact.export=Exportieren redact.export=Export
redact.upload=Hochladen redact.upload=Upload
redact.boxRedaction=Rechteck zeichnen zum zensieren redact.boxRedaction=Box draw redaction
redact.zoom=Zoom redact.zoom=Zoom
redact.zoomIn=Vergrößern redact.zoomIn=Zoom in
redact.zoomOut=Verkleinern redact.zoomOut=Zoom out
redact.nextPage=Nächste Seite redact.nextPage=Next Page
redact.previousPage=Vorherige Seite redact.previousPage=Previous Page
redact.toggleSidebar=Seitenleiste umschalten redact.toggleSidebar=Toggle Sidebar
redact.showThumbnails=Vorschau anzeigen redact.showThumbnails=Show Thumbnails
redact.showDocumentOutline=Dokumentübersicht anzeigen (Doppelklick zum Auf/Einklappen aller Elemente) redact.showDocumentOutline=Show Document Outline (double-click to expand/collapse all items)
redact.showAttatchments=Zeige Anhänge redact.showAttatchments=Show Attachments
redact.showLayers=Ebenen anzeigen (Doppelklick, um alle Ebenen auf den Standardzustand zurückzusetzen) redact.showLayers=Show Layers (double-click to reset all layers to the default state)
redact.colourPicker=Farbauswahl redact.colourPicker=Colour Picker
redact.findCurrentOutlineItem=Aktuell gewähltes Element finden redact.findCurrentOutlineItem=Find current outline item
#showJS #showJS
showJS.title=Javascript anzeigen showJS.title=Javascript anzeigen
@@ -659,11 +646,6 @@ MarkdownToPDF.help=In Arbeit
MarkdownToPDF.credit=Verwendet WeasyPrint MarkdownToPDF.credit=Verwendet WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF zu Markdown
PDFToMarkdown.header=PDF zu Markdown
PDFToMarkdown.submit=Konvertieren
#url-to-pdf #url-to-pdf
URLToPDF.title=URL zu PDF URLToPDF.title=URL zu PDF
@@ -880,7 +862,7 @@ sign.first=Erste Seite
sign.last=Letzte Seite sign.last=Letzte Seite
sign.next=Nächste Seite sign.next=Nächste Seite
sign.previous=Vorherige Seite sign.previous=Vorherige Seite
sign.maintainRatio=Seitenverhältnis beibehalten ein-/ausschalten sign.maintainRatio=Toggle maintain aspect ratio
#repair #repair
@@ -952,7 +934,7 @@ compress.title=Komprimieren
compress.header=PDF komprimieren compress.header=PDF komprimieren
compress.credit=Dieser Dienst verwendet qpdf für die PDF-Komprimierung/-Optimierung. compress.credit=Dieser Dienst verwendet qpdf für die PDF-Komprimierung/-Optimierung.
compress.selectText.1=Manueller Modus Von 1 bis 5 compress.selectText.1=Manueller Modus Von 1 bis 5
compress.selectText.1.1=In den Optimierungsstufen 6 bis 9 wird zusätzlich zur allgemeinen PDF-Komprimierung die Bildauflösung reduziert, um die Dateigröße weiter zu verringern. Höhere Stufen führen zu einer stärkeren Bildkomprimierung (bis zu 50 % der Originalgröße), wodurch eine stärkere Größenreduzierung erreicht wird, die jedoch mit einem möglichen Qualitätsverlust der Bilder einhergeht. compress.selectText.1.1=In optimization levels 6 to 9, in addition to general PDF compression, image resolution is scaled down to further reduce file size. Higher levels result in stronger image compression (up to 50% of the original size), achieving greater size reduction but with potential quality loss in images.
compress.selectText.2=Optimierungsstufe: compress.selectText.2=Optimierungsstufe:
compress.selectText.3=4 (Schrecklich für Textbilder) compress.selectText.3=4 (Schrecklich für Textbilder)
compress.selectText.4=Automatischer Modus Passt die Qualität automatisch an, um das PDF auf die exakte Größe zu bringen compress.selectText.4=Automatischer Modus Passt die Qualität automatisch an, um das PDF auf die exakte Größe zu bringen
@@ -1338,8 +1320,8 @@ splitByChapters.submit=PDF teilen
fileChooser.click=Klicken fileChooser.click=Klicken
fileChooser.or=oder fileChooser.or=oder
fileChooser.dragAndDrop=Drag & Drop fileChooser.dragAndDrop=Drag & Drop
fileChooser.dragAndDropPDF=Drag & Drop PDF-Datei fileChooser.dragAndDropPDF=Drag & Drop PDF file
fileChooser.dragAndDropImage=Drag & Drop Bilddatei fileChooser.dragAndDropImage=Drag & Drop Image file
fileChooser.hoveredDragAndDrop=Datei(en) hierhin Ziehen & Fallenlassen fileChooser.hoveredDragAndDrop=Datei(en) hierhin Ziehen & Fallenlassen
#release notes #release notes

File diff suppressed because it is too large Load Diff

View File

@@ -138,7 +138,6 @@ analytics.settings=You can change the settings for analytics in the config/setti
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favorites navbar.favorite=Favorites
navbar.recent=New and recently updated
navbar.darkmode=Dark Mode navbar.darkmode=Dark Mode
navbar.language=Languages navbar.language=Languages
navbar.settings=Settings navbar.settings=Settings
@@ -266,15 +265,6 @@ home.viewPdf.title=View PDF
home.viewPdf.desc=View, annotate, add text or images home.viewPdf.desc=View, annotate, add text or images
viewPdf.tags=view,read,annotate,text,image viewPdf.tags=view,read,annotate,text,image
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.multiTool.title=PDF Multi Tool home.multiTool.title=PDF Multi Tool
home.multiTool.desc=Merge, Rotate, Rearrange, Split, and Remove pages home.multiTool.desc=Merge, Rotate, Rearrange, Split, and Remove pages
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move,delete,migrate,divide multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move,delete,migrate,divide
@@ -460,11 +450,8 @@ HTMLToPDF.tags=markup,web-content,transformation,convert
home.MarkdownToPDF.title=Markdown to PDF home.MarkdownToPDF.title=Markdown to PDF
home.MarkdownToPDF.desc=Converts any Markdown file to PDF home.MarkdownToPDF.desc=Converts any Markdown file to PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert,md MarkdownToPDF.tags=markup,web-content,transformation,convert
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Get ALL Info on PDF home.getPdfInfo.title=Get ALL Info on PDF
home.getPdfInfo.desc=Grabs any and all information possible on PDFs home.getPdfInfo.desc=Grabs any and all information possible on PDFs
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Work in progress
MarkdownToPDF.credit=Uses WeasyPrint MarkdownToPDF.credit=Uses WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL To PDF URLToPDF.title=URL To PDF
@@ -1017,8 +999,8 @@ multiTool.moveLeft=Move Left
multiTool.moveRight=Move Right multiTool.moveRight=Move Right
multiTool.delete=Delete multiTool.delete=Delete
multiTool.dragDropMessage=Page(s) Selected multiTool.dragDropMessage=Page(s) Selected
multiTool.undo=Undo (CTRL + Z) multiTool.undo=Undo
multiTool.redo=Redo (CTRL + Y) multiTool.redo=Redo
#decrypt #decrypt
decrypt.passwordPrompt=This file is password-protected. Please enter the password: decrypt.passwordPrompt=This file is password-protected. Please enter the password:

View File

@@ -138,7 +138,6 @@ analytics.settings=You can change the settings for analytics in the config/setti
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favorites navbar.favorite=Favorites
navbar.recent=New and recently updated
navbar.darkmode=Dark Mode navbar.darkmode=Dark Mode
navbar.language=Languages navbar.language=Languages
navbar.settings=Settings navbar.settings=Settings
@@ -266,15 +265,6 @@ home.viewPdf.title=View PDF
home.viewPdf.desc=View, annotate, add text or images home.viewPdf.desc=View, annotate, add text or images
viewPdf.tags=view,read,annotate,text,image viewPdf.tags=view,read,annotate,text,image
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.multiTool.title=PDF Multi Tool home.multiTool.title=PDF Multi Tool
home.multiTool.desc=Merge, Rotate, Rearrange, Split, and Remove pages home.multiTool.desc=Merge, Rotate, Rearrange, Split, and Remove pages
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move,delete,migrate,divide multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move,delete,migrate,divide
@@ -460,11 +450,8 @@ HTMLToPDF.tags=markup,web-content,transformation,convert
home.MarkdownToPDF.title=Markdown to PDF home.MarkdownToPDF.title=Markdown to PDF
home.MarkdownToPDF.desc=Converts any Markdown file to PDF home.MarkdownToPDF.desc=Converts any Markdown file to PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert,md MarkdownToPDF.tags=markup,web-content,transformation,convert
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Get ALL Info on PDF home.getPdfInfo.title=Get ALL Info on PDF
home.getPdfInfo.desc=Grabs any and all information possible on PDFs home.getPdfInfo.desc=Grabs any and all information possible on PDFs
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Work in progress
MarkdownToPDF.credit=Uses WeasyPrint MarkdownToPDF.credit=Uses WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL To PDF URLToPDF.title=URL To PDF

View File

@@ -138,7 +138,6 @@ analytics.settings=Puede cambiar la configuración de analíticas en el archivo
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favoritos navbar.favorite=Favoritos
navbar.recent=New and recently updated
navbar.darkmode=Modo oscuro navbar.darkmode=Modo oscuro
navbar.language=Idiomas navbar.language=Idiomas
navbar.settings=Configuración navbar.settings=Configuración
@@ -266,15 +265,6 @@ home.viewPdf.title=Ver PDF
home.viewPdf.desc=Ver, anotar, añadir texto o imágenes home.viewPdf.desc=Ver, anotar, añadir texto o imágenes
viewPdf.tags=ver,leer,anotar,texto,imagen viewPdf.tags=ver,leer,anotar,texto,imagen
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.multiTool.title=Multi-herramienta PDF home.multiTool.title=Multi-herramienta PDF
home.multiTool.desc=Combinar, rotar, reorganizar y eliminar páginas home.multiTool.desc=Combinar, rotar, reorganizar y eliminar páginas
multiTool.tags=Multi-herramienta,Multi-operación,Interfaz de usuario,Arrastrar con un click,front end,lado del cliente multiTool.tags=Multi-herramienta,Multi-operación,Interfaz de usuario,Arrastrar con un click,front end,lado del cliente
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown a PDF
home.MarkdownToPDF.desc=Convierte cualquier archivo Markdown a PDF home.MarkdownToPDF.desc=Convierte cualquier archivo Markdown a PDF
MarkdownToPDF.tags=margen,contenido web,transformación,convertir MarkdownToPDF.tags=margen,contenido web,transformación,convertir
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Obtener toda la información en PDF home.getPdfInfo.title=Obtener toda la información en PDF
home.getPdfInfo.desc=Obtiene toda la información posible de archivos PDF home.getPdfInfo.desc=Obtiene toda la información posible de archivos PDF
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Tarea en proceso
MarkdownToPDF.credit=Usa WeasyPrint MarkdownToPDF.credit=Usa WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL a PDF URLToPDF.title=URL a PDF

View File

@@ -138,7 +138,6 @@ analytics.settings=You can change the settings for analytics in the config/setti
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favorites navbar.favorite=Favorites
navbar.recent=New and recently updated
navbar.darkmode=Modu iluna navbar.darkmode=Modu iluna
navbar.language=Languages navbar.language=Languages
navbar.settings=Ezarpenak navbar.settings=Ezarpenak
@@ -266,15 +265,6 @@ home.viewPdf.title=View PDF
home.viewPdf.desc=View, annotate, add text or images home.viewPdf.desc=View, annotate, add text or images
viewPdf.tags=view,read,annotate,text,image viewPdf.tags=view,read,annotate,text,image
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.multiTool.title=Erabilera anitzeko tresna PDF home.multiTool.title=Erabilera anitzeko tresna PDF
home.multiTool.desc=Orriak konbinatu, biratu, berrantolatu eta ezabatu home.multiTool.desc=Orriak konbinatu, biratu, berrantolatu eta ezabatu
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown PDF-ra
home.MarkdownToPDF.desc=Bihurtu Markdown fitxategi guztiak PDF home.MarkdownToPDF.desc=Bihurtu Markdown fitxategi guztiak PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert MarkdownToPDF.tags=markup,web-content,transformation,convert
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Lortu informazio guztia PDF-tik home.getPdfInfo.title=Lortu informazio guztia PDF-tik
home.getPdfInfo.desc=Eskuratu PDF fitxategiko Informazio guztia home.getPdfInfo.desc=Eskuratu PDF fitxategiko Informazio guztia
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Lanean
MarkdownToPDF.credit=WeasyPrint darabil MarkdownToPDF.credit=WeasyPrint darabil
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL bat PDF-ra URLToPDF.title=URL bat PDF-ra

View File

@@ -138,7 +138,6 @@ analytics.settings=می‌توانید تنظیمات مربوط به تحلیل
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=علاقه‌مندی‌ها navbar.favorite=علاقه‌مندی‌ها
navbar.recent=New and recently updated
navbar.darkmode=حالت تاریک navbar.darkmode=حالت تاریک
navbar.language=زبان‌ها navbar.language=زبان‌ها
navbar.settings=تنظیمات navbar.settings=تنظیمات
@@ -266,15 +265,6 @@ home.viewPdf.title=مشاهده PDF
home.viewPdf.desc=مشاهده، حاشیه‌نویسی، افزودن متن یا تصاویر home.viewPdf.desc=مشاهده، حاشیه‌نویسی، افزودن متن یا تصاویر
viewPdf.tags=مشاهده،خواندن،حاشیه‌نویسی،متن،تصویر 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.multiTool.title=ابزار چندگانه PDF home.multiTool.title=ابزار چندگانه PDF
home.multiTool.desc=ترکیب، چرخش، بازآرایی، تقسیم و حذف صفحات home.multiTool.desc=ترکیب، چرخش، بازآرایی، تقسیم و حذف صفحات
multiTool.tags=ابزار چندگانه،عملیات چندگانه،واسط کاربری،کلیک و کشیدن،فرانت‌اند،کاربردی،قابل تعامل،جابجایی،حذف،تقسیم multiTool.tags=ابزار چندگانه،عملیات چندگانه،واسط کاربری،کلیک و کشیدن،فرانت‌اند،کاربردی،قابل تعامل،جابجایی،حذف،تقسیم
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=مارک‌داون به PDF
home.MarkdownToPDF.desc=تبدیل هر فایل مارک‌داون به PDF home.MarkdownToPDF.desc=تبدیل هر فایل مارک‌داون به PDF
MarkdownToPDF.tags=مارک‌آپ،محتوای وب،تبدیل،تغییر MarkdownToPDF.tags=مارک‌آپ،محتوای وب،تبدیل،تغییر
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=دریافت تمام اطلاعات در مورد PDF home.getPdfInfo.title=دریافت تمام اطلاعات در مورد PDF
home.getPdfInfo.desc=گرفتن هر اطلاعات ممکن در مورد PDF home.getPdfInfo.desc=گرفتن هر اطلاعات ممکن در مورد PDF
@@ -659,11 +646,6 @@ MarkdownToPDF.help=در حال پیشرفت
MarkdownToPDF.credit=از WeasyPrint استفاده می‌کند MarkdownToPDF.credit=از WeasyPrint استفاده می‌کند
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL به PDF URLToPDF.title=URL به PDF

View File

@@ -82,7 +82,7 @@ pages=Pages
loading=Chargement... loading=Chargement...
addToDoc=Ajouter au Document addToDoc=Ajouter au Document
reset=Réinitialiser reset=Réinitialiser
apply=Appliquer apply=Apply
legal.privacy=Politique de Confidentialité legal.privacy=Politique de Confidentialité
legal.terms=Conditions Générales legal.terms=Conditions Générales
@@ -138,7 +138,6 @@ analytics.settings=Vous pouvez modifier les paramètres des analyses dans le fic
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favoris navbar.favorite=Favoris
navbar.recent=New and recently updated
navbar.darkmode=Mode sombre navbar.darkmode=Mode sombre
navbar.language=Langues navbar.language=Langues
navbar.settings=Paramètres navbar.settings=Paramètres
@@ -240,20 +239,20 @@ database.creationDate=Date de Création
database.fileSize=Taille du Fichier database.fileSize=Taille du Fichier
database.deleteBackupFile=Supprimer le fichier de sauvegarde database.deleteBackupFile=Supprimer le fichier de sauvegarde
database.importBackupFile=Importer le fichier de sauvegarde database.importBackupFile=Importer le fichier de sauvegarde
database.createBackupFile=Créer un fichier de sauvegarde database.createBackupFile=Create Backup File
database.downloadBackupFile=Télécharger le fichier de sauvegarde database.downloadBackupFile=Télécharger le fichier de sauvegarde
database.info_1=Lors de l'importation des données, il est crucial de garantir la structure correcte. Si vous n'êtes pas sûr de ce que vous faites, sollicitez un avis et un soutien d'un professionnel. Une erreur dans la structure peut entraîner des dysfonctionnements de l'application, allant jusqu'à l'incapacité totale d'exécuter l'application. database.info_1=Lors de l'importation des données, il est crucial de garantir la structure correcte. Si vous n'êtes pas sûr de ce que vous faites, sollicitez un avis et un soutien d'un professionnel. Une erreur dans la structure peut entraîner des dysfonctionnements de l'application, allant jusqu'à l'incapacité totale d'exécuter l'application.
database.info_2=Le nom du fichier ne fait pas de différence lors de l'upload. Il sera renommé ultérieurement selon le format backup_user_yyyyMMddHHmm.sql, assurant ainsi une convention de nommage cohérente. database.info_2=Le nom du fichier ne fait pas de différence lors de l'upload. Il sera renommé ultérieurement selon le format backup_user_yyyyMMddHHmm.sql, assurant ainsi une convention de nommage cohérente.
database.submit=Importer la sauvegarde database.submit=Importer la sauvegarde
database.importIntoDatabaseSuccessed=Importation dans la base de données réussie database.importIntoDatabaseSuccessed=Importation dans la base de données réussie
database.backupCreated=Sauvegarde de la base de donnée réussie database.backupCreated=Database backup successful
database.fileNotFound=Fichier introuvable database.fileNotFound=File not Found
database.fileNullOrEmpty=Fichier ne peut pas être null ou vide database.fileNullOrEmpty=Fichier ne peut pas être null ou vide
database.failedImportFile=Échec de l'imporation du fichier database.failedImportFile=Failed Import File
database.notSupported=Cette fonctionnalité n'est pas supportée avec votre base de donnée database.notSupported=This function is not available for your database connection.
session.expired=Votre session a expiré. Veuillez recharger la page et réessayer. session.expired=Votre session a expiré. Veuillez recharger la page et réessayer.
session.refreshPage=Rafraichir la page session.refreshPage=Refresh Page
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -266,15 +265,6 @@ home.viewPdf.title=Visionner le PDF
home.viewPdf.desc=Visionner, annoter, ajouter du texte ou des images. home.viewPdf.desc=Visionner, annoter, ajouter du texte ou des images.
viewPdf.tags=visualiser,lire,annoter,texte,image viewPdf.tags=visualiser,lire,annoter,texte,image
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.multiTool.title=Outil multifonction PDF home.multiTool.title=Outil multifonction PDF
home.multiTool.desc=Fusionnez, faites pivoter, réorganisez et supprimez des pages. home.multiTool.desc=Fusionnez, faites pivoter, réorganisez et supprimez des pages.
multiTool.tags=outil multifonction,opération multifonction,interface utilisateur,glisser déposer,front-end,client side,interactif,intransigeant,déplacer,multi tool multiTool.tags=outil multifonction,opération multifonction,interface utilisateur,glisser déposer,front-end,client side,interactif,intransigeant,déplacer,multi tool
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Markdown en PDF
home.MarkdownToPDF.desc=Convertissez n'importe quel fichier Markdown en PDF. home.MarkdownToPDF.desc=Convertissez n'importe quel fichier Markdown en PDF.
MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert
home.PDFToMarkdown.title=PDF to Markdown
home.PDFToMarkdown.desc=Converts any PDF to Markdown
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
home.getPdfInfo.title=Récupérer les informations home.getPdfInfo.title=Récupérer les informations
home.getPdfInfo.desc=Récupérez toutes les informations possibles sur un PDF. home.getPdfInfo.desc=Récupérez toutes les informations possibles sur un PDF.
@@ -489,8 +476,8 @@ home.autoRedact.title=Caviarder automatiquement
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d'un PDF. home.autoRedact.desc=Caviardez automatiquement les informations sensibles d'un PDF.
autoRedact.tags=caviarder,redact,auto autoRedact.tags=caviarder,redact,auto
home.redact.title=Rédaction manuelle home.redact.title=Manual Redaction
home.redact.desc=Rédiger un PDF en fonction de texte sélectionné, formes dessinées et/ou des pages sélectionnées. home.redact.desc=Redacts a PDF based on selected text, drawn shapes and/or selected page(s)
redact.tags=Redact,Hide,black out,black,marker,hidden,manual redact.tags=Redact,Hide,black out,black,marker,hidden,manual
home.tableExtraxt.title=PDF en CSV home.tableExtraxt.title=PDF en CSV
@@ -599,30 +586,30 @@ autoRedact.convertPDFToImageLabel=Convertir un PDF en PDF-Image (utilisé pour s
autoRedact.submitButton=Caviarder autoRedact.submitButton=Caviarder
#redact #redact
redact.title=Rédaction manuelle redact.title=Manual Redaction
redact.header=Rédaction manuelle redact.header=Manual Redaction
redact.submit=Rédiger redact.submit=Redact
redact.textBasedRedaction=Rédaction en fonction de texte redact.textBasedRedaction=Text based Redaction
redact.pageBasedRedaction=Rédaction en fonction de pages redact.pageBasedRedaction=Page-based Redaction
redact.convertPDFToImageLabel=Convertir en PDF-Image (pour supprimer le texte derrière le rectangle) redact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
redact.pageRedactionNumbers.title=Pages redact.pageRedactionNumbers.title=Pages
redact.pageRedactionNumbers.placeholder=(ex: 1,2,8 ou 4,7,12-16 ou 2n-1) redact.pageRedactionNumbers.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
redact.redactionColor.title=Couleur redact.redactionColor.title=Redaction Color
redact.export=Exporter redact.export=Export
redact.upload=Téléverser redact.upload=Upload
redact.boxRedaction=Dessiner le rectangle à rédiger redact.boxRedaction=Box draw redaction
redact.zoom=Zoom redact.zoom=Zoom
redact.zoomIn=Zoom avant redact.zoomIn=Zoom in
redact.zoomOut=Zoom arrière redact.zoomOut=Zoom out
redact.nextPage=Page suivante redact.nextPage=Next Page
redact.previousPage=Page précédente redact.previousPage=Previous Page
redact.toggleSidebar=Toggle Sidebar redact.toggleSidebar=Toggle Sidebar
redact.showThumbnails=Afficher les miniatures redact.showThumbnails=Show Thumbnails
redact.showDocumentOutline=Montrer les contours du document (double-click pour agrandir/réduire tous les éléments) redact.showDocumentOutline=Show Document Outline (double-click to expand/collapse all items)
redact.showAttatchments=Montrer les éléments attachés redact.showAttatchments=Show Attachments
redact.showLayers=Montrer les calques (double-click pour réinitialiser tous les calques à l'état par défaut) redact.showLayers=Show Layers (double-click to reset all layers to the default state)
redact.colourPicker=Sélection de couleur redact.colourPicker=Colour Picker
redact.findCurrentOutlineItem=Trouver l'élément de contour courrant redact.findCurrentOutlineItem=Find current outline item
#showJS #showJS
showJS.title=Afficher le JavaScript showJS.title=Afficher le JavaScript
@@ -659,11 +646,6 @@ MarkdownToPDF.help=(Travail en cours).
MarkdownToPDF.credit=Utilise WeasyPrint. MarkdownToPDF.credit=Utilise WeasyPrint.
#pdf-to-markdown
PDFToMarkdown.title=PDF To Markdown
PDFToMarkdown.header=PDF To Markdown
PDFToMarkdown.submit=Convert
#url-to-pdf #url-to-pdf
URLToPDF.title=URL en PDF URLToPDF.title=URL en PDF
@@ -874,13 +856,13 @@ sign.save=Enregistrer le sceau
sign.personalSigs=Sceaux personnels sign.personalSigs=Sceaux personnels
sign.sharedSigs=Sceaux partagés sign.sharedSigs=Sceaux partagés
sign.noSavedSigs=Aucun sceau enregistré trouvé sign.noSavedSigs=Aucun sceau enregistré trouvé
sign.addToAll=Ajouter à toutes les pages sign.addToAll=Add to all pages
sign.delete=Supprimer sign.delete=Delete
sign.first=Première page sign.first=First page
sign.last=Dernière page sign.last=Last page
sign.next=Page suivante sign.next=Next page
sign.previous=Page précédente sign.previous=Previous page
sign.maintainRatio=Conserver les proportions sign.maintainRatio=Toggle maintain aspect ratio
#repair #repair
@@ -1021,14 +1003,14 @@ multiTool.undo=Undo
multiTool.redo=Redo multiTool.redo=Redo
#decrypt #decrypt
decrypt.passwordPrompt=Ce fichier est protégé par un mot de passe. Veuillez saisir le mot de passe : decrypt.passwordPrompt=This file is password-protected. Please enter the password:
decrypt.cancelled=Operation annulée pour le PDF: {0} decrypt.cancelled=Operation cancelled for PDF: {0}
decrypt.noPassword=Pas de mot de passe fourni pour le PDF chiffré : {0} decrypt.noPassword=No password provided for encrypted PDF: {0}
decrypt.invalidPassword=Veuillez réessayer avec le bon mot de passe decrypt.invalidPassword=Please try again with the correct password.
decrypt.invalidPasswordHeader=Mauvais mot de passe ou chiffrement non supporté pour le PDF : {0} decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
decrypt.unexpectedError=Une erreur est survenue lors de traitement du fichier. Veuillez essayer de nouveau. decrypt.unexpectedError=There was an error processing the file. Please try again.
decrypt.serverError=Erreur du serveur lors du déchiffrement : {0} decrypt.serverError=Server error while decrypting: {0}
decrypt.success=Fichier déchiffré avec succès. decrypt.success=File decrypted successfully.
#multiTool-advert #multiTool-advert
multiTool-advert.message=Cette fonctionnalité est aussi disponible dans la <a href="{0}">page de l'outil multifonction</a>. Allez-y pour une interface page par page améliorée et des fonctionnalités additionnelles ! multiTool-advert.message=Cette fonctionnalité est aussi disponible dans la <a href="{0}">page de l'outil multifonction</a>. Allez-y pour une interface page par page améliorée et des fonctionnalités additionnelles !

View File

@@ -3,9 +3,9 @@
########### ###########
# the direction that the language is written (ltr = left to right, rtl = right to left) # the direction that the language is written (ltr = left to right, rtl = right to left)
language.direction=ltr language.direction=ltr
addPageNumbers.fontSize=Méid an Chló addPageNumbers.fontSize=Font Size
addPageNumbers.fontName=Ainm Cló addPageNumbers.fontName=Font Name
pdfPrompt=Roghnaigh PDF(anna) pdfPrompt=Roghnaigh PDF(s)
multiPdfPrompt=Roghnaigh PDFs (2+) multiPdfPrompt=Roghnaigh PDFs (2+)
multiPdfDropPrompt=Roghnaigh (nó tarraing & scaoil) gach PDF atá uait multiPdfDropPrompt=Roghnaigh (nó tarraing & scaoil) gach PDF atá uait
imgPrompt=Roghnaigh Íomhá(í) imgPrompt=Roghnaigh Íomhá(í)
@@ -56,12 +56,12 @@ userNotFoundMessage=Úsáideoir gan aimsiú.
incorrectPasswordMessage=Tá an pasfhocal reatha mícheart. incorrectPasswordMessage=Tá an pasfhocal reatha mícheart.
usernameExistsMessage=Tá Ainm Úsáideora Nua ann cheana féin. usernameExistsMessage=Tá Ainm Úsáideora Nua ann cheana féin.
invalidUsernameMessage=Ainm úsáideora neamhbhailí, ní féidir ach litreacha, uimhreacha agus na carachtair speisialta seo a leanas @._+- a bheith san ainm úsáideora nó ní mór gur seoladh ríomhphoist bailí é. invalidUsernameMessage=Ainm úsáideora neamhbhailí, ní féidir ach litreacha, uimhreacha agus na carachtair speisialta seo a leanas @._+- a bheith san ainm úsáideora nó ní mór gur seoladh ríomhphoist bailí é.
invalidPasswordMessage=Níor cheart go mbeadh an pasfhocal folamh agus níor cheart go mbeadh spásanna ag an tús nó ag an deireadh. invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
confirmPasswordErrorMessage=Ní mór Pasfhocal Nua agus Deimhnigh Pasfhocal Nua a bheith ag teacht leis. confirmPasswordErrorMessage=Ní mór Pasfhocal Nua agus Deimhnigh Pasfhocal Nua a bheith ag teacht leis.
deleteCurrentUserMessage=Ní féidir an t-úsáideoir atá logáilte isteach faoi láthair a scriosadh. deleteCurrentUserMessage=Ní féidir an t-úsáideoir atá logáilte isteach faoi láthair a scriosadh.
deleteUsernameExistsMessage=Níl an t-ainm úsáideora ann agus ní féidir é a scriosadh. deleteUsernameExistsMessage=Níl an t-ainm úsáideora ann agus ní féidir é a scriosadh.
downgradeCurrentUserMessage=Ní féidir ról an úsáideora reatha a íosghrádú downgradeCurrentUserMessage=Ní féidir ról an úsáideora reatha a íosghrádú
disabledCurrentUserMessage=Ní féidir an t-úsáideoir reatha a dhíchumasú disabledCurrentUserMessage=The current user cannot be disabled
downgradeCurrentUserLongMessage=Ní féidir ról an úsáideora reatha a íosghrádú. Mar sin, ní thaispeánfar an t-úsáideoir reatha. downgradeCurrentUserLongMessage=Ní féidir ról an úsáideora reatha a íosghrádú. Mar sin, ní thaispeánfar an t-úsáideoir reatha.
userAlreadyExistsOAuthMessage=Tá an t-úsáideoir ann cheana mar úsáideoir OAuth2. userAlreadyExistsOAuthMessage=Tá an t-úsáideoir ann cheana mar úsáideoir OAuth2.
userAlreadyExistsWebMessage=Tá an t-úsáideoir ann cheana féin mar úsáideoir gréasáin. userAlreadyExistsWebMessage=Tá an t-úsáideoir ann cheana féin mar úsáideoir gréasáin.
@@ -77,17 +77,17 @@ color=Dath
sponsor=Urraitheoir sponsor=Urraitheoir
info=Eolas info=Eolas
pro=Pro pro=Pro
page=Leathanach page=Page
pages=Leathanaigh pages=Pages
loading=Á lódáil... loading=Loading...
addToDoc=Cuir le Doiciméad addToDoc=Add to Document
reset=Athshocraigh reset=Reset
apply=Cuir i bhFeidhm apply=Apply
legal.privacy=Polasaí Príobháideachta legal.privacy=Privacy Policy
legal.terms=Téarmaí agus Coinníollacha legal.terms=Terms and Conditions
legal.accessibility=Inrochtaineacht legal.accessibility=Accessibility
legal.cookie=Polasaí Fianán legal.cookie=Cookie Policy
legal.impressum=Impressum legal.impressum=Impressum
############### ###############
@@ -118,40 +118,39 @@ pipelineOptions.validateButton=Bailíochtaigh
######################## ########################
# ENTERPRISE EDITION # # ENTERPRISE EDITION #
######################## ########################
enterpriseEdition.button=Uasghrádú go Pro enterpriseEdition.button=Upgrade to Pro
enterpriseEdition.warning=Níl an ghné seo ar fáil ach d'úsáideoirí Pro. enterpriseEdition.warning=This feature is only available to Pro users.
enterpriseEdition.yamlAdvert=Tacaíonn Stirling PDF Pro le comhaid cumraíochta YAML agus gnéithe SSO eile. enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
enterpriseEdition.ssoAdvert=Tá tuilleadh gnéithe bainistíochta úsáideoirí á lorg? Seiceáil Stirling PDF Pro enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
################# #################
# Analytics # # Analytics #
################# #################
analytics.title=An bhfuil fonn ort PDF Stirling a fheabhsú? analytics.title=Do you want make Stirling PDF better?
analytics.paragraph1=Tá rogha an diúltaithe ag PDF Stirling chun cabhrú linn an táirge a fheabhsú. Ní rianaimid aon fhaisnéis phearsanta nó ábhar comhaid. analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
analytics.paragraph2=Smaoinigh le do thoil ar anailísíocht a chumasú chun cabhrú le Stirling-PDF fás agus chun ligean dúinn ár n-úsáideoirí a thuiscint níos fearr. analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
analytics.enable=Cumasaigh anailísíocht analytics.enable=Enable analytics
analytics.disable=Díchumasaigh anailísíocht analytics.disable=Disable analytics
analytics.settings=Is féidir leat na socruithe don anailísíocht a athrú sa chomhad config/settings.yml analytics.settings=You can change the settings for analytics in the config/settings.yml file
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Ceanáin navbar.favorite=Ceanáin
navbar.recent=New and recently updated
navbar.darkmode=Mód Dorcha navbar.darkmode=Mód Dorcha
navbar.language=Teangacha navbar.language=Teangacha
navbar.settings=Socruithe navbar.settings=Socruithe
navbar.allTools=Uirlisí navbar.allTools=Uirlisí
navbar.multiTool=Uirlisí Il navbar.multiTool=Uirlisí Il
navbar.search=Cuardach navbar.search=Search
navbar.sections.organize=Eagraigh navbar.sections.organize=Eagraigh
navbar.sections.convertTo=Tiontaigh go PDF navbar.sections.convertTo=Tiontaigh go PDF
navbar.sections.convertFrom=Tiontaigh ó PDF navbar.sections.convertFrom=Tiontaigh ó PDF
navbar.sections.security=Comhartha & Slándáil navbar.sections.security=Comhartha & Slándáil
navbar.sections.advance=Casta navbar.sections.advance=Casta
navbar.sections.edit=Féach ar & Cuir in Eagar navbar.sections.edit=Féach ar & Cuir in Eagar
navbar.sections.popular=Coitianta navbar.sections.popular=Popular
############# #############
# SETTINGS # # SETTINGS #
@@ -210,7 +209,7 @@ adminUserSettings.user=Úsáideoir
adminUserSettings.addUser=Cuir Úsáideoir Nua leis adminUserSettings.addUser=Cuir Úsáideoir Nua leis
adminUserSettings.deleteUser=Scrios Úsáideoir adminUserSettings.deleteUser=Scrios Úsáideoir
adminUserSettings.confirmDeleteUser=Ar cheart an t-úsáideoir a scriosadh? adminUserSettings.confirmDeleteUser=Ar cheart an t-úsáideoir a scriosadh?
adminUserSettings.confirmChangeUserStatus=Ar cheart an t-úsáideoir a dhíchumasú/a chumasú? adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
adminUserSettings.usernameInfo=Ní féidir ach litreacha, uimhreacha agus na carachtair speisialta seo a leanas @._+- a bheith san ainm úsáideora nó ní mór gur seoladh ríomhphoist bailí é. adminUserSettings.usernameInfo=Ní féidir ach litreacha, uimhreacha agus na carachtair speisialta seo a leanas @._+- a bheith san ainm úsáideora nó ní mór gur seoladh ríomhphoist bailí é.
adminUserSettings.roles=Róil adminUserSettings.roles=Róil
adminUserSettings.role=Ról adminUserSettings.role=Ról
@@ -224,36 +223,36 @@ adminUserSettings.forceChange=Cuir iallach ar an úsáideoir pasfhocal a athrú
adminUserSettings.submit=Sábháil Úsáideoir adminUserSettings.submit=Sábháil Úsáideoir
adminUserSettings.changeUserRole=Athraigh Ról an Úsáideora adminUserSettings.changeUserRole=Athraigh Ról an Úsáideora
adminUserSettings.authenticated=Fíordheimhnithe adminUserSettings.authenticated=Fíordheimhnithe
adminUserSettings.editOwnProfil=Cuir a phróifíl féin in eagar adminUserSettings.editOwnProfil=Edit own profile
adminUserSettings.enabledUser=úsáideoir cumasaithe adminUserSettings.enabledUser=enabled user
adminUserSettings.disabledUser=úsáideoir faoi mhíchumas adminUserSettings.disabledUser=disabled user
adminUserSettings.activeUsers=Úsáideoirí Gníomhacha: adminUserSettings.activeUsers=Active Users:
adminUserSettings.disabledUsers=Úsáideoirí faoi mhíchumas: adminUserSettings.disabledUsers=Disabled Users:
adminUserSettings.totalUsers=Úsáideoirí Iomlán: adminUserSettings.totalUsers=Total Users:
adminUserSettings.lastRequest=Iarratas Deiridh adminUserSettings.lastRequest=Last Request
database.title=Iompórtáil/Easpórtáil Bunachar Sonraí database.title=Iompórtáil / Easpórtáil Bunachar Sonraí
database.header=Iompórtáil/Easpórtáil Bunachar Sonraí database.header=Iompórtáil / Easpórtáil Bunachar Sonraí
database.fileName=Ainm comhaid database.fileName=Ainm comhaid
database.creationDate=Dáta Cruthaithe database.creationDate=Dáta Cruthaithe
database.fileSize=Méid an Chomhaid database.fileSize=Méid an Chomhaid
database.deleteBackupFile=Scrios Comhad Cúltaca database.deleteBackupFile=Scrios Comhad Cúltaca
database.importBackupFile=Iompórtáil Comhad Cúltaca database.importBackupFile=Iompórtáil Comhad Cúltaca
database.createBackupFile=Cruthaigh Comhad Cúltaca database.createBackupFile=Create Backup File
database.downloadBackupFile=Íoslódáil an comhad cúltaca database.downloadBackupFile=Íoslódáil an comhad cúltaca
database.info_1=Agus sonraí á n-allmhairiú, tá sé ríthábhachtach an struchtúr ceart a chinntiú. Mura bhfuil tú cinnte faoina bhfuil ar siúl agat, iarr comhairle agus tacaíocht ó ghairmí. Féadfaidh earráid sa struchtúr a bheith ina chúis le mífheidhmeanna iarratais, suas go dtí agus lena n-áirítear an neamhábaltacht iomlán an t-iarratas a rith. database.info_1=Agus sonraí á n-allmhairiú, tá sé ríthábhachtach an struchtúr ceart a chinntiú. Mura bhfuil tú cinnte faoina bhfuil ar siúl agat, iarr comhairle agus tacaíocht ó ghairmí. Féadfaidh earráid sa struchtúr a bheith ina chúis le mífheidhmeanna iarratais, suas go dtí agus lena n-áirítear an neamhábaltacht iomlán an t-iarratas a rith.
database.info_2=Ní hionann ainm an chomhaid agus é á uaslódáil. Déanfar é a athainmniú ina dhiaidh sin chun an fhormáid backup_user_yyyyMMddHHmm.sql a leanúint, ag cinntiú go bhfuil coinbhinsiún ainmniúcháin comhsheasmhach ann. database.info_2=Ní hionann ainm an chomhaid agus é á uaslódáil. Déanfar é a athainmniú ina dhiaidh sin chun an fhormáid backup_user_yyyyMMddHHmm.sql a leanúint, ag cinntiú go bhfuil coinbhinsiún ainmniúcháin comhsheasmhach ann.
database.submit=Iompórtáil Cúltaca database.submit=Iompórtáil Cúltaca
database.importIntoDatabaseSuccessed=D'éirigh leis an allmhairiú isteach sa bhunachar sonraí database.importIntoDatabaseSuccessed=D'éirigh leis an allmhairiú isteach sa bhunachar sonraí
database.backupCreated=D'éirigh le cúltaca bunachar sonraí database.backupCreated=Database backup successful
database.fileNotFound=Comhad gan aimsiú database.fileNotFound=Comhad gan aimsiú
database.fileNullOrEmpty=Níor cheart go mbeadh an comhad ar neamhní nó folamh database.fileNullOrEmpty=Níor cheart go mbeadh an comhad ar neamhní nó folamh
database.failedImportFile=Theip ar iompórtáil an chomhaid database.failedImportFile=Theip ar iompórtáil an chomhaid
database.notSupported=Níl an fheidhm seo ar fáil do nasc bunachar sonraí. database.notSupported=This function is not available for your database connection.
session.expired=Tá do sheisiún imithe in éag. Athnuaigh an leathanach agus bain triail eile as. session.expired=Your session has expired. Please refresh the page and try again.
session.refreshPage=Athnuaigh an Leathanach session.refreshPage=Refresh Page
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -266,15 +265,6 @@ home.viewPdf.title=Féach PDF
home.viewPdf.desc=Féach ar, nótáil, cuir téacs nó íomhánna leis home.viewPdf.desc=Féach ar, nótáil, cuir téacs nó íomhánna leis
viewPdf.tags=amharc, léamh, anótáil, téacs, íomhá viewPdf.tags=amharc, léamh, anótáil, téacs, íomhá
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.multiTool.title=Il-uirlis PDF home.multiTool.title=Il-uirlis PDF
home.multiTool.desc=Cumaisc, Rothlaigh, Atheagraigh, agus Bain leathanaigh home.multiTool.desc=Cumaisc, Rothlaigh, Atheagraigh, agus Bain leathanaigh
multiTool.tags=Il-Uirlis, Iloibríocht, Chomhéadain, cliceáil tarraing, ceann tosaigh, taobh an chliaint, idirghníomhach, intractable, bog multiTool.tags=Il-Uirlis, Iloibríocht, Chomhéadain, cliceáil tarraing, ceann tosaigh, taobh an chliaint, idirghníomhach, intractable, bog
@@ -288,7 +278,7 @@ home.split.desc=Scoilt comhaid PDF isteach i ndoiciméid iolracha
split.tags=Oibríochtaí leathanach, roinnt, Leathanach Il, gearrtha, taobh freastalaí split.tags=Oibríochtaí leathanach, roinnt, Leathanach Il, gearrtha, taobh freastalaí
home.rotate.title=Rothlaigh home.rotate.title=Rothlaigh
home.rotate.desc=Rothlaigh do PDFanna go héasca. home.rotate.desc=Rothlaigh do PDFs go héasca.
rotate.tags=taobh freastalaí rotate.tags=taobh freastalaí
@@ -337,13 +327,13 @@ compressPdfs.tags=squish, beag, beag bídeach
home.changeMetadata.title=Athraigh Meiteashonraí home.changeMetadata.title=Athraigh Meiteashonraí
home.changeMetadata.desc=Athraigh/Bain/Cuir meiteashonraí ó dhoiciméad PDF home.changeMetadata.desc=Athraigh/Bain/Cuir meiteashonraí ó dhoiciméad PDF
changeMetadata.tags=Teideal,údar, dáta, cruthú, am, foilsitheoir, léiritheoir, staitisticí changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Comhad a thiontú go PDF home.fileToPDF.title=Comhad a thiontú go PDF
home.fileToPDF.desc=Tiontaigh beagnach aon chomhad go PDF (DOCX, PNG, XLS, PPT, TXT agus go leor eile) home.fileToPDF.desc=Tiontaigh beagnach aon chomhad go PDF (DOCX, PNG, XLS, PPT, TXT agus go leor eile)
fileToPDF.tags=claochlú, formáid, doiciméad, pictiúr, sleamhnán, téacs, comhshó, oifig, docs, focal, excel, powerpoint fileToPDF.tags=claochlú, formáid, doiciméad, pictiúr, sleamhnán, téacs, comhshó, oifig, docs, focal, excel, powerpoint
home.ocr.title=OCR / Scananna glanta home.ocr.title=Scananna OCR / Glanta
home.ocr.desc=Scanann glantachán agus aimsíonn sé téacs ó íomhánna laistigh de PDF agus cuireann sé isteach arís é mar théacs. home.ocr.desc=Scanann glantachán agus aimsíonn sé téacs ó íomhánna laistigh de PDF agus cuireann sé isteach arís é mar théacs.
ocr.tags=aithint, téacs, íomhá, scanadh, léamh, a aithint, a bhrath, in eagar ocr.tags=aithint, téacs, íomhá, scanadh, léamh, a aithint, a bhrath, in eagar
@@ -449,7 +439,7 @@ home.sanitizePdf.title=Sláintíocht
home.sanitizePdf.desc=Bain scripteanna agus gnéithe eile ó chomhaid PDF home.sanitizePdf.desc=Bain scripteanna agus gnéithe eile ó chomhaid PDF
sanitizePdf.tags=glan, slán, sábháilte, bain bagairtí sanitizePdf.tags=glan, slán, sábháilte, bain bagairtí
home.URLToPDF.title=URL/Láithreán Gréasáin go PDF home.URLToPDF.title=URL / Láithreán Gréasáin go PDF
home.URLToPDF.desc=Tiontaíonn aon http(s) URL go PDF home.URLToPDF.desc=Tiontaíonn aon http(s) URL go PDF
URLToPDF.tags=gréasán a ghabháil, a shábháil-leathanach, gréasán-go-doc, cartlann URLToPDF.tags=gréasán a ghabháil, a shábháil-leathanach, gréasán-go-doc, cartlann
@@ -462,9 +452,6 @@ home.MarkdownToPDF.title=Marcáil síos go PDF
home.MarkdownToPDF.desc=Tiontaíonn aon chomhad Markdown go PDF home.MarkdownToPDF.desc=Tiontaíonn aon chomhad Markdown go PDF
MarkdownToPDF.tags=marcáil, ábhar gréasáin, claochlú, tiontú MarkdownToPDF.tags=marcáil, ábhar gréasáin, claochlú, tiontú
home.PDFToMarkdown.title=PDF chuig Markdown
home.PDFToMarkdown.desc=Tiontaíonn PDF ar bith go Markdown
PDFToMarkdown.tags=marcáil, ábhar Gréasáin, claochlú, tiontú, md
home.getPdfInfo.title=Faigh GACH Eolas ar PDF home.getPdfInfo.title=Faigh GACH Eolas ar PDF
home.getPdfInfo.desc=Grab aon fhaisnéis agus is féidir ar PDFs home.getPdfInfo.desc=Grab aon fhaisnéis agus is féidir ar PDFs
@@ -489,9 +476,9 @@ home.autoRedact.title=Auto Redact
home.autoRedact.desc=Auto Redacts (Blacks out) téacs i PDF bunaithe ar an téacs ionchuir home.autoRedact.desc=Auto Redacts (Blacks out) téacs i PDF bunaithe ar an téacs ionchuir
autoRedact.tags=Dearg, Folaigh, dubh amach, dubh, marcóir, i bhfolach autoRedact.tags=Dearg, Folaigh, dubh amach, dubh, marcóir, i bhfolach
home.redact.title=Athchóiriú de Láimh home.redact.title=Manual Redaction
home.redact.desc=Réiteann sé PDF bunaithe ar théacs roghnaithe, cruthanna tarraingthe agus/nó leathanaigh roghnaithe home.redact.desc=Redacts a PDF based on selected text, drawn shapes and/or selected page(s)
redact.tags=Réiteach, Folaigh, dubh amach, dubh, marcóir, i bhfolach, lámhleabhar redact.tags=Redact,Hide,black out,black,marker,hidden,manual
home.tableExtraxt.title=Ó CSV go PDF home.tableExtraxt.title=Ó CSV go PDF
home.tableExtraxt.desc=Sleachta Táblaí ó PDF agus é a thiontú go CSV home.tableExtraxt.desc=Sleachta Táblaí ó PDF agus é a thiontú go CSV
@@ -524,37 +511,37 @@ home.BookToPDF.title=Leabhar a thiontú go PDF
home.BookToPDF.desc=Tiontaíonn sé formáidí Leabhair/Comics go PDF ag baint úsáide as calibre home.BookToPDF.desc=Tiontaíonn sé formáidí Leabhair/Comics go PDF ag baint úsáide as calibre
BookToPDF.tags=Leabhar, Comic, Calibre, Tiontaigh, manga, amazon, kindle, epub, mobi, azw3, docx, rtf, txt, html, lit, fb2, pdb, lrf BookToPDF.tags=Leabhar, Comic, Calibre, Tiontaigh, manga, amazon, kindle, epub, mobi, azw3, docx, rtf, txt, html, lit, fb2, pdb, lrf
home.removeImagePdf.title=Bain íomhá home.removeImagePdf.title=Remove image
home.removeImagePdf.desc=Bain íomhá de PDF chun méid comhaid a laghdú home.removeImagePdf.desc=Remove image from PDF to reduce file size
removeImagePdf.tags=Bain Íomhá, Oibríochtaí Leathanaigh, Cúl, taobh an fhreastalaí removeImagePdf.tags=Remove Image,Page operations,Back end,server side
home.splitPdfByChapters.title=Scoil PDF ar Chaibidlí home.splitPdfByChapters.title=Split PDF by Chapters
home.splitPdfByChapters.desc=Scoilt PDF ina chomhaid iolracha bunaithe ar a struchtúr caibidle. home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
splitPdfByChapters.tags=scoilt, caibidlí, leabharmharcanna, eagraigh splitPdfByChapters.tags=split,chapters,bookmarks,organize
home.validateSignature.title=Bailíochtaigh Síniú PDF home.validateSignature.title=Validate PDF Signature
home.validateSignature.desc=Fíoraigh sínithe digiteacha agus teastais i gcáipéisí PDF home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
validateSignature.tags=síniú, fíoraigh, deimhnigh, pdf, teastas, síniú digiteach, Síniú Bailíochtaigh, Bailíochtaigh teastas validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
#replace-invert-color #replace-invert-color
replace-color.title=Athchuir-Inbhéartaigh-Dath replace-color.title=Replace-Invert-Color
replace-color.header=Athchuir-Inbhéartaigh Dath PDF replace-color.header=Replace-Invert Color PDF
home.replaceColorPdf.title=Athchuir agus Inbhéartaigh Dath home.replaceColorPdf.title=Replace and Invert Color
home.replaceColorPdf.desc=Athchuir dath an téacs agus an chúlra i bhformáid PDF agus inbhéartaigh dath iomlán pdf chun méid comhaid a laghdú home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
replaceColorPdf.tags=Athchuir Dath,Oibríochtaí Leathanaigh,Cúl,taobh an fhreastalaí replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
replace-color.selectText.1=Athchuir nó Inbhéartaigh Roghanna datha replace-color.selectText.1=Replace or Invert color Options
replace-color.selectText.2=Réamhshocrú(Réamhshocrú dathanna ardchodarsnachta) replace-color.selectText.2=Default(Default high contrast colors)
replace-color.selectText.3=Saincheaptha(dathanna saincheaptha) replace-color.selectText.3=Custom(Customized colors)
replace-color.selectText.4=Iompaithe Lán(Inbhéartaigh gach dath) replace-color.selectText.4=Full-Invert(Invert all colors)
replace-color.selectText.5=Roghanna dathanna ardchodarsnachta replace-color.selectText.5=High contrast color options
replace-color.selectText.6=téacs bán ar chúlra dubh replace-color.selectText.6=white text on black background
replace-color.selectText.7=Téacs dubh ar chúlra bán replace-color.selectText.7=Black text on white background
replace-color.selectText.8=acs buí ar chúlra dubh replace-color.selectText.8=Yellow text on black background
replace-color.selectText.9=Téacs glas ar chúlra dubh replace-color.selectText.9=Green text on black background
replace-color.selectText.10=Roghnaigh Dath an téacs replace-color.selectText.10=Choose text Color
replace-color.selectText.11=Roghnaigh Dath an Chúlra replace-color.selectText.11=Choose background Color
replace-color.submit=Ionadaigh replace-color.submit=Replace
@@ -573,18 +560,18 @@ login.locked=Tá do chuntas glasáilte.
login.signinTitle=Sínigh isteach le do thoil login.signinTitle=Sínigh isteach le do thoil
login.ssoSignIn=Logáil isteach trí Chlárú Aonair login.ssoSignIn=Logáil isteach trí Chlárú Aonair
login.oauth2AutoCreateDisabled=OAUTH2 Uath-Chruthaigh Úsáideoir faoi Mhíchumas login.oauth2AutoCreateDisabled=OAUTH2 Uath-Chruthaigh Úsáideoir faoi Mhíchumas
login.oauth2AdminBlockedUser=Tá bac faoi láthair ar chlárú nó logáil isteach úsáideoirí neamhchláraithe. Déan teagmháil leis an riarthóir le do thoil. login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Níor aimsíodh iarratas údaraithe login.oauth2RequestNotFound=Níor aimsíodh iarratas údaraithe
login.oauth2InvalidUserInfoResponse=Freagra Neamhbhailí Faisnéise Úsáideora login.oauth2InvalidUserInfoResponse=Freagra Neamhbhailí Faisnéise Úsáideora
login.oauth2invalidRequest=Iarratas Neamhbhailí login.oauth2invalidRequest=Iarratas Neamhbhailí
login.oauth2AccessDenied=Rochtain Diúltaithe login.oauth2AccessDenied=Rochtain Diúltaithe
login.oauth2InvalidTokenResponse=Freagra Comhartha Neamhbhailí login.oauth2InvalidTokenResponse=Freagra Comhartha Neamhbhailí
login.oauth2InvalidIdToken=Comhartha Aitheantais Neamhbhailí login.oauth2InvalidIdToken=Comhartha Aitheantais Neamhbhailí
login.relyingPartyRegistrationNotFound=Níor aimsíodh clárú páirtí spleách login.relyingPartyRegistrationNotFound=No relying party registration found
login.userIsDisabled=Úsáideoir díghníomhachtaithe, tá bac ar logáil isteach leis an ainm úsáideora seo faoi láthair. Déan teagmháil leis an riarthóir le do thoil. login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
login.alreadyLoggedIn=Tá tú logáilte isteach cheana login.alreadyLoggedIn=You are already logged in to
login.alreadyLoggedIn2=gléasanna. Logáil amach as na gléasanna agus bain triail eile as. login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
login.toManySessions=Tá an iomarca seisiún gníomhach agat login.toManySessions=You have too many active sessions
#auto-redact #auto-redact
autoRedact.title=Auto Redact autoRedact.title=Auto Redact
@@ -599,35 +586,35 @@ autoRedact.convertPDFToImageLabel=Tiontaigh PDF go PDF-Image (Úsáidte chun té
autoRedact.submitButton=Cuir isteach autoRedact.submitButton=Cuir isteach
#redact #redact
redact.title=Athchóiriú de Láimh redact.title=Manual Redaction
redact.header=Athchóiriú de Láimh redact.header=Manual Redaction
redact.submit=Réiteach redact.submit=Redact
redact.textBasedRedaction=Athrú Téacsbhunaithe redact.textBasedRedaction=Text based Redaction
redact.pageBasedRedaction=Athrú bunaithe ar Leathanaigh redact.pageBasedRedaction=Page-based Redaction
redact.convertPDFToImageLabel=Tiontaigh PDF go PDF-Image (Úsáidte chun téacs a bhaint taobh thiar den bhosca) redact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
redact.pageRedactionNumbers.title=Leathanaigh redact.pageRedactionNumbers.title=Pages
redact.pageRedactionNumbers.placeholder=(m.sh. 1,2,8 4,7,12-16 2n-1) redact.pageRedactionNumbers.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
redact.redactionColor.title=Dath Athbhreithnithe redact.redactionColor.title=Redaction Color
redact.export=Easpórtáil redact.export=Export
redact.upload=Uaslódáil redact.upload=Upload
redact.boxRedaction=dearadh tarraingthe an bhosca redact.boxRedaction=Box draw redaction
redact.zoom=Súmáil redact.zoom=Zoom
redact.zoomIn=Súmáil isteach redact.zoomIn=Zoom in
redact.zoomOut=Súmáil amach redact.zoomOut=Zoom out
redact.nextPage=An Chéad Leathanach Eile redact.nextPage=Next Page
redact.previousPage=Leathanach Roimhe Seo redact.previousPage=Previous Page
redact.toggleSidebar=Scoránaigh an Barra Taoibh redact.toggleSidebar=Toggle Sidebar
redact.showThumbnails=Taispeáin Mionsamhlacha redact.showThumbnails=Show Thumbnails
redact.showDocumentOutline=Taispeáin Imlíne an Doiciméid (cliceáil faoi dhó chun gach mír a leathnú/laghdú) redact.showDocumentOutline=Show Document Outline (double-click to expand/collapse all items)
redact.showAttatchments=Taispeáin Ceangaltáin redact.showAttatchments=Show Attachments
redact.showLayers=Taispeáin Sraitheanna (cliceáil faoi dhó chun gach sraith a athshocrú go dtí an staid réamhshocraithe) redact.showLayers=Show Layers (double-click to reset all layers to the default state)
redact.colourPicker=Roghnóir Dathanna redact.colourPicker=Colour Picker
redact.findCurrentOutlineItem=Faigh imlíne reatha redact.findCurrentOutlineItem=Find current outline item
#showJS #showJS
showJS.title=Taispeáin Javascript showJS.title=Taispeáin Javascript
showJS.header=Taispeáin Javascript showJS.header=Taispeáin Javascript
showJS.downloadJS=Íosluchtaigh Javascript showJS.downloadJS=Íosluchtaigh leabhar javascript
showJS.submit=Taispeáin showJS.submit=Taispeáin
@@ -659,11 +646,6 @@ MarkdownToPDF.help=Obair idir lámha
MarkdownToPDF.credit=Úsáideann WeasyPrint MarkdownToPDF.credit=Úsáideann WeasyPrint
#pdf-to-markdown
PDFToMarkdown.title=PDF Chuig Marcáil
PDFToMarkdown.header=PDF Go Marcáil
PDFToMarkdown.submit=Tiontaigh
#url-to-pdf #url-to-pdf
URLToPDF.title=URL go PDF URLToPDF.title=URL go PDF
@@ -789,7 +771,7 @@ pageLayout.submit=Cuir isteach
scalePages.title=Coigeartaigh scála an leathanaigh scalePages.title=Coigeartaigh scála an leathanaigh
scalePages.header=Coigeartaigh scála an leathanaigh scalePages.header=Coigeartaigh scála an leathanaigh
scalePages.pageSize=Méid leathanach den doiciméad. scalePages.pageSize=Méid leathanach den doiciméad.
scalePages.keepPageSize=Méid Bunaidh scalePages.keepPageSize=Original Size
scalePages.scaleFactor=Leibhéal súmáil (barr) de leathanach. scalePages.scaleFactor=Leibhéal súmáil (barr) de leathanach.
scalePages.submit=Cuir isteach scalePages.submit=Cuir isteach
@@ -809,7 +791,7 @@ certSign.showSig=Taispeáin Síniú
certSign.reason=Cúis certSign.reason=Cúis
certSign.location=Suíomh certSign.location=Suíomh
certSign.name=Ainm certSign.name=Ainm
certSign.showLogo=Taispeáin Lógó certSign.showLogo=Show Logo
certSign.submit=Sínigh PDF certSign.submit=Sínigh PDF
@@ -844,9 +826,9 @@ compare.highlightColor.2=Dath Aibhsithe 2:
compare.document.1=Doiciméad 1 compare.document.1=Doiciméad 1
compare.document.2=Doiciméad 2 compare.document.2=Doiciméad 2
compare.submit=Déan comparáid idir compare.submit=Déan comparáid idir
compare.complex.message=Is comhaid mhóra ceann amháin nó an dá cheann de na doiciméid a soláthraíodh, d'fhéadfaí cruinneas na comparáide a laghdú compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
compare.large.file.message=Tá ceann amháin de na doiciméid nó an dá cheann rómhór le próiseáil compare.large.file.message=One or Both of the provided documents are too large to process
compare.no.text.message=Níl aon ábhar téacs i gceann amháin nó sa dá cheann de na PDF roghnaithe. Roghnaigh PDF le do thoil le téacs chun comparáid a dhéanamh. compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
#BookToPDF #BookToPDF
BookToPDF.title=Leabhair agus comics a PDF BookToPDF.title=Leabhair agus comics a PDF
@@ -869,18 +851,18 @@ sign.draw=Tarraing Síniú
sign.text=Ionchur Téacs sign.text=Ionchur Téacs
sign.clear=Glan sign.clear=Glan
sign.add=Cuir sign.add=Cuir
sign.saved=Sínithe Sínithe sign.saved=Saved Signatures
sign.save=Sábháil an Síniú sign.save=Save Signature
sign.personalSigs=Sínithe Pearsanta sign.personalSigs=Personal Signatures
sign.sharedSigs=Sínithe Roinnte sign.sharedSigs=Shared Signatures
sign.noSavedSigs=Níor aimsíodh aon síniú sábháilte sign.noSavedSigs=No saved signatures found
sign.addToAll=Cuir le gach leathanach sign.addToAll=Add to all pages
sign.delete=Scrios sign.delete=Delete
sign.first=An chéad leathanach sign.first=First page
sign.last=An leathanach deiridh sign.last=Last page
sign.next=An chéad leathanach eile sign.next=Next page
sign.previous=Leathanach roimhe seo sign.previous=Previous page
sign.maintainRatio=Scoránaigh, coinnigh an cóimheas gné sign.maintainRatio=Toggle maintain aspect ratio
#repair #repair
@@ -907,7 +889,7 @@ ScannerImageSplit.selectText.7=Íos-Limistéar Comhrianta:
ScannerImageSplit.selectText.8=Socraíonn sé an tairseach íosta achar comhrianta le haghaidh grianghraf ScannerImageSplit.selectText.8=Socraíonn sé an tairseach íosta achar comhrianta le haghaidh grianghraf
ScannerImageSplit.selectText.9=Méid na Teorann: ScannerImageSplit.selectText.9=Méid na Teorann:
ScannerImageSplit.selectText.10=Socraíonn sé méid na teorann a chuirtear leis agus a bhaintear chun teorainneacha bán a chosc san aschur (réamhshocraithe: 1). ScannerImageSplit.selectText.10=Socraíonn sé méid na teorann a chuirtear leis agus a bhaintear chun teorainneacha bán a chosc san aschur (réamhshocraithe: 1).
ScannerImageSplit.info=Níl Python suiteáilte. Tá sé ag teastáil a rith. ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR #OCR
@@ -934,7 +916,7 @@ ocr.submit=Próiseáil PDF le OCR
extractImages.title=Sliocht Íomhánna extractImages.title=Sliocht Íomhánna
extractImages.header=Sliocht Íomhánna extractImages.header=Sliocht Íomhánna
extractImages.selectText=Roghnaigh formáid íomhá chun íomhánna bainte a thiontú go extractImages.selectText=Roghnaigh formáid íomhá chun íomhánna bainte a thiontú go
extractImages.allowDuplicates=Sábháil íomhánna dúblacha extractImages.allowDuplicates=Save duplicate images
extractImages.submit=Sliocht extractImages.submit=Sliocht
@@ -952,7 +934,7 @@ compress.title=Comhbhrúigh
compress.header=Comhbhrúigh PDF compress.header=Comhbhrúigh PDF
compress.credit=Úsáideann an tseirbhís seo qpdf le haghaidh Comhbhrú/Optimization PDF. compress.credit=Úsáideann an tseirbhís seo qpdf le haghaidh Comhbhrú/Optimization PDF.
compress.selectText.1=Mód Láimhe - Ó 1 go 5 compress.selectText.1=Mód Láimhe - Ó 1 go 5
compress.selectText.1.1=I leibhéil optamaithe 6 go 9, chomh maith le comhbhrú ginearálta PDF, déantar réiteach íomhá a laghdú de réir scála chun méid comhaid a laghdú tuilleadh. Mar thoradh ar leibhéil níos airde tá comhbhrú íomhá níos láidre (suas le 50% den mhéid bunaidh), ag baint amach laghdú méide níos mó ach le caillteanas cáilíochta féideartha in íomhánna. compress.selectText.1.1=In optimization levels 6 to 9, in addition to general PDF compression, image resolution is scaled down to further reduce file size. Higher levels result in stronger image compression (up to 50% of the original size), achieving greater size reduction but with potential quality loss in images.
compress.selectText.2=Leibhéal optamaithe: compress.selectText.2=Leibhéal optamaithe:
compress.selectText.3=4 (Uafásach le haghaidh íomhánna téacs) compress.selectText.3=4 (Uafásach le haghaidh íomhánna téacs)
compress.selectText.4=Mód uathoibríoch - Coigeartaíonn Auto cáilíocht chun PDF a fháil go dtí an méid cruinn compress.selectText.4=Mód uathoibríoch - Coigeartaíonn Auto cáilíocht chun PDF a fháil go dtí an méid cruinn
@@ -999,39 +981,39 @@ pdfOrganiser.placeholder=(m.sh. 1,3,2 nó 4-8,2,10-12 nó 2n-1)
multiTool.title=Il-uirlis PDF multiTool.title=Il-uirlis PDF
multiTool.header=Il-uirlis PDF multiTool.header=Il-uirlis PDF
multiTool.uploadPrompts=Ainm comhaid multiTool.uploadPrompts=Ainm comhaid
multiTool.selectAll=Roghnaigh Uile multiTool.selectAll=Select All
multiTool.deselectAll=Díroghnaigh Uile multiTool.deselectAll=Deselect All
multiTool.selectPages=Roghnaigh Leathanach multiTool.selectPages=Page Select
multiTool.selectedPages=Leathanaigh Roghnaithe multiTool.selectedPages=Selected Pages
multiTool.page=Leathanach multiTool.page=Page
multiTool.deleteSelected=Scrios Roghnaithe multiTool.deleteSelected=Delete Selected
multiTool.downloadAll=Easpórtáil multiTool.downloadAll=Export
multiTool.downloadSelected=Easpórtáil Roghnaithe multiTool.downloadSelected=Export Selected
multiTool.insertPageBreak=Ionsáigh Sos Leathanaigh multiTool.insertPageBreak=Insert Page Break
multiTool.addFile=Cuir Comhad Leis multiTool.addFile=Add File
multiTool.rotateLeft=Rothlaigh ar Chlé multiTool.rotateLeft=Rotate Left
multiTool.rotateRight=Rothlaigh ar Dheis multiTool.rotateRight=Rotate Right
multiTool.split=Scoil multiTool.split=Split
multiTool.moveLeft=Bog ar Chlé multiTool.moveLeft=Move Left
multiTool.moveRight=Bog ar Dheis multiTool.moveRight=Move Right
multiTool.delete=Scrios multiTool.delete=Delete
multiTool.dragDropMessage=Leathanach(leathanaigh) roghnaithe multiTool.dragDropMessage=Page(s) Selected
multiTool.undo=Cealaigh multiTool.undo=Undo
multiTool.redo=Athdhéan multiTool.redo=Redo
#decrypt #decrypt
decrypt.passwordPrompt=Tá an comhad seo cosanta ag pasfhocal. Cuir isteach an pasfhocal le do thoil: decrypt.passwordPrompt=This file is password-protected. Please enter the password:
decrypt.cancelled=Cealaíodh an oibríocht le haghaidh PDF: {0} decrypt.cancelled=Operation cancelled for PDF: {0}
decrypt.noPassword=Níor soláthraíodh focal faire don PDF criptithe: {0} decrypt.noPassword=No password provided for encrypted PDF: {0}
decrypt.invalidPassword=Déan iarracht eile leis an bhfocal faire ceart. decrypt.invalidPassword=Please try again with the correct password.
decrypt.invalidPasswordHeader=Focal faire mícheart nó criptiúchán PDF nach dtacaítear leis: {0} decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0}
decrypt.unexpectedError=Tharla earráid agus an comhad á phróiseáil. Bain triail eile as. decrypt.unexpectedError=There was an error processing the file. Please try again.
decrypt.serverError=Earráid fhreastalaí agus é díchriptiú: {0} decrypt.serverError=Server error while decrypting: {0}
decrypt.success=D'éirigh le díchriptiú an chomhaid. decrypt.success=File decrypted successfully.
#multiTool-advert #multiTool-advert
multiTool-advert.message=Tá an ghné seo ar fáil inár <a href="{0}">leathanach il-uirlisí</a> freisin. Seiceáil é le haghaidh Chomhéadain leathanach ar leathanach feabhsaithe agus gnéithe breise! multiTool-advert.message=This feature is also available in our <a href="{0}">multi-tool page</a>. Check it out for enhanced page-by-page UI and additional features!
#view pdf #view pdf
viewPdf.title=Féach PDF viewPdf.title=Féach PDF
@@ -1093,7 +1075,7 @@ pdfToImage.color=Dath
pdfToImage.grey=Scála Liath pdfToImage.grey=Scála Liath
pdfToImage.blackwhite=Dubh agus Bán (Dfhéadfadh sonraí a chailleadh!) pdfToImage.blackwhite=Dubh agus Bán (Dfhéadfadh sonraí a chailleadh!)
pdfToImage.submit=Tiontaigh pdfToImage.submit=Tiontaigh
pdfToImage.info=Níl Python suiteáilte. Ag teastáil le haghaidh comhshó WebP. pdfToImage.info=Python is not installed. Required for WebP conversion.
pdfToImage.placeholder=(m.sh. 1,2,8 nó 4,7,12-16 nó 2n-1) pdfToImage.placeholder=(m.sh. 1,2,8 nó 4,7,12-16 nó 2n-1)
@@ -1127,12 +1109,12 @@ watermark.selectText.1=Roghnaigh PDF chun comhartha uisce a chur leis:
watermark.selectText.2=Téacs Comhartha Uisce: watermark.selectText.2=Téacs Comhartha Uisce:
watermark.selectText.3=Méid cló: watermark.selectText.3=Méid cló:
watermark.selectText.4=Rothlú (0-360): watermark.selectText.4=Rothlú (0-360):
watermark.selectText.5=Spásaire Leithead (Spás idir gach comhartha uisce go cothrománach): watermark.selectText.5=Width Spacer (Spás idir gach comhartha uisce go cothrománach):
watermark.selectText.6=Spásaire Airde (Spás idir gach comhartha uisce go hingearach): watermark.selectText.6=spásaire airde (Spás idir gach comhartha uisce go hingearach):
watermark.selectText.7=Teimhneacht (0% - 100%): watermark.selectText.7=Teimhneacht (0% - 100%):
watermark.selectText.8=Cineál Comhartha Uisce: watermark.selectText.8=Cineál Comhartha Uisce:
watermark.selectText.9=Íomhá Comhartha Uisce: watermark.selectText.9=Íomhá Comhartha Uisce:
watermark.selectText.10=Tiontaigh PDF go PDF-Íomhá watermark.selectText.10=Convert PDF to PDF-Image
watermark.submit=Cuir Uisce leis watermark.submit=Cuir Uisce leis
watermark.type.1=Téacs watermark.type.1=Téacs
watermark.type.2=Íomha watermark.type.2=Íomha
@@ -1294,8 +1276,8 @@ licenses.license=Ceadúnas
survey.nav=Suirbhé survey.nav=Suirbhé
survey.title=Suirbhé Stirling-PDF survey.title=Suirbhé Stirling-PDF
survey.description=Níl aon rian ar Stirling-PDF agus mar sin ba mhaith linn cloisteáil ónár n-úsáideoirí chun feabhas a chur ar Stirling-PDF! survey.description=Níl aon rian ar Stirling-PDF agus mar sin ba mhaith linn cloisteáil ónár n-úsáideoirí chun feabhas a chur ar Stirling-PDF!
survey.changes=Stirling-PDF athraithe ón suirbhé deireanach! Le tuilleadh a fháil amach féach ar ár mblagphost anseo: survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
survey.changes2=De bharr na n-athruithe seo táimid ag fáil tacaíochta gnó agus maoiniú íoctha survey.changes2=With these changes we are getting paid business support and funding
survey.please=Smaoinigh ar ár suirbhé a dhéanamh le do thoil! survey.please=Smaoinigh ar ár suirbhé a dhéanamh le do thoil!
survey.disabled=(Díchumasófar aníos an tsuirbhé sna nuashonruithe seo a leanas ach beidh siad ar fáil ag bun an leathanaigh) survey.disabled=(Díchumasófar aníos an tsuirbhé sna nuashonruithe seo a leanas ach beidh siad ar fáil ag bun an leathanaigh)
survey.button=Tóg Suirbhé survey.button=Tóg Suirbhé
@@ -1317,69 +1299,69 @@ error.discordSubmit=Discord - Cuir post Tacaíochta
#remove-image #remove-image
removeImage.title=Bain íomhá removeImage.title=Remove image
removeImage.header=Bain íomhá removeImage.header=Remove image
removeImage.removeImage=Bain íomhá removeImage.removeImage=Remove image
removeImage.submit=Bain íomhá removeImage.submit=Remove image
splitByChapters.title=Scoil PDF de réir Caibidlí splitByChapters.title=Split PDF by Chapters
splitByChapters.header=Scoil PDF de réir Caibidlí splitByChapters.header=Split PDF by Chapters
splitByChapters.bookmarkLevel=Leibhéal Leabharmharc splitByChapters.bookmarkLevel=Bookmark Level
splitByChapters.includeMetadata=Cuir meiteashonraí san áireamh splitByChapters.includeMetadata=Include Metadata
splitByChapters.allowDuplicates=Ceadaigh do Dhúblaigh splitByChapters.allowDuplicates=Allow Duplicates
splitByChapters.desc.1=Scann an uirlis seo comhad PDF ina PDFanna iolracha bunaithe ar a struchtúr caibidle. splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
splitByChapters.desc.2=Leibhéal Leabharmharc: Roghnaigh leibhéal na leabharmharcanna le húsáid don scoilteadh (0 don bharrleibhéal, 1 don dara leibhéal, etc.). splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
splitByChapters.desc.3=Cuir Meiteashonraí san áireamh: Má dhéantar iad a sheiceáil, cuirfear meiteashonraí an PDF bhunaidh san áireamh i ngach PDF scoilte. splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
splitByChapters.desc.4=Ceadaigh do Dhúblaigh: Má dhéantar iad a sheiceáil, ceadaítear go leor leabharmharcanna ar an leathanach céanna chun PDFanna ar leith a chruthú. splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
splitByChapters.submit=Scoil PDF splitByChapters.submit=Split PDF
#File Chooser #File Chooser
fileChooser.click=Cliceáil fileChooser.click=Click
fileChooser.or= fileChooser.or=or
fileChooser.dragAndDrop=Tarraing & Scaoil fileChooser.dragAndDrop=Drag & Drop
fileChooser.dragAndDropPDF=Tarraing & Scaoil comhad PDF fileChooser.dragAndDropPDF=Drag & Drop PDF file
fileChooser.dragAndDropImage=Tarraing & Scaoil comhad Íomhá fileChooser.dragAndDropImage=Drag & Drop Image file
fileChooser.hoveredDragAndDrop=Tarraing agus scaoil comhad(í) anseo fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here
#release notes #release notes
releases.footer=Eisiúintí releases.footer=Releases
releases.title=Nótaí Eisiúna releases.title=Release Notes
releases.header=Nótaí Eisiúna releases.header=Release Notes
releases.current.version=Eisiúna Reatha releases.current.version=Current Release
releases.note=Tá nótaí eisiúna ar fáil i mBéarla amháin releases.note=Release notes are only available in English
#Validate Signature #Validate Signature
validateSignature.title=Bailíochtaigh Sínithe PDF validateSignature.title=Validate PDF Signatures
validateSignature.header=Bailíochtaigh Sínithe Digiteacha validateSignature.header=Validate Digital Signatures
validateSignature.selectPDF=Roghnaigh comhad PDF sínithe validateSignature.selectPDF=Select signed PDF file
validateSignature.submit=Bailíochtaigh Sínithe validateSignature.submit=Validate Signatures
validateSignature.results=Torthaí Bailíochtaithe validateSignature.results=Validation Results
validateSignature.status=Stádas validateSignature.status=Status
validateSignature.signer=Sínitheoir validateSignature.signer=Signer
validateSignature.date=Dáta validateSignature.date=Date
validateSignature.reason=Cúis validateSignature.reason=Reason
validateSignature.location=Suíomh validateSignature.location=Location
validateSignature.noSignatures=Níor aimsíodh síniú digiteach ar bith sa doiciméad seo validateSignature.noSignatures=No digital signatures found in this document
validateSignature.status.valid=Bailí validateSignature.status.valid=Valid
validateSignature.status.invalid=Neamhbhailí validateSignature.status.invalid=Invalid
validateSignature.chain.invalid=Theip ar bhailíochtú slabhra an teastais - ní féidir aitheantas an tsínitheora a fhíorú validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity
validateSignature.trust.invalid=Níl an teastas sa stór muiníne - ní féidir an fhoinse a fhíorú validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified
validateSignature.cert.expired=Tá an teastas imithe in éag validateSignature.cert.expired=Certificate has expired
validateSignature.cert.revoked=Tá an teastas cúlghairthe validateSignature.cert.revoked=Certificate has been revoked
validateSignature.signature.info=Eolas Sínithe validateSignature.signature.info=Signature Information
validateSignature.signature=Síniú validateSignature.signature=Signature
validateSignature.signature.mathValid=Tá an síniú bailí go matamaiticiúil ACH: validateSignature.signature.mathValid=Signature is mathematically valid BUT:
validateSignature.selectCustomCert=Comhad Teastais Saincheaptha X.509 (Roghnach) validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional)
validateSignature.cert.info=Sonraí an Teastais validateSignature.cert.info=Certificate Details
validateSignature.cert.issuer=Eisitheoir validateSignature.cert.issuer=Issuer
validateSignature.cert.subject=Ábhar validateSignature.cert.subject=Subject
validateSignature.cert.serialNumber=Sraithuimhir validateSignature.cert.serialNumber=Serial Number
validateSignature.cert.validFrom=Bailí Ó validateSignature.cert.validFrom=Valid From
validateSignature.cert.validUntil=Bailí Go dtí validateSignature.cert.validUntil=Valid Until
validateSignature.cert.algorithm=Algartam validateSignature.cert.algorithm=Algorithm
validateSignature.cert.keySize=Méid na hEochrach validateSignature.cert.keySize=Key Size
validateSignature.cert.version=Leagan validateSignature.cert.version=Version
validateSignature.cert.keyUsage=Úsáid Eochrach validateSignature.cert.keyUsage=Key Usage
validateSignature.cert.selfSigned=Féin-Sínithe validateSignature.cert.selfSigned=Self-Signed
validateSignature.cert.bits=giotáin validateSignature.cert.bits=bits

Some files were not shown because too many files have changed in this diff Show More