Compare commits
22 Commits
fix-sig-lo
...
saml2-sso-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92c0ddf63b | ||
|
|
7297e9e62d | ||
|
|
f8944fd2a9 | ||
|
|
3fd44fe7af | ||
|
|
4c9c9b5cbe | ||
|
|
e660237e28 | ||
|
|
83e93688ee | ||
|
|
dedfabd630 | ||
|
|
3b5b7772a9 | ||
|
|
c59d3ff3e0 | ||
|
|
5832147b30 | ||
|
|
20dc2f60cd | ||
|
|
b46ccdde44 | ||
|
|
4fa1b4adb0 | ||
|
|
03158b05e4 | ||
|
|
28c55ca80c | ||
|
|
6ca14edaf1 | ||
|
|
f9677b1fe8 | ||
|
|
04a6ebf515 | ||
|
|
262e2ed47a | ||
|
|
4436759e12 | ||
|
|
87925ac618 |
1
.github/pull_request_template.md
vendored
1
.github/pull_request_template.md
vendored
@@ -8,7 +8,6 @@ Closes #(issue_number)
|
|||||||
|
|
||||||
- [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
|
- [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
|
||||||
- [ ] I have performed a self-review of my own code
|
- [ ] I have performed a self-review of my own code
|
||||||
- [ ] I have attached images of the change if it is UI based
|
|
||||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||||
- [ ] My changes generate no new warnings
|
- [ ] My changes generate no new warnings
|
||||||
- [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only)
|
- [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only)
|
||||||
|
|||||||
53
.github/scripts/gradle_to_chart.py
vendored
53
.github/scripts/gradle_to_chart.py
vendored
@@ -8,20 +8,17 @@ gradle_path = "build.gradle"
|
|||||||
|
|
||||||
def get_chart_version(path):
|
def get_chart_version(path):
|
||||||
"""
|
"""
|
||||||
Reads the version and the appVersion from Chart.yaml.
|
Reads the appVersion from Chart.yaml.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): The file path to the Chart.yaml.
|
path (str): The file path to the Chart.yaml.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: The version under "chart" key and the appVersion under "app" key.
|
str: The appVersion if found, otherwise an empty string.
|
||||||
"""
|
"""
|
||||||
with open(path, encoding="utf-8") as file:
|
with open(path, encoding="utf-8") as file:
|
||||||
chart_yaml = yaml.safe_load(file)
|
chart_yaml = yaml.safe_load(file)
|
||||||
return {
|
return chart_yaml.get("appVersion", "")
|
||||||
"chart": chart_yaml["version"],
|
|
||||||
"app": chart_yaml["appVersion"]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_gradle_version(path):
|
def get_gradle_version(path):
|
||||||
@@ -42,46 +39,17 @@ def get_gradle_version(path):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def get_new_chart_version(chart_version, old_app_version, new_app_version):
|
def update_chart_version(path, new_version):
|
||||||
"""
|
|
||||||
Get the new chart version from
|
|
||||||
|
|
||||||
Args:
|
|
||||||
str: The current chart version.
|
|
||||||
str: The current app version.
|
|
||||||
str: The new app version.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The new chart version to update to.
|
|
||||||
"""
|
|
||||||
chart_major, chart_minor, chart_patch = chart_version.split(".")
|
|
||||||
|
|
||||||
old_major, old_minor, old_patch = old_app_version.split(".")
|
|
||||||
new_major, new_minor, new_patch = new_app_version.split(".")
|
|
||||||
|
|
||||||
if old_major != new_major:
|
|
||||||
new_chart_version = f"{int(chart_major)+1}.0.0"
|
|
||||||
elif old_minor != new_minor:
|
|
||||||
new_chart_version = f"{chart_major}.{int(chart_minor)+1}.0"
|
|
||||||
elif old_patch != new_patch:
|
|
||||||
new_chart_version = f"{chart_major}.{chart_minor}.{int(chart_patch)+1}"
|
|
||||||
|
|
||||||
return new_chart_version
|
|
||||||
|
|
||||||
|
|
||||||
def update_chart_version(path, new_chart_version, new_app_version):
|
|
||||||
"""
|
"""
|
||||||
Updates the version and the appVersion in Chart.yaml with a new version.
|
Updates the appVersion in Chart.yaml with a new version.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): The file path to the Chart.yaml.
|
path (str): The file path to the Chart.yaml.
|
||||||
new_chart_version (str): The new chart version to update to.
|
new_version (str): The new version to update to.
|
||||||
new_app_version (str): The new app version to update to.
|
|
||||||
"""
|
"""
|
||||||
with open(path, encoding="utf-8") as file:
|
with open(path, encoding="utf-8") as file:
|
||||||
chart_yaml = yaml.safe_load(file)
|
chart_yaml = yaml.safe_load(file)
|
||||||
chart_yaml["version"] = new_chart_version
|
chart_yaml["appVersion"] = new_version
|
||||||
chart_yaml["appVersion"] = new_app_version
|
|
||||||
with open(path, "w", encoding="utf-8") as file:
|
with open(path, "w", encoding="utf-8") as file:
|
||||||
yaml.safe_dump(chart_yaml, file)
|
yaml.safe_dump(chart_yaml, file)
|
||||||
|
|
||||||
@@ -90,11 +58,10 @@ def update_chart_version(path, new_chart_version, new_app_version):
|
|||||||
chart_version = get_chart_version(chart_yaml_path)
|
chart_version = get_chart_version(chart_yaml_path)
|
||||||
gradle_version = get_gradle_version(gradle_path)
|
gradle_version = get_gradle_version(gradle_path)
|
||||||
|
|
||||||
if chart_version["app"] != gradle_version:
|
if chart_version != gradle_version:
|
||||||
new_chart_version = get_new_chart_version(chart_version["chart"], chart_version["app"], gradle_version, )
|
|
||||||
print(
|
print(
|
||||||
f"Versions do not match. Updating Chart.yaml from {chart_version['chart']} to {new_chart_version}."
|
f"Versions do not match. Updating Chart.yaml from {chart_version} to {gradle_version}."
|
||||||
)
|
)
|
||||||
update_chart_version(chart_yaml_path, new_chart_version, gradle_version)
|
update_chart_version(chart_yaml_path, gradle_version)
|
||||||
else:
|
else:
|
||||||
print("Versions match. No update required.")
|
print("Versions match. No update required.")
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,7 +4,6 @@ bin/
|
|||||||
tmp/
|
tmp/
|
||||||
*.tmp
|
*.tmp
|
||||||
*.bak
|
*.bak
|
||||||
*.exe
|
|
||||||
*.swp
|
*.swp
|
||||||
*~.nib
|
*~.nib
|
||||||
local.properties
|
local.properties
|
||||||
@@ -111,6 +110,7 @@ watchedFolders/
|
|||||||
*.war
|
*.war
|
||||||
*.nar
|
*.nar
|
||||||
*.ear
|
*.ear
|
||||||
|
*.zip
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.rar
|
*.rar
|
||||||
*.db
|
*.db
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ If you would like to add or modify a translation, please see [How to add new lan
|
|||||||
|
|
||||||
## Docs
|
## Docs
|
||||||
|
|
||||||
Documentation for Stirling-PDF is handled in a separate repository. Please see [Docs repository](https://github.com/Stirling-Tools/Stirling-Tools.github.io) or use "edit this page"-button at the bottom of each page at [https://docs.stirlingpdf.com/](https://docs.stirlingpdf.com/).
|
Documentation for Stirling-PDF is handled in a separate repository. Please see [Docs repository](https://github.com/Stirling-Tools/Stirling-Tools.github.io) or use "edit this page"-button at the bottom of each page at [https://stirlingtools.com/docs/](https://stirlingtools.com/docs/).
|
||||||
|
|
||||||
## Fixing Bugs or Adding a New Feature
|
## Fixing Bugs or Adding a New Feature
|
||||||
|
|
||||||
@@ -41,4 +41,4 @@ If, at any point of time, you have a question, please feel free to ask in the sa
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
By contributing to this project, you agree that your contributions will be licensed under the [MIT License](LICENSE).
|
By contributing to this project, you agree that your contributions will be licensed under the [GPL 3 License](LICENSE). You also acknowledge and agree that your contributions will be included in Stirling-PDF and that they can be relicensed in the future under the MPL 2.0 (Mozilla Public License Version 2.0) license.
|
||||||
|
|||||||
@@ -1,557 +0,0 @@
|
|||||||
# Stirling-PDF Developer Guide
|
|
||||||
|
|
||||||
## 1. Introduction
|
|
||||||
|
|
||||||
Stirling-PDF is a robust, locally hosted web-based PDF manipulation tool. This guide focuses on Docker-based development and testing, which is the recommended approach for working with the full version of Stirling-PDF.
|
|
||||||
|
|
||||||
## 2. Project Overview
|
|
||||||
|
|
||||||
Stirling-PDF is built using:
|
|
||||||
- Spring Boot + Thymeleaf
|
|
||||||
- PDFBox
|
|
||||||
- LibreOffice
|
|
||||||
- OcrMyPdf
|
|
||||||
- HTML, CSS, JavaScript
|
|
||||||
- Docker
|
|
||||||
- PDF.js
|
|
||||||
- PDF-LIB.js
|
|
||||||
- Lombok
|
|
||||||
|
|
||||||
## 3. Development Environment Setup
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Docker
|
|
||||||
- Git
|
|
||||||
- Java JDK 17 or later
|
|
||||||
- Gradle 7.0 or later (Included within repo)
|
|
||||||
|
|
||||||
### Setup Steps
|
|
||||||
1. Clone the repository:
|
|
||||||
```
|
|
||||||
git clone https://github.com/Stirling-Tools/Stirling-PDF.git
|
|
||||||
cd Stirling-PDF
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Install Docker and JDK17 if not already installed.
|
|
||||||
|
|
||||||
3. Install a recommended Java IDE such as Eclipse, IntelliJ or VSCode
|
|
||||||
|
|
||||||
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:
|
|
||||||
Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE.
|
|
||||||
|
|
||||||
5. Add environment variable
|
|
||||||
For local testing you should generally be testing the full 'Security' version of Stirling-PDF to do this you must add the environment flag DOCKER_ENABLE_SECURITY=true to your system and/or IDE build/run step
|
|
||||||
|
|
||||||
|
|
||||||
## 4. Project Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
Stirling-PDF/
|
|
||||||
├── .github/ # GitHub-specific files (workflows, issue templates)
|
|
||||||
├── configs/ # Configuration files used by stirling at runtime (generated at runtime)
|
|
||||||
├── cucumber/ # Cucumber test files
|
|
||||||
│ ├── features/
|
|
||||||
├── customFiles/ # Custom static files and templates (generated at runtime used to replace existing files)
|
|
||||||
├── docs/ # Documentation files
|
|
||||||
├── exampleYmlFiles/ # Example YAML configuration files
|
|
||||||
├── images/ # Image assets
|
|
||||||
├── pipeline/ # Pipeline-related files (generated at runtime)
|
|
||||||
├── scripts/ # Utility scripts
|
|
||||||
├── src/ # Source code
|
|
||||||
│ ├── main/
|
|
||||||
│ │ ├── java/
|
|
||||||
│ │ │ └── stirling/
|
|
||||||
│ │ │ └── software/
|
|
||||||
│ │ │ └── SPDF/
|
|
||||||
│ │ │ ├── config/
|
|
||||||
│ │ │ ├── controller/
|
|
||||||
│ │ │ ├── model/
|
|
||||||
│ │ │ ├── repository/
|
|
||||||
│ │ │ ├── service/
|
|
||||||
│ │ │ └── utils/
|
|
||||||
│ │ └── resources/
|
|
||||||
│ │ ├── static/
|
|
||||||
│ │ │ ├── css/
|
|
||||||
│ │ │ ├── js/
|
|
||||||
│ │ │ └── pdfjs/
|
|
||||||
│ │ └── templates/
|
|
||||||
│ └── test/
|
|
||||||
│ └── java/
|
|
||||||
│ └── stirling/
|
|
||||||
│ └── software/
|
|
||||||
│ └── SPDF/
|
|
||||||
├── build.gradle # Gradle build configuration
|
|
||||||
├── Dockerfile # Main Dockerfile
|
|
||||||
├── Dockerfile-ultra-lite # Dockerfile for ultra-lite version
|
|
||||||
├── Dockerfile-fat # Dockerfile for fat version
|
|
||||||
├── docker-compose.yml # Docker Compose configuration
|
|
||||||
└── test.sh # Test script to deploy all docker versions and run cuke tests
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. Docker-based Development
|
|
||||||
|
|
||||||
Stirling-PDF offers several Docker versions:
|
|
||||||
- Full: All features included
|
|
||||||
- Ultra-Lite: Basic PDF operations only
|
|
||||||
- Fat: Includes additional libraries and fonts predownloaded
|
|
||||||
|
|
||||||
### Example Docker Compose Files
|
|
||||||
|
|
||||||
Stirling-PDF provides several example Docker Compose files in the `exampleYmlFiles` directory such as :
|
|
||||||
|
|
||||||
- `docker-compose-latest.yml`: Latest version without security features
|
|
||||||
- `docker-compose-latest-security.yml`: Latest version with security features enabled
|
|
||||||
- `docker-compose-latest-fat-security.yml`: Fat version with security features enabled
|
|
||||||
|
|
||||||
These files provide pre-configured setups for different scenarios. For example, here's a snippet from `docker-compose-latest-security.yml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security
|
|
||||||
image: frooodle/s-pdf:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
volumes:
|
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- /stirling/latest/config:/configs:rw
|
|
||||||
- /stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DOCKER_ENABLE_SECURITY: "true"
|
|
||||||
SECURITY_ENABLELOGIN: "true"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
restart: on-failure:5
|
|
||||||
```
|
|
||||||
|
|
||||||
To use these example files, copy the desired file to your project root and rename it to `docker-compose.yml`, or specify the file explicitly when running Docker Compose:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose -f exampleYmlFiles/docker-compose-latest-security.yml up
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building Docker Images
|
|
||||||
|
|
||||||
Stirling-PDF uses different Docker images for various configurations. The build process is controlled by environment variables and uses specific Dockerfile variants. Here's how to build the Docker images:
|
|
||||||
|
|
||||||
1. Set the security environment variable:
|
|
||||||
```bash
|
|
||||||
export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Build the project with Gradle:
|
|
||||||
```bash
|
|
||||||
./gradlew clean build
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Build the Docker images:
|
|
||||||
|
|
||||||
For the latest version:
|
|
||||||
```bash
|
|
||||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest -f ./Dockerfile .
|
|
||||||
```
|
|
||||||
|
|
||||||
For the ultra-lite version:
|
|
||||||
```bash
|
|
||||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-ultra-lite -f ./Dockerfile-ultra-lite .
|
|
||||||
```
|
|
||||||
|
|
||||||
For the fat version (with security enabled):
|
|
||||||
```bash
|
|
||||||
export DOCKER_ENABLE_SECURITY=true
|
|
||||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-fat -f ./Dockerfile-fat .
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: The `--no-cache` and `--pull` flags ensure that the build process uses the latest base images and doesn't use cached layers, which is useful for testing and ensuring reproducible builds. however to improve build times these can often be removed depending on your usecase
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 6. Testing
|
|
||||||
|
|
||||||
### Comprehensive Testing Script
|
|
||||||
|
|
||||||
Stirling-PDF provides a `test.sh` script in the root directory. This script builds all versions of Stirling-PDF, checks that each version works, and runs Cucumber tests. It's recommended to run this script before submitting a final pull request.
|
|
||||||
|
|
||||||
To run the test script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./test.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This script performs the following actions:
|
|
||||||
1. Builds all Docker images (full, ultra-lite, fat)
|
|
||||||
2. Runs each version to ensure it starts correctly
|
|
||||||
3. Executes Cucumber tests against main version and ensures feature compatibility, in the event these tests fail your PR will not be merged
|
|
||||||
|
|
||||||
Note: The `test.sh` script will run automatically when you raise a PR. However, it's recommended to run it locally first to save resources and catch any issues early.
|
|
||||||
|
|
||||||
### Full Testing with Docker
|
|
||||||
|
|
||||||
1. Build and run the Docker container per the above instructions:
|
|
||||||
|
|
||||||
2. Access the application at `http://localhost:8080` and manually test all features developed.
|
|
||||||
|
|
||||||
|
|
||||||
### Local Testing (Java and UI Components)
|
|
||||||
|
|
||||||
For quick iterations and development of Java backend, JavaScript, and UI components, you can run and test Stirling-PDF locally without Docker. This approach allows you to work on and verify changes to:
|
|
||||||
|
|
||||||
- Java backend logic
|
|
||||||
- RESTful API endpoints
|
|
||||||
- JavaScript functionality
|
|
||||||
- User interface components and styling
|
|
||||||
- Thymeleaf templates
|
|
||||||
|
|
||||||
To run Stirling-PDF locally:
|
|
||||||
|
|
||||||
1. Compile and run the project using built in IDE methods or by running:
|
|
||||||
```
|
|
||||||
./gradlew bootRun
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Access the application at `http://localhost:8080` in your web browser.
|
|
||||||
|
|
||||||
3. Manually test the features you're working on through the UI.
|
|
||||||
|
|
||||||
4. For API changes, use tools like Postman or curl to test endpoints directly.
|
|
||||||
|
|
||||||
Important notes:
|
|
||||||
- Local testing doesn't include features that depend on external tools like OCRmyPDF, LibreOffice, or Python scripts.
|
|
||||||
- There are currently no automated unit tests. All testing is done manually through the UI or API calls. (You are welcome to add JUnits!)
|
|
||||||
- Always verify your changes in the full Docker environment before submitting pull requests, as some integrations and features will only work in the complete setup.
|
|
||||||
|
|
||||||
|
|
||||||
## 7. Contributing
|
|
||||||
|
|
||||||
1. Fork the repository on GitHub.
|
|
||||||
2. Create a new branch for your feature or bug fix.
|
|
||||||
3. Make your changes and commit them with clear, descriptive messages and ensure any documentation is updated related to your changes.
|
|
||||||
4. Test your changes thoroughly in the Docker environment.
|
|
||||||
5. Run the `test.sh` script to ensure all versions build correctly and pass the Cucumber tests:
|
|
||||||
```bash
|
|
||||||
./test.sh
|
|
||||||
```
|
|
||||||
6. Push your changes to your fork.
|
|
||||||
7. Submit a pull request to the main repository.
|
|
||||||
8. See additional [contributing guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
|
|
||||||
|
|
||||||
When you raise a PR:
|
|
||||||
- The `test.sh` script will run automatically against your PR.
|
|
||||||
- The PR checks will verify versioning and dependency updates.
|
|
||||||
- Documentation will be automatically updated for dependency changes.
|
|
||||||
- Security issues will be checked using Snyk and PixeeBot.
|
|
||||||
|
|
||||||
Address any issues that arise from these checks before finalizing your pull request.
|
|
||||||
|
|
||||||
## 8. API Documentation
|
|
||||||
|
|
||||||
API documentation is available at `/swagger-ui/index.html` when running the application. You can also view the latest API documentation [here](https://app.swaggerhub.com/apis-docs/Stirling-Tools/Stirling-PDF/).
|
|
||||||
|
|
||||||
## 9. Customization
|
|
||||||
|
|
||||||
Stirling-PDF can be customized through environment variables or a `settings.yml` file. Key customization options include:
|
|
||||||
- Application name and branding
|
|
||||||
- Security settings
|
|
||||||
- UI customization
|
|
||||||
- Endpoint management
|
|
||||||
|
|
||||||
When using Docker, pass environment variables using the `-e` flag or in your `docker-compose.yml` file.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```
|
|
||||||
docker run -p 8080:8080 -e APP_NAME="My PDF Tool" stirling-pdf:full
|
|
||||||
```
|
|
||||||
|
|
||||||
Refer to the main README for a full list of customization options.
|
|
||||||
|
|
||||||
## 10. Language Translations
|
|
||||||
|
|
||||||
For managing language translations that affect multiple files, Stirling-PDF provides a helper script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/scripts/replace_translation_line.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This script helps you make consistent replacements across language files.
|
|
||||||
|
|
||||||
When contributing translations:
|
|
||||||
1. Use the helper script for multi-file changes.
|
|
||||||
2. Ensure all language files are updated consistently.
|
|
||||||
3. The PR checks will verify consistency in language file updates.
|
|
||||||
|
|
||||||
Remember to test your changes thoroughly to ensure they don't break any existing functionality.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Code examples
|
|
||||||
|
|
||||||
### Overview of Thymeleaf
|
|
||||||
|
|
||||||
Thymeleaf is a server-side Java HTML template engine. It is used in Stirling-PDF to render dynamic web pages. Thymeleaf integrates heavily with Spring Boot
|
|
||||||
|
|
||||||
### Thymeleaf overview
|
|
||||||
|
|
||||||
In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content.
|
|
||||||
Some examples of this are
|
|
||||||
```html
|
|
||||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
|
||||||
or
|
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
|
||||||
```
|
|
||||||
Where it uses the th:block, th: indicating its a special thymeleaf element to be used serverside in generating the html, and block being the actual element type.
|
|
||||||
In this case we are inserting the ``navbar`` entry within the ``fragments/navbar.html`` fragment into the ``th:block`` element.
|
|
||||||
|
|
||||||
They can be more complex such as
|
|
||||||
```html
|
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{pageExtracter.title}, header=#{pageExtracter.header})}"></th:block>
|
|
||||||
```
|
|
||||||
Which is the same as above but passes the parameters title and header into the fragment common.html to be used in its HTML generation
|
|
||||||
|
|
||||||
Thymeleaf can also be used to loop through objects or pass things from java side into html side.
|
|
||||||
```java
|
|
||||||
@GetMapping
|
|
||||||
public String newFeaturePage(Model model) {
|
|
||||||
model.addAttribute("exampleData", exampleData);
|
|
||||||
return "new-feature";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
in above example if exampleData is a list of plain java objects of class Person and within it you had id, name, age etc. You can reference it like so
|
|
||||||
```html
|
|
||||||
<tbody>
|
|
||||||
<!-- Use th:each to iterate over the list -->
|
|
||||||
<tr th:each="person : ${exampleData}">
|
|
||||||
<td th:text="${person.id}"></td>
|
|
||||||
<td th:text="${person.name}"></td>
|
|
||||||
<td th:text="${person.age}"></td>
|
|
||||||
<td th:text="${person.email}"></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
```
|
|
||||||
This would generate n entries of tr for each person in exampleData
|
|
||||||
|
|
||||||
### Adding a New Feature to the Backend (API)
|
|
||||||
|
|
||||||
1. **Create a New Controller:**
|
|
||||||
- Create a new Java class in the `src/main/java/stirling/software/SPDF/controller/api` directory.
|
|
||||||
- Annotate the class with `@RestController` and `@RequestMapping` to define the API endpoint.
|
|
||||||
- Ensure to add API documentation annotations like `@Tag(name = "General", description = "General APIs")` and `@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")`.
|
|
||||||
|
|
||||||
```java
|
|
||||||
package stirling.software.SPDF.controller.api;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/new-feature")
|
|
||||||
@Tag(name = "General", description = "General APIs")
|
|
||||||
public class NewFeatureController {
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
@Operation(summary = "New Feature", description = "This is a new feature endpoint.")
|
|
||||||
public String newFeature() {
|
|
||||||
return "NewFeatureResponse"; // This refers to the NewFeatureResponse.html template presenting the user with the generated html from that file when they navigate to /api/v1/new-feature
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Define the Service Layer:** (Not required but often useful)
|
|
||||||
- Create a new service class in the `src/main/java/stirling/software/SPDF/service` directory.
|
|
||||||
- Implement the business logic for the new feature.
|
|
||||||
|
|
||||||
```java
|
|
||||||
package stirling.software.SPDF.service;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class NewFeatureService {
|
|
||||||
|
|
||||||
public String getNewFeatureData() {
|
|
||||||
// Implement business logic here
|
|
||||||
return "New Feature Data";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2b. **Integrate the Service with the Controller:**
|
|
||||||
- Autowire the service class in the controller and use it to handle the API request.
|
|
||||||
|
|
||||||
```java
|
|
||||||
package stirling.software.SPDF.controller.api;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import stirling.software.SPDF.service.NewFeatureService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/new-feature")
|
|
||||||
@Tag(name = "General", description = "General APIs")
|
|
||||||
public class NewFeatureController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private NewFeatureService newFeatureService;
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
@Operation(summary = "New Feature", description = "This is a new feature endpoint.")
|
|
||||||
public String newFeature() {
|
|
||||||
return newFeatureService.getNewFeatureData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding a New Feature to the Frontend (UI)
|
|
||||||
|
|
||||||
1. **Create a New Thymeleaf Template:**
|
|
||||||
- Create a new HTML file in the `src/main/resources/templates` directory.
|
|
||||||
- Use Thymeleaf attributes to dynamically generate content.
|
|
||||||
- Use `extract-page.html` as a base example for the HTML template, useful to ensure importing of the general layout, navbar and footer.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
|
|
||||||
<head>
|
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{newFeature.title}, header=#{newFeature.header})}"></th:block>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="page-container">
|
|
||||||
<div id="content-wrap">
|
|
||||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
|
||||||
<br><br>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row justify-content-center">
|
|
||||||
<div class="col-md-6 bg-card">
|
|
||||||
<div class="tool-header">
|
|
||||||
<span class="material-symbols-rounded tool-header-icon organize">upload</span>
|
|
||||||
<span class="tool-header-text" th:text="#{newFeature.header}"></span>
|
|
||||||
</div>
|
|
||||||
<form th:action="@{'/api/v1/new-feature'}" method="post" enctype="multipart/form-data">
|
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
|
|
||||||
<input type="hidden" id="customMode" name="customMode" value="">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="featureInput" th:text="#{newFeature.prompt}"></label>
|
|
||||||
<input type="text" class="form-control" id="featureInput" name="featureInput" th:placeholder="#{newFeature.placeholder}" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{newFeature.submit}"></button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Create a New Controller for the UI:**
|
|
||||||
- Create a new Java class in the `src/main/java/stirling/software/SPDF/controller/ui` directory.
|
|
||||||
- Annotate the class with `@Controller` and `@RequestMapping` to define the UI endpoint.
|
|
||||||
|
|
||||||
```java
|
|
||||||
package stirling.software.SPDF.controller.ui;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import stirling.software.SPDF.service.NewFeatureService;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/new-feature")
|
|
||||||
public class NewFeatureUIController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private NewFeatureService newFeatureService;
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public String newFeaturePage(Model model) {
|
|
||||||
model.addAttribute("newFeatureData", newFeatureService.getNewFeatureData());
|
|
||||||
return "new-feature";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Update the Navigation Bar:**
|
|
||||||
- Add a link to the new feature page in the navigation bar.
|
|
||||||
- Update the `src/main/resources/templates/fragments/navbar.html` file.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" th:href="@{/new-feature}">New Feature</a>
|
|
||||||
</li>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Adding New Translations to Existing Language Files in Stirling-PDF
|
|
||||||
|
|
||||||
When adding a new feature or modifying existing ones in Stirling-PDF, you'll need to add new translation entries to the existing language files. Here's a step-by-step guide:
|
|
||||||
|
|
||||||
### 1. Locate Existing Language Files
|
|
||||||
|
|
||||||
Find the existing `messages.properties` files in the `src/main/resources` directory. You'll see files like:
|
|
||||||
|
|
||||||
- `messages.properties` (default, usually English)
|
|
||||||
- `messages_en_GB.properties`
|
|
||||||
- `messages_fr.properties`
|
|
||||||
- `messages_de.properties`
|
|
||||||
- etc.
|
|
||||||
|
|
||||||
### 2. Add New Translation Entries
|
|
||||||
|
|
||||||
Open each of these files and add your new translation entries. For example, if you're adding a new feature called "PDF Splitter",
|
|
||||||
Use descriptive, hierarchical keys (e.g., `feature.element.description`)
|
|
||||||
you might add:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
pdfSplitter.title=PDF Splitter
|
|
||||||
pdfSplitter.description=Split your PDF into multiple documents
|
|
||||||
pdfSplitter.button.split=Split PDF
|
|
||||||
pdfSplitter.input.pages=Enter page numbers to split
|
|
||||||
```
|
|
||||||
|
|
||||||
Add these entries to the default GB language file and any others you wish, translating the values as appropriate for each language.
|
|
||||||
|
|
||||||
### 3. Use Translations in Thymeleaf Templates
|
|
||||||
|
|
||||||
In your Thymeleaf templates, use the `#{key}` syntax to reference the new translations:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<h1 th:text="#{pdfSplitter.title}">PDF Splitter</h1>
|
|
||||||
<p th:text="#{pdfSplitter.description}">Split your PDF into multiple documents</p>
|
|
||||||
<input type="text" th:placeholder="#{pdfSplitter.input.pages}">
|
|
||||||
<button th:text="#{pdfSplitter.button.split}">Split PDF</button>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Remember, never hard-code text in your templates or Java code. Always use translation keys to ensure proper localization.
|
|
||||||
112
README.md
112
README.md
@@ -166,55 +166,48 @@ Note: Podman is CLI-compatible with Docker, so simply replace "docker" with "pod
|
|||||||
|
|
||||||
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md
|
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md
|
||||||
|
|
||||||
## Reuse stored files
|
|
||||||
|
|
||||||
Certain functionality like ``Sign`` Supports pre-saved files stored at ``/customFiles/signatures/``, image files placed within here will be accesable to be used via webUI
|
|
||||||
Currently this supports two folder types
|
|
||||||
- ``/customFiles/signatures/ALL_USERS`` accessible to all users, useful for orginasations were many users use same files or for users not using authentication
|
|
||||||
- ``/customFiles/signatures/{username}`` such as ``/customFiles/signatures/froodle`` accessible to only the ``froodle`` username, private for all others
|
|
||||||
|
|
||||||
## Supported Languages
|
## Supported Languages
|
||||||
|
|
||||||
Stirling PDF currently supports 38!
|
Stirling PDF currently supports 38!
|
||||||
|
|
||||||
| Language | Progress |
|
| Language | Progress |
|
||||||
| ------------------------------------------- | -------------------------------------- |
|
| ------------------------------------------- | -------------------------------------- |
|
||||||
| Arabic (العربية) (ar_AR) |  |
|
| Arabic (العربية) (ar_AR) |  |
|
||||||
| Basque (Euskara) (eu_ES) |  |
|
| Basque (Euskara) (eu_ES) |  |
|
||||||
| Bulgarian (Български) (bg_BG) |  |
|
| Bulgarian (Български) (bg_BG) |  |
|
||||||
| Catalan (Català) (ca_CA) |  |
|
| Catalan (Català) (ca_CA) |  |
|
||||||
| Croatian (Hrvatski) (hr_HR) |  |
|
| Croatian (Hrvatski) (hr_HR) |  |
|
||||||
| Czech (Česky) (cs_CZ) |  |
|
| Czech (Česky) (cs_CZ) |  |
|
||||||
| Danish (Dansk) (da_DK) |  |
|
| Danish (Dansk) (da_DK) |  |
|
||||||
| Dutch (Nederlands) (nl_NL) |  |
|
| Dutch (Nederlands) (nl_NL) |  |
|
||||||
| English (English) (en_GB) |  |
|
| English (English) (en_GB) |  |
|
||||||
| English (US) (en_US) |  |
|
| English (US) (en_US) |  |
|
||||||
| French (Français) (fr_FR) |  |
|
| French (Français) (fr_FR) |  |
|
||||||
| German (Deutsch) (de_DE) |  |
|
| German (Deutsch) (de_DE) |  |
|
||||||
| Greek (Ελληνικά) (el_GR) |  |
|
| Greek (Ελληνικά) (el_GR) |  |
|
||||||
| Hindi (हिंदी) (hi_IN) |  |
|
| Hindi (हिंदी) (hi_IN) |  |
|
||||||
| Hungarian (Magyar) (hu_HU) |  |
|
| Hungarian (Magyar) (hu_HU) |  |
|
||||||
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
||||||
| Irish (Gaeilge) (ga_IE) |  |
|
| Irish (Gaeilge) (ga_IE) |  |
|
||||||
| Italian (Italiano) (it_IT) |  |
|
| Italian (Italiano) (it_IT) |  |
|
||||||
| Japanese (日本語) (ja_JP) |  |
|
| Japanese (日本語) (ja_JP) |  |
|
||||||
| Korean (한국어) (ko_KR) |  |
|
| Korean (한국어) (ko_KR) |  |
|
||||||
| Norwegian (Norsk) (no_NB) |  |
|
| Norwegian (Norsk) (no_NB) |  |
|
||||||
| Polish (Polski) (pl_PL) |  |
|
| Polish (Polski) (pl_PL) |  |
|
||||||
| Portuguese (Português) (pt_PT) |  |
|
| Portuguese (Português) (pt_PT) |  |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||||
| Romanian (Română) (ro_RO) |  |
|
| Romanian (Română) (ro_RO) |  |
|
||||||
| Russian (Русский) (ru_RU) |  |
|
| Russian (Русский) (ru_RU) |  |
|
||||||
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
||||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||||
| Slovakian (Slovensky) (sk_SK) |  |
|
| Slovakian (Slovensky) (sk_SK) |  |
|
||||||
| Spanish (Español) (es_ES) |  |
|
| Spanish (Español) (es_ES) |  |
|
||||||
| Swedish (Svenska) (sv_SE) |  |
|
| Swedish (Svenska) (sv_SE) |  |
|
||||||
| Thai (ไทย) (th_TH) |  |
|
| Thai (ไทย) (th_TH) |  |
|
||||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||||
| Turkish (Türkçe) (tr_TR) |  |
|
| Turkish (Türkçe) (tr_TR) |  |
|
||||||
| Ukrainian (Українська) (uk_UA) |  |
|
| Ukrainian (Українська) (uk_UA) |  |
|
||||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||||
|
|
||||||
## Contributing (creating issues, translations, fixing bugs, etc.)
|
## Contributing (creating issues, translations, fixing bugs, etc.)
|
||||||
|
|
||||||
@@ -280,44 +273,14 @@ security:
|
|||||||
useAsUsername: email # Default is 'email'; custom fields can be used as the username
|
useAsUsername: email # Default is 'email'; custom fields can be used as the username
|
||||||
scopes: openid, profile, email # Specify the scopes for which the application will request permissions
|
scopes: openid, profile, email # Specify the scopes for which the application will request permissions
|
||||||
provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
||||||
saml2:
|
|
||||||
enabled: false # Currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true
|
|
||||||
autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
|
|
||||||
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
|
||||||
registrationId: stirling
|
|
||||||
idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata
|
|
||||||
idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml
|
|
||||||
idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml
|
|
||||||
idpIssuer: http://www.okta.com/externalKey
|
|
||||||
idpCert: classpath:octa.crt
|
|
||||||
privateKey: classpath:saml-private-key.key
|
|
||||||
spCert: classpath:saml-public-cert.crt
|
|
||||||
|
|
||||||
enterpriseEdition:
|
|
||||||
enabled: false # set to 'true' to enable enterprise edition
|
|
||||||
key: 00000000-0000-0000-0000-000000000000
|
|
||||||
CustomMetadata:
|
|
||||||
autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values
|
|
||||||
author: username # Supports text such as 'John Doe' or types such as username to autopopulate with users username
|
|
||||||
creator: Stirling-PDF # Supports text such as 'Company-PDF'
|
|
||||||
producer: Stirling-PDF # Supports text such as 'Company-PDF'
|
|
||||||
|
|
||||||
legal:
|
|
||||||
termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms) Empty string to disable or filename to load from local file in static folder
|
|
||||||
privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy) Empty string to disable or filename to load from local file in static folder
|
|
||||||
accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility) Empty string to disable or filename to load from local file in static folder
|
|
||||||
cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie) Empty string to disable or filename to load from local file in static folder
|
|
||||||
impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum) Empty string to disable or filename to load from local file in static folder
|
|
||||||
|
|
||||||
system:
|
system:
|
||||||
defaultLocale: en-US # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
|
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
|
||||||
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
|
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
|
||||||
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
|
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
|
||||||
showUpdate: false # see when a new update is available
|
showUpdate: true # see when a new update is available
|
||||||
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
|
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
|
||||||
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
|
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
|
||||||
tessdataDir: /usr/share/tessdata # Path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored.
|
|
||||||
enableAnalytics: undefined # Set to 'true' to enable analytics, set to 'false' to disable analytics, for enterprise users this is set to true
|
|
||||||
|
|
||||||
ui:
|
ui:
|
||||||
appName: '' # Application's visible name
|
appName: '' # Application's visible name
|
||||||
@@ -330,11 +293,6 @@ endpoints:
|
|||||||
|
|
||||||
metrics:
|
metrics:
|
||||||
enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
|
enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
|
||||||
|
|
||||||
# Automatically Generated Settings (Do Not Edit Directly)
|
|
||||||
AutomaticallyGenerated:
|
|
||||||
key: example
|
|
||||||
UUID: example
|
|
||||||
```
|
```
|
||||||
|
|
||||||
There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones
|
There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones
|
||||||
|
|||||||
43
build.gradle
43
build.gradle
@@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id "java"
|
||||||
id "org.springframework.boot" version "3.3.5"
|
id "org.springframework.boot" version "3.3.4"
|
||||||
id "io.spring.dependency-management" version "1.1.6"
|
id "io.spring.dependency-management" version "1.1.6"
|
||||||
id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
|
id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
|
||||||
id "io.swagger.swaggerhub" version "1.3.2"
|
id "io.swagger.swaggerhub" version "1.3.2"
|
||||||
@@ -13,16 +13,16 @@ plugins {
|
|||||||
import com.github.jk1.license.render.*
|
import com.github.jk1.license.render.*
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
springBootVersion = "3.3.5"
|
springBootVersion = "3.3.4"
|
||||||
pdfboxVersion = "3.0.3"
|
pdfboxVersion = "3.0.3"
|
||||||
logbackVersion = "1.5.7"
|
logbackVersion = "1.5.7"
|
||||||
imageioVersion = "3.12.0"
|
imageioVersion = "3.11.0"
|
||||||
lombokVersion = "1.18.34"
|
lombokVersion = "1.18.34"
|
||||||
bouncycastleVersion = "1.78.1"
|
bouncycastleVersion = "1.78.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
group = "stirling.software"
|
||||||
version = "0.31.1"
|
version = "0.29.0"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
// 17 is lowest but we support and recommend 21
|
// 17 is lowest but we support and recommend 21
|
||||||
@@ -32,9 +32,11 @@ java {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
|
maven {
|
||||||
|
url "https://build.shibboleth.net/nexus/content/repositories/releases/"
|
||||||
|
}
|
||||||
maven {
|
maven {
|
||||||
url 'https://build.shibboleth.net/maven/releases'
|
url "https://build.shibboleth.net/maven/releases/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
//security updates
|
//security updates
|
||||||
implementation "org.springframework:spring-webmvc:6.1.14"
|
implementation "org.springframework:spring-webmvc:6.1.13"
|
||||||
|
|
||||||
implementation("io.github.pixee:java-security-toolkit:1.2.0")
|
implementation("io.github.pixee:java-security-toolkit:1.2.0")
|
||||||
|
|
||||||
@@ -132,36 +134,24 @@ dependencies {
|
|||||||
|
|
||||||
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
||||||
implementation 'com.posthog.java:posthog:1.1.1'
|
implementation 'com.posthog.java:posthog:1.1.1'
|
||||||
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
|
|
||||||
|
|
||||||
|
|
||||||
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
|
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
|
||||||
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
|
||||||
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
|
runtimeOnly "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
||||||
|
|
||||||
implementation 'org.springframework.security:spring-security-saml2-service-provider:6.3.4'
|
implementation 'org.springframework.security:spring-security-saml2-service-provider:6.3.3'
|
||||||
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
||||||
//2.2.x requires rebuild of DB file.. need migration path
|
//2.2.x requires rebuild of DB file.. need migration path
|
||||||
runtimeOnly "com.h2database:h2:2.1.214"
|
runtimeOnly "com.h2database:h2:2.1.214"
|
||||||
// implementation "com.h2database:h2:2.2.224"
|
// implementation "com.h2database:h2:2.2.224"
|
||||||
constraints {
|
|
||||||
implementation "org.opensaml:opensaml-core"
|
|
||||||
implementation "org.opensaml:opensaml-saml-api"
|
|
||||||
implementation "org.opensaml:opensaml-saml-impl"
|
|
||||||
}
|
|
||||||
implementation "org.springframework.security:spring-security-saml2-service-provider"
|
|
||||||
|
|
||||||
implementation 'com.coveo:saml-client:5.0.0'
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
||||||
|
|
||||||
// Batik
|
// Batik
|
||||||
implementation "org.apache.xmlgraphics:batik-all:1.18"
|
implementation "org.apache.xmlgraphics:batik-all:1.17"
|
||||||
|
|
||||||
// TwelveMonkeys
|
// TwelveMonkeys
|
||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
||||||
@@ -181,9 +171,6 @@ dependencies {
|
|||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
||||||
|
|
||||||
// Image metadata extractor
|
|
||||||
implementation "com.drewnoakes:metadata-extractor:2.19.0"
|
|
||||||
|
|
||||||
implementation "commons-io:commons-io:2.17.0"
|
implementation "commons-io:commons-io:2.17.0"
|
||||||
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
|
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
|
||||||
//general PDF
|
//general PDF
|
||||||
@@ -206,11 +193,11 @@ dependencies {
|
|||||||
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
|
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
|
||||||
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
|
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
|
||||||
implementation "io.micrometer:micrometer-core:1.13.6"
|
implementation "io.micrometer:micrometer-core:1.13.4"
|
||||||
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
|
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
|
||||||
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
||||||
implementation "org.commonmark:commonmark:0.24.0"
|
implementation "org.commonmark:commonmark:0.23.0"
|
||||||
implementation "org.commonmark:commonmark-ext-gfm-tables:0.24.0"
|
implementation "org.commonmark:commonmark-ext-gfm-tables:0.23.0"
|
||||||
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
||||||
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
|
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
|
||||||
implementation "com.fathzer:javaluator:3.0.5"
|
implementation "com.fathzer:javaluator:3.0.5"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 0.31.1
|
appVersion: 0.29.0
|
||||||
description: locally hosted web application that allows you to perform various operations
|
description: locally hosted web application that allows you to perform various operations
|
||||||
on PDF files
|
on PDF files
|
||||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
@@ -13,4 +13,4 @@ maintainers:
|
|||||||
name: stirling-pdf-chart
|
name: stirling-pdf-chart
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/Stirling-Tools/Stirling-PDF
|
- https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
version: 1.0.1
|
version: 1.0.0
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h1>My First Heading</h1>
|
|
||||||
|
|
||||||
<p>My first paragraph.</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
header
|
|
||||||
============
|
|
||||||
|
|
||||||
Header2
|
|
||||||
------------
|
|
||||||
text
|
|
||||||
|
|
||||||
text2
|
|
||||||
|
|
||||||
## **PDF Features**
|
|
||||||
|
|
||||||
### **Page Operations**
|
|
||||||
|
|
||||||
- View and modify PDFs - View multi page PDFs with custom viewing sorting and searching. Plus on page edit features like annotate, draw and adding text and images. (Using PDF.js with Joxit and Liberation.Liberation fonts)
|
|
||||||
- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages.
|
|
||||||
- Merge multiple PDFs together into a single resultant file.
|
|
||||||
Binary file not shown.
@@ -218,28 +218,6 @@ Feature: API Validation
|
|||||||
| .odt |
|
| .odt |
|
||||||
| .pptx |
|
| .pptx |
|
||||||
| .rtf |
|
| .rtf |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@calibre @positive @htmltopdf
|
|
||||||
Scenario: Convert HTML to PDF
|
|
||||||
Given I use an example file at "exampleFiles/example.html" as parameter "fileInput"
|
|
||||||
When I send the API request to the endpoint "/api/v1/convert/html/pdf"
|
|
||||||
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 ".pdf"
|
|
||||||
|
|
||||||
@calibre @positive @zippedhtmltopdf
|
|
||||||
Scenario: Convert zipped HTML to PDF
|
|
||||||
Given I use an example file at "exampleFiles/example_html.zip" as parameter "fileInput"
|
|
||||||
When I send the API request to the endpoint "/api/v1/convert/html/pdf"
|
|
||||||
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 ".pdf"
|
|
||||||
|
|
||||||
@calibre @positive @markdowntopdf
|
|
||||||
Scenario: Convert Markdown to PDF
|
|
||||||
Given I use an example file at "exampleFiles/example.md" as parameter "fileInput"
|
|
||||||
When I send the API request to the endpoint "/api/v1/convert/markdown/pdf"
|
|
||||||
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 ".pdf"
|
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ services:
|
|||||||
limits:
|
limits:
|
||||||
memory: 4G
|
memory: 4G
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 16
|
retries: 16
|
||||||
@@ -19,7 +19,7 @@ services:
|
|||||||
- /stirling/latest/logs:/logs:rw
|
- /stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DOCKER_ENABLE_SECURITY: "true"
|
DOCKER_ENABLE_SECURITY: "true"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
UMASK: "022"
|
UMASK: "022"
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Check if a key was provided
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
echo "Please provide a key to remove."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
key_to_remove="$1"
|
|
||||||
|
|
||||||
for file in ../src/main/resources/messages_*.properties; do
|
|
||||||
# If the key ends with a dot, remove all keys starting with it
|
|
||||||
if [[ "$key_to_remove" == *. ]]; then
|
|
||||||
sed -i "/^${key_to_remove//./\\.}/d" "$file"
|
|
||||||
else
|
|
||||||
# Otherwise, remove only the exact key match
|
|
||||||
sed -i "/^${key_to_remove//./\\.}=/d" "$file"
|
|
||||||
fi
|
|
||||||
echo "Updated $file"
|
|
||||||
done
|
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
package stirling.software.SPDF.EE;
|
package stirling.software.SPDF.EE;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Lazy
|
@Lazy
|
||||||
@Slf4j
|
|
||||||
public class EEAppConfig {
|
public class EEAppConfig {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EEAppConfig.class);
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Autowired private LicenseKeyChecker licenseKeyChecker;
|
@Autowired private LicenseKeyChecker licenseKeyChecker;
|
||||||
|
|
||||||
@Bean(name = "runningEE")
|
@Bean(name = "runningEE")
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.net.http.HttpClient;
|
|||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
@@ -13,22 +12,19 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.posthog.java.shaded.org.json.JSONObject;
|
import com.posthog.java.shaded.org.json.JSONObject;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
|
||||||
import stirling.software.SPDF.utils.GeneralUtils;
|
import stirling.software.SPDF.utils.GeneralUtils;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class KeygenLicenseVerifier {
|
public class KeygenLicenseVerifier {
|
||||||
private static final String ACCOUNT_ID = "e5430f69-e834-4ae4-befd-b602aae5f372";
|
private static final String ACCOUNT_ID = "e5430f69-e834-4ae4-befd-b602aae5f372";
|
||||||
|
private static final String PRODUCT_ID = "f9bb2423-62c9-4d39-8def-4fdc5aca751e";
|
||||||
private static final String BASE_URL = "https://api.keygen.sh/v1/accounts";
|
private static final String BASE_URL = "https://api.keygen.sh/v1/accounts";
|
||||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
// 23:26:20.344 [scheduling-1] INFO s.s.SPDF.EE.KeygenLicenseVerifier -
|
||||||
|
// validateLicenseResponse body:
|
||||||
@Autowired
|
// {"data":{"id":"808ed3c9-584b-46dd-8a80-c9217ef70915","type":"licenses","attributes":{"name":"userCounTest","key":"A7EW-KUPF-PRML-RRVL-HLMP-7THR-F7KE-XF4C","expiry":"2024-10-31T21:39:49.271Z","status":"ACTIVE","uses":0,"suspended":false,"scheme":null,"encrypted":false,"strict":true,"floating":true,"protected":true,"version":null,"maxMachines":1,"maxProcesses":null,"maxUsers":null,"maxCores":null,"maxUses":null,"requireHeartbeat":false,"requireCheckIn":false,"lastValidated":"2024-10-01T22:26:18.121Z","lastCheckIn":null,"nextCheckIn":null,"lastCheckOut":null,"metadata":{"users":10},"created":"2024-10-01T21:39:49.268Z","updated":"2024-10-01T21:39:49.268Z"},"relationships":{"account":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372"},"data":{"type":"accounts","id":"e5430f69-e834-4ae4-befd-b602aae5f372"}},"environment":{"links":{"related":null},"data":null},"product":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/product"},"data":{"type":"products","id":"f9bb2423-62c9-4d39-8def-4fdc5aca751e"}},"policy":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/policy"},"data":{"type":"policies","id":"04caef06-9ac2-4084-bf3c-bca4a0d29143"}},"group":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/group"},"data":null},"owner":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/owner"},"data":null},"users":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/users"},"meta":{"count":0}},"machines":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/machines"},"meta":{"cores":0,"count":0}},"tokens":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/tokens"}},"entitlements":{"links":{"related":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915/entitlements"}}},"links":{"self":"/v1/accounts/e5430f69-e834-4ae4-befd-b602aae5f372/licenses/808ed3c9-584b-46dd-8a80-c9217ef70915"}},"meta":{"ts":"2024-10-01T22:26:18.124Z","valid":false,"detail":"fingerprint is not activated (has no associated machines)","code":"NO_MACHINES","scope":{"fingerprint":"example-fingerprint"}}}
|
||||||
public KeygenLicenseVerifier(ApplicationProperties applicationProperties) {
|
|
||||||
this.applicationProperties = applicationProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean verifyLicense(String licenseKey) {
|
public boolean verifyLicense(String licenseKey) {
|
||||||
try {
|
try {
|
||||||
@@ -72,7 +68,7 @@ public class KeygenLicenseVerifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode validateLicense(String licenseKey, String machineFingerprint)
|
private static JsonNode validateLicense(String licenseKey, String machineFingerprint)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
HttpClient client = HttpClient.newHttpClient();
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
String requestBody =
|
String requestBody =
|
||||||
@@ -108,24 +104,14 @@ public class KeygenLicenseVerifier {
|
|||||||
log.debug("Validation detail: " + detail);
|
log.debug("Validation detail: " + detail);
|
||||||
log.debug("Validation code: " + code);
|
log.debug("Validation code: " + code);
|
||||||
|
|
||||||
int users =
|
|
||||||
jsonResponse
|
|
||||||
.path("data")
|
|
||||||
.path("attributes")
|
|
||||||
.path("metadata")
|
|
||||||
.path("users")
|
|
||||||
.asInt(0);
|
|
||||||
applicationProperties.getEnterpriseEdition().setMaxUsers(users);
|
|
||||||
log.info(applicationProperties.toString());
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.error("Error validating license. Status code: " + response.statusCode());
|
log.error("Error validating license. Status code: " + response.statusCode());
|
||||||
}
|
}
|
||||||
return jsonResponse;
|
return jsonResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean activateMachine(String licenseKey, String licenseId, String machineFingerprint)
|
private static boolean activateMachine(
|
||||||
throws Exception {
|
String licenseKey, String licenseId, String machineFingerprint) throws Exception {
|
||||||
HttpClient client = HttpClient.newHttpClient();
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
|
|
||||||
String hostname;
|
String hostname;
|
||||||
@@ -198,7 +184,7 @@ public class KeygenLicenseVerifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateMachineFingerprint() {
|
private static String generateMachineFingerprint() {
|
||||||
return GeneralUtils.generateMachineFingerprint();
|
return GeneralUtils.generateMachineFingerprint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class LicenseKeyChecker {
|
|||||||
|
|
||||||
private boolean enterpriseEnbaledResult = false;
|
private boolean enterpriseEnbaledResult = false;
|
||||||
|
|
||||||
|
// Inject your license service or configuration
|
||||||
@Autowired
|
@Autowired
|
||||||
public LicenseKeyChecker(
|
public LicenseKeyChecker(
|
||||||
KeygenLicenseVerifier licenseService, ApplicationProperties applicationProperties) {
|
KeygenLicenseVerifier licenseService, ApplicationProperties applicationProperties) {
|
||||||
|
|||||||
@@ -33,15 +33,11 @@ public class SPdfApplication {
|
|||||||
@Autowired private Environment env;
|
@Autowired private Environment env;
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
private static String baseUrlStatic;
|
|
||||||
private static String serverPortStatic;
|
private static String serverPortStatic;
|
||||||
|
|
||||||
@Value("${baseUrl:http://localhost}")
|
|
||||||
private String baseUrl;
|
|
||||||
|
|
||||||
@Value("${server.port:8080}")
|
@Value("${server.port:8080}")
|
||||||
public void setServerPortStatic(String port) {
|
public void setServerPortStatic(String port) {
|
||||||
if ("auto".equalsIgnoreCase(port)) {
|
if (port.equalsIgnoreCase("auto")) {
|
||||||
// Use Spring Boot's automatic port assignment (server.port=0)
|
// Use Spring Boot's automatic port assignment (server.port=0)
|
||||||
SPdfApplication.serverPortStatic =
|
SPdfApplication.serverPortStatic =
|
||||||
"0"; // This will let Spring Boot assign an available port
|
"0"; // This will let Spring Boot assign an available port
|
||||||
@@ -69,13 +65,12 @@ public class SPdfApplication {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
baseUrlStatic = this.baseUrl;
|
|
||||||
// Check if the BROWSER_OPEN environment variable is set to true
|
// Check if the BROWSER_OPEN environment variable is set to true
|
||||||
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
||||||
boolean browserOpen = browserOpenEnv != null && "true".equalsIgnoreCase(browserOpenEnv);
|
boolean browserOpen = browserOpenEnv != null && "true".equalsIgnoreCase(browserOpenEnv);
|
||||||
if (browserOpen) {
|
if (browserOpen) {
|
||||||
try {
|
try {
|
||||||
String url = baseUrl + ":" + getStaticPort();
|
String url = "http://localhost:" + getStaticPort();
|
||||||
|
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
Runtime rt = Runtime.getRuntime();
|
Runtime rt = Runtime.getRuntime();
|
||||||
@@ -83,9 +78,9 @@ public class SPdfApplication {
|
|||||||
// For Windows
|
// For Windows
|
||||||
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
|
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
|
||||||
} else if (os.contains("mac")) {
|
} else if (os.contains("mac")) {
|
||||||
SystemCommand.runCommand(rt, "open " + url);
|
rt.exec("open " + url);
|
||||||
} else if (os.contains("nix") || os.contains("nux")) {
|
} else if (os.contains("nix") || os.contains("nux")) {
|
||||||
SystemCommand.runCommand(rt, "xdg-open " + url);
|
rt.exec("xdg-open " + url);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Error opening browser: {}", e.getMessage());
|
logger.error("Error opening browser: {}", e.getMessage());
|
||||||
@@ -143,18 +138,10 @@ public class SPdfApplication {
|
|||||||
|
|
||||||
private static void printStartupLogs() {
|
private static void printStartupLogs() {
|
||||||
logger.info("Stirling-PDF Started.");
|
logger.info("Stirling-PDF Started.");
|
||||||
String url = baseUrlStatic + ":" + getStaticPort();
|
String url = "http://localhost:" + getStaticPort();
|
||||||
logger.info("Navigate to {}", url);
|
logger.info("Navigate to {}", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getStaticBaseUrl() {
|
|
||||||
return baseUrlStatic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNonStaticBaseUrl() {
|
|
||||||
return baseUrlStatic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getStaticPort() {
|
public static String getStaticPort() {
|
||||||
return serverPortStatic;
|
return serverPortStatic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@@ -163,14 +162,12 @@ public class AppConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "analyticsPrompt")
|
@Bean(name = "analyticsPrompt")
|
||||||
@Scope("request")
|
|
||||||
public boolean analyticsPrompt() {
|
public boolean analyticsPrompt() {
|
||||||
return applicationProperties.getSystem().getEnableAnalytics() == null
|
return applicationProperties.getSystem().getEnableAnalytics() == null
|
||||||
|| "undefined".equals(applicationProperties.getSystem().getEnableAnalytics());
|
|| "undefined".equals(applicationProperties.getSystem().getEnableAnalytics());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "analyticsEnabled")
|
@Bean(name = "analyticsEnabled")
|
||||||
@Scope("request")
|
|
||||||
public boolean analyticsEnabled() {
|
public boolean analyticsEnabled() {
|
||||||
if (applicationProperties.getEnterpriseEdition().isEnabled()) return true;
|
if (applicationProperties.getEnterpriseEdition().isEnabled()) return true;
|
||||||
return applicationProperties.getSystem().getEnableAnalytics() != null
|
return applicationProperties.getSystem().getEnableAnalytics() != null
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -43,7 +42,7 @@ public class EndpointConfiguration {
|
|||||||
|
|
||||||
public void disableEndpoint(String endpoint) {
|
public void disableEndpoint(String endpoint) {
|
||||||
if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
||||||
logger.debug("Disabling {}", endpoint);
|
logger.info("Disabling {}", endpoint);
|
||||||
endpointStatuses.put(endpoint, false);
|
endpointStatuses.put(endpoint, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,23 +76,6 @@ public class EndpointConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logDisabledEndpointsSummary() {
|
|
||||||
List<String> disabledList =
|
|
||||||
endpointStatuses.entrySet().stream()
|
|
||||||
.filter(entry -> !entry.getValue()) // only get disabled endpoints (value
|
|
||||||
// is false)
|
|
||||||
.map(Map.Entry::getKey)
|
|
||||||
.sorted()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (!disabledList.isEmpty()) {
|
|
||||||
logger.info(
|
|
||||||
"Total disabled endpoints: {}. Disabled endpoints: {}",
|
|
||||||
disabledList.size(),
|
|
||||||
String.join(", ", disabledList));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
// Adding endpoints to "PageOps" group
|
// Adding endpoints to "PageOps" group
|
||||||
addEndpointToGroup("PageOps", "remove-pages");
|
addEndpointToGroup("PageOps", "remove-pages");
|
||||||
@@ -181,12 +163,14 @@ public class EndpointConfiguration {
|
|||||||
|
|
||||||
// python
|
// python
|
||||||
addEndpointToGroup("Python", "extract-image-scans");
|
addEndpointToGroup("Python", "extract-image-scans");
|
||||||
|
addEndpointToGroup("Python", REMOVE_BLANKS);
|
||||||
addEndpointToGroup("Python", "html-to-pdf");
|
addEndpointToGroup("Python", "html-to-pdf");
|
||||||
addEndpointToGroup("Python", "url-to-pdf");
|
addEndpointToGroup("Python", "url-to-pdf");
|
||||||
addEndpointToGroup("Python", "pdf-to-img");
|
addEndpointToGroup("Python", "pdf-to-img");
|
||||||
|
|
||||||
// openCV
|
// openCV
|
||||||
addEndpointToGroup("OpenCV", "extract-image-scans");
|
addEndpointToGroup("OpenCV", "extract-image-scans");
|
||||||
|
addEndpointToGroup("OpenCV", REMOVE_BLANKS);
|
||||||
|
|
||||||
// LibreOffice
|
// LibreOffice
|
||||||
addEndpointToGroup("LibreOffice", "repair");
|
addEndpointToGroup("LibreOffice", "repair");
|
||||||
@@ -246,17 +230,6 @@ public class EndpointConfiguration {
|
|||||||
addEndpointToGroup("Javascript", "sign");
|
addEndpointToGroup("Javascript", "sign");
|
||||||
addEndpointToGroup("Javascript", "compare");
|
addEndpointToGroup("Javascript", "compare");
|
||||||
addEndpointToGroup("Javascript", "adjust-contrast");
|
addEndpointToGroup("Javascript", "adjust-contrast");
|
||||||
|
|
||||||
// Ghostscript dependent endpoints
|
|
||||||
addEndpointToGroup("Ghostscript", "compress-pdf");
|
|
||||||
addEndpointToGroup("Ghostscript", "pdf-to-pdfa");
|
|
||||||
|
|
||||||
// Weasyprint dependent endpoints
|
|
||||||
addEndpointToGroup("Weasyprint", "html-to-pdf");
|
|
||||||
addEndpointToGroup("Weasyprint", "url-to-pdf");
|
|
||||||
|
|
||||||
// Pdftohtml dependent endpoints
|
|
||||||
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processEnvironmentConfigs() {
|
private void processEnvironmentConfigs() {
|
||||||
@@ -278,9 +251,5 @@ public class EndpointConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getEndpointsForGroup(String group) {
|
|
||||||
return endpointGroups.getOrDefault(group, new HashSet<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String REMOVE_BLANKS = "remove-blanks";
|
private static final String REMOVE_BLANKS = "remove-blanks";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
package stirling.software.SPDF.config;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@Slf4j
|
|
||||||
public class ExternalAppDepConfig {
|
|
||||||
@Autowired private EndpointConfiguration endpointConfiguration;
|
|
||||||
|
|
||||||
private boolean isCommandAvailable(String command) {
|
|
||||||
try {
|
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
|
||||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
|
||||||
processBuilder.command("where", command);
|
|
||||||
} else {
|
|
||||||
processBuilder.command("which", command);
|
|
||||||
}
|
|
||||||
Process process = processBuilder.start();
|
|
||||||
int exitCode = process.waitFor();
|
|
||||||
return exitCode == 0;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.debug("Error checking for command {}: {}", command, e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<String, List<String>> commandToGroupMapping =
|
|
||||||
new HashMap<>() {
|
|
||||||
{
|
|
||||||
put("gs", List.of("Ghostscript"));
|
|
||||||
put("soffice", List.of("LibreOffice"));
|
|
||||||
put("ocrmypdf", List.of("OCRmyPDF"));
|
|
||||||
put("weasyprint", List.of("Weasyprint"));
|
|
||||||
put("pdftohtml", List.of("Pdftohtml"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private List<String> getAffectedFeatures(String group) {
|
|
||||||
return endpointConfiguration.getEndpointsForGroup(group).stream()
|
|
||||||
.map(endpoint -> formatEndpointAsFeature(endpoint))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String formatEndpointAsFeature(String endpoint) {
|
|
||||||
// First replace common terms
|
|
||||||
String feature = endpoint.replace("-", " ").replace("pdf", "PDF").replace("img", "image");
|
|
||||||
|
|
||||||
// Split into words and capitalize each word
|
|
||||||
return Arrays.stream(feature.split("\\s+"))
|
|
||||||
.map(word -> capitalizeWord(word))
|
|
||||||
.collect(Collectors.joining(" "));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String capitalizeWord(String word) {
|
|
||||||
if (word.isEmpty()) {
|
|
||||||
return word;
|
|
||||||
}
|
|
||||||
if ("pdf".equalsIgnoreCase(word)) {
|
|
||||||
return "PDF";
|
|
||||||
}
|
|
||||||
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDependencyAndDisableGroup(String command) {
|
|
||||||
boolean isAvailable = isCommandAvailable(command);
|
|
||||||
if (!isAvailable) {
|
|
||||||
List<String> affectedGroups = commandToGroupMapping.get(command);
|
|
||||||
|
|
||||||
if (affectedGroups != null) {
|
|
||||||
for (String group : affectedGroups) {
|
|
||||||
List<String> affectedFeatures = getAffectedFeatures(group);
|
|
||||||
endpointConfiguration.disableGroup(group);
|
|
||||||
log.warn(
|
|
||||||
"Missing dependency: {} - Disabling group: {} (Affected features: {})",
|
|
||||||
command,
|
|
||||||
group,
|
|
||||||
affectedFeatures != null && !affectedFeatures.isEmpty()
|
|
||||||
? String.join(", ", affectedFeatures)
|
|
||||||
: "unknown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void checkDependencies() {
|
|
||||||
|
|
||||||
// Check core dependencies
|
|
||||||
checkDependencyAndDisableGroup("gs");
|
|
||||||
checkDependencyAndDisableGroup("soffice");
|
|
||||||
checkDependencyAndDisableGroup("ocrmypdf");
|
|
||||||
checkDependencyAndDisableGroup("weasyprint");
|
|
||||||
checkDependencyAndDisableGroup("pdftohtml");
|
|
||||||
|
|
||||||
// Special handling for Python/OpenCV dependencies
|
|
||||||
boolean pythonAvailable = isCommandAvailable("python3") || isCommandAvailable("python");
|
|
||||||
if (!pythonAvailable) {
|
|
||||||
List<String> pythonFeatures = getAffectedFeatures("Python");
|
|
||||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
|
||||||
|
|
||||||
endpointConfiguration.disableGroup("Python");
|
|
||||||
endpointConfiguration.disableGroup("OpenCV");
|
|
||||||
log.warn(
|
|
||||||
"Missing dependency: Python - Disabling Python features: {} and OpenCV features: {}",
|
|
||||||
String.join(", ", pythonFeatures),
|
|
||||||
String.join(", ", openCVFeatures));
|
|
||||||
} else {
|
|
||||||
// If Python is available, check for OpenCV
|
|
||||||
try {
|
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
|
||||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
|
||||||
processBuilder.command("python", "-c", "import cv2");
|
|
||||||
} else {
|
|
||||||
processBuilder.command("python3", "-c", "import cv2");
|
|
||||||
}
|
|
||||||
Process process = processBuilder.start();
|
|
||||||
int exitCode = process.waitFor();
|
|
||||||
if (exitCode != 0) {
|
|
||||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
|
||||||
endpointConfiguration.disableGroup("OpenCV");
|
|
||||||
log.warn(
|
|
||||||
"OpenCV not available in Python - Disabling OpenCV features: {}",
|
|
||||||
String.join(", ", openCVFeatures));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
|
||||||
endpointConfiguration.disableGroup("OpenCV");
|
|
||||||
log.warn(
|
|
||||||
"Error checking OpenCV: {} - Disabling OpenCV features: {}",
|
|
||||||
e.getMessage(),
|
|
||||||
String.join(", ", openCVFeatures));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endpointConfiguration.logDisabledEndpointsSummary();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,8 +8,6 @@ import org.springframework.core.Ordered;
|
|||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import io.micrometer.common.util.StringUtils;
|
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
@@ -41,23 +39,4 @@ public class InitialSetup {
|
|||||||
applicationProperties.getAutomaticallyGenerated().setKey(secretKey);
|
applicationProperties.getAutomaticallyGenerated().setKey(secretKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void initLegalUrls() throws IOException {
|
|
||||||
// Initialize Terms and Conditions
|
|
||||||
String termsUrl = applicationProperties.getLegal().getTermsAndConditions();
|
|
||||||
if (StringUtils.isEmpty(termsUrl)) {
|
|
||||||
String defaultTermsUrl = "https://www.stirlingpdf.com/terms-and-conditions";
|
|
||||||
GeneralUtils.saveKeyToConfig("legal.termsAndConditions", defaultTermsUrl);
|
|
||||||
applicationProperties.getLegal().setTermsAndConditions(defaultTermsUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize Privacy Policy
|
|
||||||
String privacyUrl = applicationProperties.getLegal().getPrivacyPolicy();
|
|
||||||
if (StringUtils.isEmpty(privacyUrl)) {
|
|
||||||
String defaultPrivacyUrl = "https://www.stirlingpdf.com/privacy-policy";
|
|
||||||
GeneralUtils.saveKeyToConfig("legal.privacyPolicy", defaultPrivacyUrl);
|
|
||||||
applicationProperties.getLegal().setPrivacyPolicy(defaultPrivacyUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,237 +1,27 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
|
||||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||||
|
|
||||||
import com.coveo.saml.SamlClient;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.SPdfApplication;
|
|
||||||
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
|
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
|
||||||
import stirling.software.SPDF.model.Provider;
|
|
||||||
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
|
|
||||||
import stirling.software.SPDF.utils.UrlUtils;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLogoutSuccess(
|
public void onLogoutSuccess(
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
|
|
||||||
if (!response.isCommitted()) {
|
if (request.getParameter("userIsDisabled") != null) {
|
||||||
// Handle user logout due to disabled account
|
getRedirectStrategy()
|
||||||
if (request.getParameter("userIsDisabled") != null) {
|
.sendRedirect(request, response, "/login?erroroauth=userIsDisabled");
|
||||||
response.sendRedirect(
|
return;
|
||||||
request.getContextPath() + "/login?erroroauth=userIsDisabled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Handle OAuth2 authentication error
|
|
||||||
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
|
||||||
response.sendRedirect(
|
|
||||||
request.getContextPath() + "/login?erroroauth=userAlreadyExistsWeb");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (authentication != null) {
|
|
||||||
// Handle SAML2 logout redirection
|
|
||||||
if (authentication instanceof Saml2Authentication) {
|
|
||||||
getRedirect_saml2(request, response, authentication);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Handle OAuth2 logout redirection
|
|
||||||
else if (authentication instanceof OAuth2AuthenticationToken) {
|
|
||||||
getRedirect_oauth2(request, response, authentication);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Handle Username/Password logout
|
|
||||||
else if (authentication instanceof UsernamePasswordAuthenticationToken) {
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Handle unknown authentication types
|
|
||||||
else {
|
|
||||||
log.error(
|
|
||||||
"authentication class unknown: "
|
|
||||||
+ authentication.getClass().getSimpleName());
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Redirect to login page after logout
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect for SAML2 authentication logout
|
|
||||||
private void getRedirect_saml2(
|
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
|
|
||||||
String registrationId = samlConf.getRegistrationId();
|
|
||||||
|
|
||||||
Saml2Authentication samlAuthentication = (Saml2Authentication) authentication;
|
|
||||||
CustomSaml2AuthenticatedPrincipal principal =
|
|
||||||
(CustomSaml2AuthenticatedPrincipal) samlAuthentication.getPrincipal();
|
|
||||||
|
|
||||||
String nameIdValue = principal.getName();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Read certificate from the resource
|
|
||||||
Resource certificateResource = samlConf.getSpCert();
|
|
||||||
X509Certificate certificate = CertificateUtils.readCertificate(certificateResource);
|
|
||||||
|
|
||||||
List<X509Certificate> certificates = new ArrayList<>();
|
|
||||||
certificates.add(certificate);
|
|
||||||
|
|
||||||
// Construct URLs required for SAML configuration
|
|
||||||
String serverUrl =
|
|
||||||
SPdfApplication.getStaticBaseUrl() + ":" + SPdfApplication.getStaticPort();
|
|
||||||
|
|
||||||
String relyingPartyIdentifier =
|
|
||||||
serverUrl + "/saml2/service-provider-metadata/" + registrationId;
|
|
||||||
|
|
||||||
String assertionConsumerServiceUrl = serverUrl + "/login/saml2/sso/" + registrationId;
|
|
||||||
|
|
||||||
String idpUrl = samlConf.getIdpSingleLogoutUrl();
|
|
||||||
|
|
||||||
String idpIssuer = samlConf.getIdpIssuer();
|
|
||||||
|
|
||||||
// Create SamlClient instance for SAML logout
|
|
||||||
SamlClient samlClient =
|
|
||||||
new SamlClient(
|
|
||||||
relyingPartyIdentifier,
|
|
||||||
assertionConsumerServiceUrl,
|
|
||||||
idpUrl,
|
|
||||||
idpIssuer,
|
|
||||||
certificates,
|
|
||||||
SamlClient.SamlIdpBinding.POST);
|
|
||||||
|
|
||||||
// Read private key for service provider
|
|
||||||
Resource privateKeyResource = samlConf.getPrivateKey();
|
|
||||||
RSAPrivateKey privateKey = CertificateUtils.readPrivateKey(privateKeyResource);
|
|
||||||
|
|
||||||
// Set service provider keys for the SamlClient
|
|
||||||
samlClient.setSPKeys(certificate, privateKey);
|
|
||||||
|
|
||||||
// Redirect to identity provider for logout
|
|
||||||
samlClient.redirectToIdentityProvider(response, null, nameIdValue);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(nameIdValue, e);
|
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect for OAuth2 authentication logout
|
|
||||||
private void getRedirect_oauth2(
|
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
|
||||||
throws IOException {
|
|
||||||
String param = "logout=true";
|
|
||||||
String registrationId = null;
|
|
||||||
String issuer = null;
|
|
||||||
String clientId = null;
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
|
|
||||||
if (authentication instanceof OAuth2AuthenticationToken) {
|
|
||||||
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
|
|
||||||
registrationId = oauthToken.getAuthorizedClientRegistrationId();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Get OAuth2 provider details from configuration
|
|
||||||
Provider provider = oauth.getClient().get(registrationId);
|
|
||||||
issuer = provider.getIssuer();
|
|
||||||
clientId = provider.getClientId();
|
|
||||||
} catch (UnsupportedProviderException e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
registrationId = oauth.getProvider() != null ? oauth.getProvider() : "";
|
|
||||||
issuer = oauth.getIssuer();
|
|
||||||
clientId = oauth.getClientId();
|
|
||||||
}
|
|
||||||
String errorMessage = "";
|
|
||||||
// Handle different error scenarios during logout
|
|
||||||
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
|
||||||
param = "erroroauth=oauth2AuthenticationErrorWeb";
|
|
||||||
} else if ((errorMessage = request.getParameter("error")) != null) {
|
|
||||||
param = "error=" + sanitizeInput(errorMessage);
|
|
||||||
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
|
|
||||||
param = "erroroauth=" + sanitizeInput(errorMessage);
|
|
||||||
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
|
|
||||||
param = "error=oauth2AutoCreateDisabled";
|
|
||||||
} else if (request.getParameter("oauth2_admin_blocked_user") != null) {
|
|
||||||
param = "erroroauth=oauth2_admin_blocked_user";
|
|
||||||
} else if (request.getParameter("userIsDisabled") != null) {
|
|
||||||
param = "erroroauth=userIsDisabled";
|
|
||||||
} else if (request.getParameter("badcredentials") != null) {
|
|
||||||
param = "error=badcredentials";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String redirect_url = UrlUtils.getOrigin(request) + "/login?" + param;
|
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
|
||||||
|
|
||||||
// Redirect based on OAuth2 provider
|
|
||||||
switch (registrationId.toLowerCase()) {
|
|
||||||
case "keycloak":
|
|
||||||
// Add Keycloak specific logout URL if needed
|
|
||||||
String logoutUrl =
|
|
||||||
issuer
|
|
||||||
+ "/protocol/openid-connect/logout"
|
|
||||||
+ "?client_id="
|
|
||||||
+ clientId
|
|
||||||
+ "&post_logout_redirect_uri="
|
|
||||||
+ response.encodeRedirectURL(redirect_url);
|
|
||||||
log.info("Redirecting to Keycloak logout URL: " + logoutUrl);
|
|
||||||
response.sendRedirect(logoutUrl);
|
|
||||||
break;
|
|
||||||
case "github":
|
|
||||||
// Add GitHub specific logout URL if needed
|
|
||||||
String githubLogoutUrl = "https://github.com/logout";
|
|
||||||
log.info("Redirecting to GitHub logout URL: " + githubLogoutUrl);
|
|
||||||
response.sendRedirect(githubLogoutUrl);
|
|
||||||
break;
|
|
||||||
case "google":
|
|
||||||
// Add Google specific logout URL if needed
|
|
||||||
// String googleLogoutUrl =
|
|
||||||
// "https://accounts.google.com/Logout?continue=https://appengine.google.com/_ah/logout?continue="
|
|
||||||
// + response.encodeRedirectURL(redirect_url);
|
|
||||||
log.info("Google does not have a specific logout URL");
|
|
||||||
// log.info("Redirecting to Google logout URL: " + googleLogoutUrl);
|
|
||||||
// response.sendRedirect(googleLogoutUrl);
|
|
||||||
// break;
|
|
||||||
default:
|
|
||||||
String defaultRedirectUrl = request.getContextPath() + "/login?" + param;
|
|
||||||
log.info("Redirecting to default logout URL: " + defaultRedirectUrl);
|
|
||||||
response.sendRedirect(defaultRedirectUrl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanitize input to avoid potential security vulnerabilities
|
|
||||||
private String sanitizeInput(String input) {
|
|
||||||
return input.replaceAll("[^a-zA-Z0-9 ]", "");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +1,43 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
|
|
||||||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
|
||||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
|
||||||
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
|
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
|
||||||
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
|
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||||
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
|
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
|
||||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
|
||||||
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
||||||
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
|
import stirling.software.SPDF.config.security.saml.ConvertResponseToAuthentication;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationFailureHandler;
|
import stirling.software.SPDF.config.security.saml.CustomSAMLAuthenticationFailureHandler;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationSuccessHandler;
|
import stirling.software.SPDF.config.security.saml.CustomSAMLAuthenticationSuccessHandler;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2ResponseAuthenticationConverter;
|
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
|
||||||
import stirling.software.SPDF.model.User;
|
|
||||||
import stirling.software.SPDF.model.provider.GithubProvider;
|
|
||||||
import stirling.software.SPDF.model.provider.GoogleProvider;
|
|
||||||
import stirling.software.SPDF.model.provider.KeycloakProvider;
|
|
||||||
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -68,6 +48,12 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
@Autowired private CustomUserDetailsService userDetailsService;
|
@Autowired private CustomUserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private GrantedAuthoritiesMapper userAuthoritiesMapper;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
@@ -88,50 +74,16 @@ public class SecurityConfiguration {
|
|||||||
@Autowired private FirstLoginFilter firstLoginFilter;
|
@Autowired private FirstLoginFilter firstLoginFilter;
|
||||||
@Autowired private SessionPersistentRegistry sessionRegistry;
|
@Autowired private SessionPersistentRegistry sessionRegistry;
|
||||||
|
|
||||||
|
@Autowired private ConvertResponseToAuthentication convertResponseToAuthentication;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http.authenticationManager(authenticationManager(http));
|
||||||
|
|
||||||
if (loginEnabledValue) {
|
if (loginEnabledValue) {
|
||||||
http.addFilterBefore(
|
http.addFilterBefore(
|
||||||
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
http.csrf(csrf -> csrf.disable());
|
||||||
http.csrf(csrf -> csrf.disable());
|
|
||||||
} else {
|
|
||||||
CookieCsrfTokenRepository cookieRepo =
|
|
||||||
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
|
||||||
CsrfTokenRequestAttributeHandler requestHandler =
|
|
||||||
new CsrfTokenRequestAttributeHandler();
|
|
||||||
requestHandler.setCsrfRequestAttributeName(null);
|
|
||||||
http.csrf(
|
|
||||||
csrf ->
|
|
||||||
csrf.ignoringRequestMatchers(
|
|
||||||
request -> {
|
|
||||||
String apiKey = request.getHeader("X-API-Key");
|
|
||||||
|
|
||||||
// If there's no API key, don't ignore CSRF
|
|
||||||
// (return false)
|
|
||||||
if (apiKey == null || apiKey.trim().isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate API key using existing UserService
|
|
||||||
try {
|
|
||||||
Optional<User> user =
|
|
||||||
userService.getUserByApiKey(apiKey);
|
|
||||||
// If API key is valid, ignore CSRF (return
|
|
||||||
// true)
|
|
||||||
// If API key is invalid, don't ignore CSRF
|
|
||||||
// (return false)
|
|
||||||
return user.isPresent();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// If there's any error validating the API
|
|
||||||
// key, don't ignore CSRF
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.csrfTokenRepository(cookieRepo)
|
|
||||||
.csrfTokenRequestHandler(requestHandler));
|
|
||||||
}
|
|
||||||
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||||
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
http.sessionManagement(
|
http.sessionManagement(
|
||||||
@@ -143,371 +95,165 @@ public class SecurityConfiguration {
|
|||||||
.sessionRegistry(sessionRegistry)
|
.sessionRegistry(sessionRegistry)
|
||||||
.expiredUrl("/login?logout=true"));
|
.expiredUrl("/login?logout=true"));
|
||||||
|
|
||||||
http.authenticationProvider(daoAuthenticationProvider());
|
http.formLogin(
|
||||||
http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()));
|
formLogin ->
|
||||||
http.logout(
|
formLogin
|
||||||
logout ->
|
.loginPage("/login")
|
||||||
logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
.successHandler(
|
||||||
.logoutSuccessHandler(
|
new CustomAuthenticationSuccessHandler(
|
||||||
new CustomLogoutSuccessHandler(applicationProperties))
|
loginAttemptService, userService))
|
||||||
.clearAuthentication(true)
|
.defaultSuccessUrl("/")
|
||||||
.invalidateHttpSession(true) // Invalidate session
|
.failureHandler(
|
||||||
.deleteCookies("JSESSIONID", "remember-me"));
|
new CustomAuthenticationFailureHandler(
|
||||||
http.rememberMe(
|
loginAttemptService, userService))
|
||||||
rememberMeConfigurer ->
|
.permitAll())
|
||||||
rememberMeConfigurer // Use the configurator directly
|
.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()))
|
||||||
.key("uniqueAndSecret")
|
.logout(
|
||||||
.tokenRepository(persistentTokenRepository())
|
logout ->
|
||||||
.tokenValiditySeconds(1209600) // 2 weeks
|
logout.logoutRequestMatcher(
|
||||||
);
|
new AntPathRequestMatcher("/logout"))
|
||||||
http.authorizeHttpRequests(
|
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
|
||||||
authz ->
|
.invalidateHttpSession(true) // Invalidate session
|
||||||
authz.requestMatchers(
|
.deleteCookies("JSESSIONID", "remember-me"))
|
||||||
req -> {
|
.rememberMe(
|
||||||
String uri = req.getRequestURI();
|
rememberMeConfigurer ->
|
||||||
String contextPath = req.getContextPath();
|
rememberMeConfigurer // Use the configurator directly
|
||||||
|
.key("uniqueAndSecret")
|
||||||
|
.tokenRepository(persistentTokenRepository())
|
||||||
|
.tokenValiditySeconds(1209600) // 2 weeks
|
||||||
|
)
|
||||||
|
.authorizeHttpRequests(
|
||||||
|
authz ->
|
||||||
|
authz.requestMatchers(
|
||||||
|
req -> {
|
||||||
|
String uri = req.getRequestURI();
|
||||||
|
String contextPath = req.getContextPath();
|
||||||
|
|
||||||
// Remove the context path from the URI
|
// Remove the context path from the URI
|
||||||
String trimmedUri =
|
String trimmedUri =
|
||||||
uri.startsWith(contextPath)
|
uri.startsWith(contextPath)
|
||||||
? uri.substring(
|
? uri.substring(
|
||||||
contextPath.length())
|
contextPath
|
||||||
: uri;
|
.length())
|
||||||
|
: uri;
|
||||||
|
|
||||||
return trimmedUri.startsWith("/login")
|
return trimmedUri.startsWith("/login")
|
||||||
|| trimmedUri.startsWith("/oauth")
|
|| trimmedUri.startsWith("/oauth")
|
||||||
|| trimmedUri.startsWith("/saml2")
|
|| trimmedUri.startsWith("/saml2")
|
||||||
|| trimmedUri.endsWith(".svg")
|
|| trimmedUri.endsWith(".svg")
|
||||||
|| trimmedUri.startsWith("/register")
|
|| trimmedUri.startsWith(
|
||||||
|| trimmedUri.startsWith("/error")
|
"/register")
|
||||||
|| trimmedUri.startsWith("/images/")
|
|| trimmedUri.startsWith("/error")
|
||||||
|| trimmedUri.startsWith("/public/")
|
|| trimmedUri.startsWith("/images/")
|
||||||
|| trimmedUri.startsWith("/css/")
|
|| trimmedUri.startsWith("/public/")
|
||||||
|| trimmedUri.startsWith("/fonts/")
|
|| trimmedUri.startsWith("/css/")
|
||||||
|| trimmedUri.startsWith("/js/")
|
|| trimmedUri.startsWith("/fonts/")
|
||||||
|| trimmedUri.startsWith(
|
|| trimmedUri.startsWith("/js/")
|
||||||
"/api/v1/info/status");
|
|| trimmedUri.startsWith(
|
||||||
})
|
"/api/v1/info/status");
|
||||||
.permitAll()
|
})
|
||||||
.anyRequest()
|
.permitAll()
|
||||||
.authenticated());
|
.anyRequest()
|
||||||
|
.authenticated());
|
||||||
// Handle User/Password Logins
|
|
||||||
if (applicationProperties.getSecurity().isUserPass()) {
|
|
||||||
http.formLogin(
|
|
||||||
formLogin ->
|
|
||||||
formLogin
|
|
||||||
.loginPage("/login")
|
|
||||||
.successHandler(
|
|
||||||
new CustomAuthenticationSuccessHandler(
|
|
||||||
loginAttemptService, userService))
|
|
||||||
.failureHandler(
|
|
||||||
new CustomAuthenticationFailureHandler(
|
|
||||||
loginAttemptService, userService))
|
|
||||||
.defaultSuccessUrl("/")
|
|
||||||
.permitAll());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle OAUTH2 Logins
|
// Handle OAUTH2 Logins
|
||||||
if (applicationProperties.getSecurity().isOauth2Activ()) {
|
if (applicationProperties.getSecurity().getOauth2() != null
|
||||||
|
&& applicationProperties.getSecurity().getOauth2().getEnabled()
|
||||||
|
&& !applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getLoginMethod()
|
||||||
|
.equalsIgnoreCase("normal")) {
|
||||||
|
|
||||||
http.oauth2Login(
|
http.oauth2Login(
|
||||||
oauth2 ->
|
oauth2 ->
|
||||||
oauth2.loginPage("/oauth2")
|
oauth2.loginPage("/oauth2")
|
||||||
/*
|
/*
|
||||||
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
|
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
|
||||||
If user exists, login proceeds as usual. If user does not exist, then it is autocreated but only if 'OAUTH2AutoCreateUser'
|
If user exists, login proceeds as usual. If user does not exist, then it is autocreated but only if 'OAUTH2AutoCreateUser'
|
||||||
is set as true, else login fails with an error message advising the same.
|
is set as true, else login fails with an error message advising the same.
|
||||||
*/
|
*/
|
||||||
.successHandler(
|
|
||||||
new CustomOAuth2AuthenticationSuccessHandler(
|
|
||||||
loginAttemptService,
|
|
||||||
applicationProperties,
|
|
||||||
userService))
|
|
||||||
.failureHandler(
|
|
||||||
new CustomOAuth2AuthenticationFailureHandler())
|
|
||||||
// Add existing Authorities from the database
|
|
||||||
.userInfoEndpoint(
|
|
||||||
userInfoEndpoint ->
|
|
||||||
userInfoEndpoint
|
|
||||||
.oidcUserService(
|
|
||||||
new CustomOAuth2UserService(
|
|
||||||
applicationProperties,
|
|
||||||
userService,
|
|
||||||
loginAttemptService))
|
|
||||||
.userAuthoritiesMapper(
|
|
||||||
userAuthoritiesMapper()))
|
|
||||||
.permitAll());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle SAML
|
|
||||||
if (applicationProperties.getSecurity().isSaml2Activ()
|
|
||||||
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
|
|
||||||
http.authenticationProvider(samlAuthenticationProvider());
|
|
||||||
http.saml2Login(
|
|
||||||
saml2 ->
|
|
||||||
saml2.loginPage("/saml2")
|
|
||||||
.successHandler(
|
.successHandler(
|
||||||
new CustomSaml2AuthenticationSuccessHandler(
|
new CustomOAuth2AuthenticationSuccessHandler(
|
||||||
loginAttemptService,
|
loginAttemptService,
|
||||||
applicationProperties,
|
applicationProperties,
|
||||||
userService))
|
userService))
|
||||||
.failureHandler(
|
.failureHandler(
|
||||||
new CustomSaml2AuthenticationFailureHandler())
|
new CustomOAuth2AuthenticationFailureHandler())
|
||||||
.permitAll())
|
// Add existing Authorities from the database
|
||||||
|
.userInfoEndpoint(
|
||||||
|
userInfoEndpoint ->
|
||||||
|
userInfoEndpoint
|
||||||
|
.oidcUserService(
|
||||||
|
new CustomOAuth2UserService(
|
||||||
|
applicationProperties,
|
||||||
|
userService,
|
||||||
|
loginAttemptService))
|
||||||
|
.userAuthoritiesMapper(
|
||||||
|
userAuthoritiesMapper)))
|
||||||
|
.logout(
|
||||||
|
logout ->
|
||||||
|
logout.logoutSuccessHandler(
|
||||||
|
new CustomOAuth2LogoutSuccessHandler(
|
||||||
|
applicationProperties)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle SAML
|
||||||
|
if (applicationProperties.getSecurity().getSaml() != null
|
||||||
|
&& applicationProperties.getSecurity().getSaml().getEnabled()
|
||||||
|
&& !applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getLoginMethod()
|
||||||
|
.equalsIgnoreCase("normal")) {
|
||||||
|
http.saml2Login(
|
||||||
|
saml2 -> {
|
||||||
|
saml2.relyingPartyRegistrationRepository(
|
||||||
|
relyingPartyRegistrationRepository)
|
||||||
|
.successHandler(
|
||||||
|
new CustomSAMLAuthenticationSuccessHandler(
|
||||||
|
loginAttemptService,
|
||||||
|
userService,
|
||||||
|
applicationProperties))
|
||||||
|
.failureHandler(
|
||||||
|
new CustomSAMLAuthenticationFailureHandler());
|
||||||
|
})
|
||||||
|
.saml2Logout(withDefaults())
|
||||||
.addFilterBefore(
|
.addFilterBefore(
|
||||||
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
|
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
http.csrf(csrf -> csrf.disable())
|
||||||
http.csrf(csrf -> csrf.disable());
|
.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
||||||
} else {
|
|
||||||
CookieCsrfTokenRepository cookieRepo =
|
|
||||||
CookieCsrfTokenRepository.withHttpOnlyFalse();
|
|
||||||
CsrfTokenRequestAttributeHandler requestHandler =
|
|
||||||
new CsrfTokenRequestAttributeHandler();
|
|
||||||
requestHandler.setCsrfRequestAttributeName(null);
|
|
||||||
http.csrf(
|
|
||||||
csrf ->
|
|
||||||
csrf.csrfTokenRepository(cookieRepo)
|
|
||||||
.csrfTokenRequestHandler(requestHandler));
|
|
||||||
}
|
|
||||||
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
|
||||||
name = "security.saml2.enabled",
|
|
||||||
havingValue = "true",
|
|
||||||
matchIfMissing = false)
|
|
||||||
public AuthenticationProvider samlAuthenticationProvider() {
|
public AuthenticationProvider samlAuthenticationProvider() {
|
||||||
OpenSaml4AuthenticationProvider authenticationProvider =
|
OpenSaml4AuthenticationProvider authenticationProvider =
|
||||||
new OpenSaml4AuthenticationProvider();
|
new OpenSaml4AuthenticationProvider();
|
||||||
authenticationProvider.setResponseAuthenticationConverter(
|
authenticationProvider.setResponseAuthenticationConverter(convertResponseToAuthentication);
|
||||||
new CustomSaml2ResponseAuthenticationConverter(userService));
|
|
||||||
return authenticationProvider;
|
return authenticationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client Registration Repository for OAUTH2 OIDC Login
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
public AuthenticationProvider daoAuthenticationProvider() {
|
||||||
value = "security.oauth2.enabled",
|
|
||||||
havingValue = "true",
|
|
||||||
matchIfMissing = false)
|
|
||||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
|
||||||
List<ClientRegistration> registrations = new ArrayList<>();
|
|
||||||
|
|
||||||
githubClientRegistration().ifPresent(registrations::add);
|
|
||||||
oidcClientRegistration().ifPresent(registrations::add);
|
|
||||||
googleClientRegistration().ifPresent(registrations::add);
|
|
||||||
keycloakClientRegistration().ifPresent(registrations::add);
|
|
||||||
|
|
||||||
if (registrations.isEmpty()) {
|
|
||||||
log.error("At least one OAuth2 provider must be configured");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new InMemoryClientRegistrationRepository(registrations);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<ClientRegistration> googleClientRegistration() {
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
if (oauth == null || !oauth.getEnabled()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
Client client = oauth.getClient();
|
|
||||||
if (client == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
GoogleProvider google = client.getGoogle();
|
|
||||||
return google != null && google.isSettingsValid()
|
|
||||||
? Optional.of(
|
|
||||||
ClientRegistration.withRegistrationId(google.getName())
|
|
||||||
.clientId(google.getClientId())
|
|
||||||
.clientSecret(google.getClientSecret())
|
|
||||||
.scope(google.getScopes())
|
|
||||||
.authorizationUri(google.getAuthorizationuri())
|
|
||||||
.tokenUri(google.getTokenuri())
|
|
||||||
.userInfoUri(google.getUserinfouri())
|
|
||||||
.userNameAttributeName(google.getUseAsUsername())
|
|
||||||
.clientName(google.getClientName())
|
|
||||||
.redirectUri("{baseUrl}/login/oauth2/code/" + google.getName())
|
|
||||||
.authorizationGrantType(
|
|
||||||
org.springframework.security.oauth2.core
|
|
||||||
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
|
||||||
.build())
|
|
||||||
: Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<ClientRegistration> keycloakClientRegistration() {
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
if (oauth == null || !oauth.getEnabled()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
Client client = oauth.getClient();
|
|
||||||
if (client == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
KeycloakProvider keycloak = client.getKeycloak();
|
|
||||||
|
|
||||||
return keycloak != null && keycloak.isSettingsValid()
|
|
||||||
? Optional.of(
|
|
||||||
ClientRegistrations.fromIssuerLocation(keycloak.getIssuer())
|
|
||||||
.registrationId(keycloak.getName())
|
|
||||||
.clientId(keycloak.getClientId())
|
|
||||||
.clientSecret(keycloak.getClientSecret())
|
|
||||||
.scope(keycloak.getScopes())
|
|
||||||
.userNameAttributeName(keycloak.getUseAsUsername())
|
|
||||||
.clientName(keycloak.getClientName())
|
|
||||||
.build())
|
|
||||||
: Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<ClientRegistration> githubClientRegistration() {
|
|
||||||
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
if (oauth == null || !oauth.getEnabled()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
Client client = oauth.getClient();
|
|
||||||
if (client == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
GithubProvider github = client.getGithub();
|
|
||||||
return github != null && github.isSettingsValid()
|
|
||||||
? Optional.of(
|
|
||||||
ClientRegistration.withRegistrationId(github.getName())
|
|
||||||
.clientId(github.getClientId())
|
|
||||||
.clientSecret(github.getClientSecret())
|
|
||||||
.scope(github.getScopes())
|
|
||||||
.authorizationUri(github.getAuthorizationuri())
|
|
||||||
.tokenUri(github.getTokenuri())
|
|
||||||
.userInfoUri(github.getUserinfouri())
|
|
||||||
.userNameAttributeName(github.getUseAsUsername())
|
|
||||||
.clientName(github.getClientName())
|
|
||||||
.redirectUri("{baseUrl}/login/oauth2/code/" + github.getName())
|
|
||||||
.authorizationGrantType(
|
|
||||||
org.springframework.security.oauth2.core
|
|
||||||
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
|
||||||
.build())
|
|
||||||
: Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<ClientRegistration> oidcClientRegistration() {
|
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
|
||||||
if (oauth == null
|
|
||||||
|| oauth.getIssuer() == null
|
|
||||||
|| oauth.getIssuer().isEmpty()
|
|
||||||
|| oauth.getClientId() == null
|
|
||||||
|| oauth.getClientId().isEmpty()
|
|
||||||
|| oauth.getClientSecret() == null
|
|
||||||
|| oauth.getClientSecret().isEmpty()
|
|
||||||
|| oauth.getScopes() == null
|
|
||||||
|| oauth.getScopes().isEmpty()
|
|
||||||
|| oauth.getUseAsUsername() == null
|
|
||||||
|| oauth.getUseAsUsername().isEmpty()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
return Optional.of(
|
|
||||||
ClientRegistrations.fromIssuerLocation(oauth.getIssuer())
|
|
||||||
.registrationId("oidc")
|
|
||||||
.clientId(oauth.getClientId())
|
|
||||||
.clientSecret(oauth.getClientSecret())
|
|
||||||
.scope(oauth.getScopes())
|
|
||||||
.userNameAttributeName(oauth.getUseAsUsername())
|
|
||||||
.clientName("OIDC")
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnProperty(
|
|
||||||
name = "security.saml2.enabled",
|
|
||||||
havingValue = "true",
|
|
||||||
matchIfMissing = false)
|
|
||||||
public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exception {
|
|
||||||
|
|
||||||
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
|
|
||||||
|
|
||||||
Resource privateKeyResource = samlConf.getPrivateKey();
|
|
||||||
|
|
||||||
Resource certificateResource = samlConf.getSpCert();
|
|
||||||
|
|
||||||
Saml2X509Credential signingCredential =
|
|
||||||
new Saml2X509Credential(
|
|
||||||
CertificateUtils.readPrivateKey(privateKeyResource),
|
|
||||||
CertificateUtils.readCertificate(certificateResource),
|
|
||||||
Saml2X509CredentialType.SIGNING);
|
|
||||||
|
|
||||||
X509Certificate idpCert = CertificateUtils.readCertificate(samlConf.getidpCert());
|
|
||||||
|
|
||||||
Saml2X509Credential verificationCredential = Saml2X509Credential.verification(idpCert);
|
|
||||||
|
|
||||||
RelyingPartyRegistration rp =
|
|
||||||
RelyingPartyRegistration.withRegistrationId(samlConf.getRegistrationId())
|
|
||||||
.signingX509Credentials((c) -> c.add(signingCredential))
|
|
||||||
.assertingPartyDetails(
|
|
||||||
(details) ->
|
|
||||||
details.entityId(samlConf.getIdpIssuer())
|
|
||||||
.singleSignOnServiceLocation(
|
|
||||||
samlConf.getIdpSingleLoginUrl())
|
|
||||||
.verificationX509Credentials(
|
|
||||||
(c) -> c.add(verificationCredential))
|
|
||||||
.wantAuthnRequestsSigned(true))
|
|
||||||
.build();
|
|
||||||
return new InMemoryRelyingPartyRegistrationRepository(rp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DaoAuthenticationProvider daoAuthenticationProvider() {
|
|
||||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||||
provider.setUserDetailsService(userDetailsService);
|
provider.setUserDetailsService(userDetailsService); // UserDetailsService
|
||||||
provider.setPasswordEncoder(passwordEncoder());
|
provider.setPasswordEncoder(passwordEncoder()); // PasswordEncoder
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
This following function is to grant Authorities to the OAUTH2 user from the values stored in the database.
|
|
||||||
This is required for the internal; 'hasRole()' function to give out the correct role.
|
|
||||||
*/
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
|
||||||
value = "security.oauth2.enabled",
|
AuthenticationManagerBuilder authenticationManagerBuilder =
|
||||||
havingValue = "true",
|
http.getSharedObject(AuthenticationManagerBuilder.class);
|
||||||
matchIfMissing = false)
|
|
||||||
GrantedAuthoritiesMapper userAuthoritiesMapper() {
|
|
||||||
return (authorities) -> {
|
|
||||||
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
|
|
||||||
|
|
||||||
authorities.forEach(
|
authenticationManagerBuilder
|
||||||
authority -> {
|
.authenticationProvider(daoAuthenticationProvider()) // Benutzername/Passwort
|
||||||
// Add existing OAUTH2 Authorities
|
.authenticationProvider(samlAuthenticationProvider()); // SAML
|
||||||
mappedAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
|
|
||||||
|
|
||||||
// Add Authorities from database for existing user, if user is present.
|
return authenticationManagerBuilder.build();
|
||||||
if (authority instanceof OAuth2UserAuthority oauth2Auth) {
|
|
||||||
String useAsUsername =
|
|
||||||
applicationProperties
|
|
||||||
.getSecurity()
|
|
||||||
.getOauth2()
|
|
||||||
.getUseAsUsername();
|
|
||||||
Optional<User> userOpt =
|
|
||||||
userService.findByUsernameIgnoreCase(
|
|
||||||
(String) oauth2Auth.getAttributes().get(useAsUsername));
|
|
||||||
if (userOpt.isPresent()) {
|
|
||||||
User user = userOpt.get();
|
|
||||||
if (user != null) {
|
|
||||||
mappedAuthorities.add(
|
|
||||||
new SimpleGrantedAuthority(
|
|
||||||
userService.findRole(user).getAuthority()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return mappedAuthorities;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -526,13 +272,12 @@ public class SecurityConfiguration {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Only Dev test
|
// Only Dev test
|
||||||
// @Bean
|
@Bean
|
||||||
// public WebSecurityCustomizer webSecurityCustomizer() {
|
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||||
// return (web) ->
|
return (web) ->
|
||||||
// web.ignoring()
|
web.ignoring()
|
||||||
// .requestMatchers(
|
.requestMatchers(
|
||||||
// "/css/**", "/images/**", "/js/**", "/**.svg",
|
"/css/**", "/images/**", "/js/**", "/**.svg", "/pdfjs-legacy/**");
|
||||||
// "/pdfjs-legacy/**");
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import jakarta.servlet.FilterChain;
|
|||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
@@ -112,9 +111,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||||
response.getWriter()
|
response.getWriter()
|
||||||
.write(
|
.write(
|
||||||
"Authentication required. Please provide a X-API-KEY in request header.\n"
|
"Authentication required. Please provide a X-API-KEY in request header.\nThis is found in Settings -> Account Settings -> API Key\nAlternatively you can disable authentication if this is unexpected");
|
||||||
+ "This is found in Settings -> Account Settings -> API Key\n"
|
|
||||||
+ "Alternatively you can disable authentication if this is unexpected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,8 +124,6 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
username = ((UserDetails) principal).getUsername();
|
username = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
username = ((OAuth2User) principal).getName();
|
username = ((OAuth2User) principal).getName();
|
||||||
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
username = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
username = (String) principal;
|
username = (String) principal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
@@ -335,10 +334,6 @@ public class UserService implements UserServiceInterface {
|
|||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
OAuth2User oAuth2User = (OAuth2User) principal;
|
OAuth2User oAuth2User = (OAuth2User) principal;
|
||||||
usernameP = oAuth2User.getName();
|
usernameP = oAuth2User.getName();
|
||||||
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
CustomSaml2AuthenticatedPrincipal saml2User =
|
|
||||||
(CustomSaml2AuthenticatedPrincipal) principal;
|
|
||||||
usernameP = saml2User.getName();
|
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
usernameP = (String) principal;
|
usernameP = (String) principal;
|
||||||
}
|
}
|
||||||
@@ -358,9 +353,4 @@ public class UserService implements UserServiceInterface {
|
|||||||
return principal.toString();
|
return principal.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getTotalUsersCount() {
|
|
||||||
return userRepository.count();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ public class CustomOAuth2AuthenticationFailureHandler
|
|||||||
}
|
}
|
||||||
log.error("OAuth2 Authentication error: " + errorCode);
|
log.error("OAuth2 Authentication error: " + errorCode);
|
||||||
log.error("OAuth2AuthenticationException", exception);
|
log.error("OAuth2AuthenticationException", exception);
|
||||||
getRedirectStrategy().sendRedirect(request, response, "/login?erroroauth=" + errorCode);
|
getRedirectStrategy()
|
||||||
|
.sendRedirect(request, response, "/logout?erroroauth=" + errorCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.error("Unhandled authentication exception", exception);
|
log.error("Unhandled authentication exception", exception);
|
||||||
|
|||||||
@@ -75,11 +75,6 @@ public class CustomOAuth2AuthenticationSuccessHandler
|
|||||||
throw new LockedException(
|
throw new LockedException(
|
||||||
"Your account has been locked due to too many failed login attempts.");
|
"Your account has been locked due to too many failed login attempts.");
|
||||||
}
|
}
|
||||||
if (userService.isUserDisabled(username)) {
|
|
||||||
getRedirectStrategy()
|
|
||||||
.sendRedirect(request, response, "/logout?userIsDisabled=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (userService.usernameExistsIgnoreCase(username)
|
if (userService.usernameExistsIgnoreCase(username)
|
||||||
&& userService.hasPassword(username)
|
&& userService.hasPassword(username)
|
||||||
&& !userService.isAuthenticationTypeByUsername(
|
&& !userService.isAuthenticationTypeByUsername(
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package stirling.software.SPDF.config.security.oauth2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
|
import stirling.software.SPDF.model.Provider;
|
||||||
|
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
|
||||||
|
import stirling.software.SPDF.utils.UrlUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||||
|
|
||||||
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
public CustomOAuth2LogoutSuccessHandler(ApplicationProperties applicationProperties) {
|
||||||
|
this.applicationProperties = applicationProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLogoutSuccess(
|
||||||
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
String param = "logout=true";
|
||||||
|
String registrationId = null;
|
||||||
|
String issuer = null;
|
||||||
|
String clientId = null;
|
||||||
|
|
||||||
|
if (authentication == null) {
|
||||||
|
if (request.getParameter("userIsDisabled") != null) {
|
||||||
|
response.sendRedirect(
|
||||||
|
request.getContextPath() + "/login?erroroauth=userIsDisabled");
|
||||||
|
} else {
|
||||||
|
super.onLogoutSuccess(request, response, authentication);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
|
||||||
|
if (authentication instanceof OAuth2AuthenticationToken) {
|
||||||
|
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
|
||||||
|
registrationId = oauthToken.getAuthorizedClientRegistrationId();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Provider provider = oauth.getClient().get(registrationId);
|
||||||
|
issuer = provider.getIssuer();
|
||||||
|
clientId = provider.getClientId();
|
||||||
|
} catch (UnsupportedProviderException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
registrationId = oauth.getProvider() != null ? oauth.getProvider() : "";
|
||||||
|
issuer = oauth.getIssuer();
|
||||||
|
clientId = oauth.getClientId();
|
||||||
|
}
|
||||||
|
String errorMessage = "";
|
||||||
|
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
||||||
|
param = "erroroauth=oauth2AuthenticationErrorWeb";
|
||||||
|
} else if ((errorMessage = request.getParameter("error")) != null) {
|
||||||
|
param = "error=" + sanitizeInput(errorMessage);
|
||||||
|
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
|
||||||
|
param = "erroroauth=" + sanitizeInput(errorMessage);
|
||||||
|
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
|
||||||
|
param = "error=oauth2AutoCreateDisabled";
|
||||||
|
} else if (request.getParameter("oauth2_admin_blocked_user") != null) {
|
||||||
|
param = "erroroauth=oauth2_admin_blocked_user";
|
||||||
|
} else if (request.getParameter("userIsDisabled") != null) {
|
||||||
|
param = "erroroauth=userIsDisabled";
|
||||||
|
} else if (request.getParameter("badcredentials") != null) {
|
||||||
|
param = "error=badcredentials";
|
||||||
|
}
|
||||||
|
|
||||||
|
String redirect_url = UrlUtils.getOrigin(request) + "/login?" + param;
|
||||||
|
|
||||||
|
switch (registrationId.toLowerCase()) {
|
||||||
|
case "keycloak":
|
||||||
|
// Add Keycloak specific logout URL if needed
|
||||||
|
String logoutUrl =
|
||||||
|
issuer
|
||||||
|
+ "/protocol/openid-connect/logout"
|
||||||
|
+ "?client_id="
|
||||||
|
+ clientId
|
||||||
|
+ "&post_logout_redirect_uri="
|
||||||
|
+ response.encodeRedirectURL(redirect_url);
|
||||||
|
log.info("Redirecting to Keycloak logout URL: " + logoutUrl);
|
||||||
|
response.sendRedirect(logoutUrl);
|
||||||
|
break;
|
||||||
|
case "github":
|
||||||
|
// Add GitHub specific logout URL if needed
|
||||||
|
String githubLogoutUrl = "https://github.com/logout";
|
||||||
|
log.info("Redirecting to GitHub logout URL: " + githubLogoutUrl);
|
||||||
|
response.sendRedirect(githubLogoutUrl);
|
||||||
|
break;
|
||||||
|
case "google":
|
||||||
|
// Add Google specific logout URL if needed
|
||||||
|
// String googleLogoutUrl =
|
||||||
|
// "https://accounts.google.com/Logout?continue=https://appengine.google.com/_ah/logout?continue="
|
||||||
|
// + response.encodeRedirectURL(redirect_url);
|
||||||
|
log.info("Google does not have a specific logout URL");
|
||||||
|
// log.info("Redirecting to Google logout URL: " + googleLogoutUrl);
|
||||||
|
// response.sendRedirect(googleLogoutUrl);
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
String defaultRedirectUrl = request.getContextPath() + "/login?" + param;
|
||||||
|
log.info("Redirecting to default logout URL: " + defaultRedirectUrl);
|
||||||
|
response.sendRedirect(defaultRedirectUrl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sanitizeInput(String input) {
|
||||||
|
return input.replaceAll("[^a-zA-Z0-9 ]", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class ConvertResponseToAuthentication
|
||||||
|
implements Converter<ResponseToken, Saml2Authentication> {
|
||||||
|
|
||||||
|
private final Saml2AuthorityAttributeLookup saml2AuthorityAttributeLookup;
|
||||||
|
|
||||||
|
public ConvertResponseToAuthentication(
|
||||||
|
Saml2AuthorityAttributeLookup saml2AuthorityAttributeLookup) {
|
||||||
|
this.saml2AuthorityAttributeLookup = saml2AuthorityAttributeLookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Saml2Authentication convert(ResponseToken responseToken) {
|
||||||
|
final Assertion assertion =
|
||||||
|
CollectionUtils.firstElement(responseToken.getResponse().getAssertions());
|
||||||
|
final Map<String, List<Object>> attributes =
|
||||||
|
SamlAssertionUtils.getAssertionAttributes(assertion);
|
||||||
|
final String registrationId =
|
||||||
|
responseToken.getToken().getRelyingPartyRegistration().getRegistrationId();
|
||||||
|
final ScimSaml2AuthenticatedPrincipal principal =
|
||||||
|
new ScimSaml2AuthenticatedPrincipal(
|
||||||
|
assertion,
|
||||||
|
attributes,
|
||||||
|
saml2AuthorityAttributeLookup.getIdentityMappings(registrationId));
|
||||||
|
final Collection<? extends GrantedAuthority> assertionAuthorities =
|
||||||
|
getAssertionAuthorities(
|
||||||
|
attributes,
|
||||||
|
saml2AuthorityAttributeLookup.getAuthorityAttribute(registrationId));
|
||||||
|
return new Saml2Authentication(
|
||||||
|
principal, responseToken.getToken().getSaml2Response(), assertionAuthorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<? extends GrantedAuthority> getAssertionAuthorities(
|
||||||
|
final Map<String, List<Object>> attributes, final String authoritiesAttributeName) {
|
||||||
|
if (attributes == null || attributes.isEmpty()) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> groups = new ArrayList<>();
|
||||||
|
|
||||||
|
if (attributes.get(authoritiesAttributeName) != null) {
|
||||||
|
groups = new ArrayList<>(attributes.get(authoritiesAttributeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups.stream()
|
||||||
|
.filter(String.class::isInstance)
|
||||||
|
.map(String.class::cast)
|
||||||
|
.map(String::toLowerCase)
|
||||||
|
.map(SimpleGrantedAuthority::new)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||||
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CustomSAMLAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationFailure(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
AuthenticationException exception)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
|
||||||
|
if (exception instanceof BadCredentialsException) {
|
||||||
|
log.error("BadCredentialsException", exception);
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/login?error=badcredentials");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (exception instanceof DisabledException) {
|
||||||
|
log.error("User is deactivated: ", exception);
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/logout?userIsDisabled=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (exception instanceof LockedException) {
|
||||||
|
log.error("Account locked: ", exception);
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, "/logout?error=locked");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (exception instanceof Saml2AuthenticationException) {
|
||||||
|
log.error("SAML2 Authentication error: ", exception);
|
||||||
|
getRedirectStrategy()
|
||||||
|
.sendRedirect(request, response, "/logout?error=saml2AuthenticationError");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.error("Unhandled authentication exception", exception);
|
||||||
|
super.onAuthenticationFailure(request, response, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||||
|
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.config.security.LoginAttemptService;
|
||||||
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
|
import stirling.software.SPDF.utils.RequestUriUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CustomSAMLAuthenticationSuccessHandler
|
||||||
|
extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||||
|
|
||||||
|
private LoginAttemptService loginAttemptService;
|
||||||
|
private UserService userService;
|
||||||
|
private ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
public CustomSAMLAuthenticationSuccessHandler(
|
||||||
|
LoginAttemptService loginAttemptService,
|
||||||
|
UserService userService,
|
||||||
|
ApplicationProperties applicationProperties) {
|
||||||
|
this.loginAttemptService = loginAttemptService;
|
||||||
|
this.userService = userService;
|
||||||
|
this.applicationProperties = applicationProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSuccess(
|
||||||
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
|
||||||
|
Object principal = authentication.getPrincipal();
|
||||||
|
String username = "";
|
||||||
|
|
||||||
|
if (principal instanceof OAuth2User) {
|
||||||
|
OAuth2User oauthUser = (OAuth2User) principal;
|
||||||
|
username = oauthUser.getName();
|
||||||
|
} else if (principal instanceof UserDetails) {
|
||||||
|
UserDetails oauthUser = (UserDetails) principal;
|
||||||
|
username = oauthUser.getUsername();
|
||||||
|
} else if (principal instanceof ScimSaml2AuthenticatedPrincipal) {
|
||||||
|
ScimSaml2AuthenticatedPrincipal samlPrincipal =
|
||||||
|
(ScimSaml2AuthenticatedPrincipal) principal;
|
||||||
|
username = samlPrincipal.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the saved request
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
String contextPath = request.getContextPath();
|
||||||
|
SavedRequest savedRequest =
|
||||||
|
(session != null)
|
||||||
|
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (savedRequest != null
|
||||||
|
&& !RequestUriUtils.isStaticResource(contextPath, savedRequest.getRedirectUrl())) {
|
||||||
|
// Redirect to the original destination
|
||||||
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
|
} else {
|
||||||
|
OAUTH2 oAuth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
|
||||||
|
if (loginAttemptService.isBlocked(username)) {
|
||||||
|
if (session != null) {
|
||||||
|
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
||||||
|
}
|
||||||
|
throw new LockedException(
|
||||||
|
"Your account has been locked due to too many failed login attempts.");
|
||||||
|
}
|
||||||
|
if (userService.usernameExistsIgnoreCase(username)
|
||||||
|
&& userService.hasPassword(username)
|
||||||
|
&& !userService.isAuthenticationTypeByUsername(
|
||||||
|
username, AuthenticationType.OAUTH2)
|
||||||
|
&& oAuth.getAutoCreateUser()) {
|
||||||
|
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (oAuth.getBlockRegistration()
|
||||||
|
&& !userService.usernameExistsIgnoreCase(username)) {
|
||||||
|
response.sendRedirect(contextPath + "/logout?oauth2_admin_blocked_user=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (principal instanceof OAuth2User) {
|
||||||
|
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
|
||||||
|
}
|
||||||
|
response.sendRedirect(contextPath + "/");
|
||||||
|
return;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class SAMLLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLogoutSuccess(
|
||||||
|
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
|
||||||
|
String redirectUrl = determineTargetUrl(request, response, authentication);
|
||||||
|
|
||||||
|
if (response.isCommitted()) {
|
||||||
|
log.debug("Response has already been committed. Unable to redirect to " + redirectUrl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRedirectStrategy().sendRedirect(request, response, redirectUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String determineTargetUrl(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
Authentication authentication) {
|
||||||
|
// Default to the root URL
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
public interface Saml2AuthorityAttributeLookup {
|
||||||
|
String getAuthorityAttribute(String registrationId);
|
||||||
|
|
||||||
|
SimpleScimMappings getIdentityMappings(String registrationId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Saml2AuthorityAttributeLookupImpl implements Saml2AuthorityAttributeLookup {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthorityAttribute(String registrationId) {
|
||||||
|
return "authorityAttributeName";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SimpleScimMappings getIdentityMappings(String registrationId) {
|
||||||
|
return new SimpleScimMappings();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.opensaml.core.xml.XMLObject;
|
||||||
|
import org.opensaml.core.xml.schema.*;
|
||||||
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
|
|
||||||
|
public class SamlAssertionUtils {
|
||||||
|
|
||||||
|
public static Map<String, List<Object>> getAssertionAttributes(Assertion assertion) {
|
||||||
|
Map<String, List<Object>> attributeMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
assertion
|
||||||
|
.getAttributeStatements()
|
||||||
|
.forEach(
|
||||||
|
attributeStatement -> {
|
||||||
|
attributeStatement
|
||||||
|
.getAttributes()
|
||||||
|
.forEach(
|
||||||
|
attribute -> {
|
||||||
|
List<Object> attributeValues = new ArrayList<>();
|
||||||
|
|
||||||
|
attribute
|
||||||
|
.getAttributeValues()
|
||||||
|
.forEach(
|
||||||
|
xmlObject -> {
|
||||||
|
Object attributeValue =
|
||||||
|
getXmlObjectValue(
|
||||||
|
xmlObject);
|
||||||
|
if (attributeValue != null) {
|
||||||
|
attributeValues.add(
|
||||||
|
attributeValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
attributeMap.put(
|
||||||
|
attribute.getName(), attributeValues);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return attributeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getXmlObjectValue(XMLObject xmlObject) {
|
||||||
|
if (xmlObject instanceof XSAny) {
|
||||||
|
return ((XSAny) xmlObject).getTextContent();
|
||||||
|
} else if (xmlObject instanceof XSString) {
|
||||||
|
return ((XSString) xmlObject).getValue();
|
||||||
|
} else if (xmlObject instanceof XSInteger) {
|
||||||
|
return ((XSInteger) xmlObject).getValue();
|
||||||
|
} else if (xmlObject instanceof XSURI) {
|
||||||
|
return ((XSURI) xmlObject).getURI();
|
||||||
|
} else if (xmlObject instanceof XSBoolean) {
|
||||||
|
return ((XSBoolean) xmlObject).getValue().getValue();
|
||||||
|
} else if (xmlObject instanceof XSDateTime) {
|
||||||
|
Instant dateTime = ((XSDateTime) xmlObject).getValue();
|
||||||
|
return (dateTime != null) ? Instant.ofEpochMilli(dateTime.toEpochMilli()) : null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
|
||||||
|
import org.opensaml.security.x509.X509Support;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.security.converter.RsaKeyConverters;
|
||||||
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
|
import org.springframework.security.saml2.provider.service.registration.*;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class SamlConfig {
|
||||||
|
|
||||||
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@Autowired ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(
|
||||||
|
value = "security.saml.enabled",
|
||||||
|
havingValue = "true",
|
||||||
|
matchIfMissing = false)
|
||||||
|
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository()
|
||||||
|
throws CertificateException, IOException {
|
||||||
|
|
||||||
|
// Resource signingCertResource = new ClassPathResource(this.rpSigningCertLocation);
|
||||||
|
Resource signingCertResource =
|
||||||
|
resourceLoader.getResource(
|
||||||
|
this.applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getSaml()
|
||||||
|
.getCertificateLocation());
|
||||||
|
// Resource signingKeyResource = new ClassPathResource(this.rpSigningKeyLocation);
|
||||||
|
Resource signingKeyResource =
|
||||||
|
resourceLoader.getResource(
|
||||||
|
this.applicationProperties.getSecurity().getSaml().getPrivateKeyLocation());
|
||||||
|
try (InputStream is = signingKeyResource.getInputStream();
|
||||||
|
InputStream certIS = signingCertResource.getInputStream(); ) {
|
||||||
|
X509Certificate rpCertificate = X509Support.decodeCertificate(certIS.readAllBytes());
|
||||||
|
RSAPrivateKey rpKey = RsaKeyConverters.pkcs8().convert(is);
|
||||||
|
final Saml2X509Credential rpSigningCredentials =
|
||||||
|
Saml2X509Credential.signing(rpKey, rpCertificate);
|
||||||
|
|
||||||
|
X509Certificate apCert =
|
||||||
|
X509Support.decodeCertificate(
|
||||||
|
applicationProperties.getSecurity().getSaml().getSigningCertificate());
|
||||||
|
Saml2X509Credential apCredential = Saml2X509Credential.verification(apCert);
|
||||||
|
|
||||||
|
RelyingPartyRegistration registration =
|
||||||
|
RelyingPartyRegistrations.fromMetadataLocation(
|
||||||
|
applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getSaml()
|
||||||
|
.getIdpMetadataLocation())
|
||||||
|
.entityId(applicationProperties.getSecurity().getSaml().getEntityId())
|
||||||
|
.registrationId(
|
||||||
|
applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getSaml()
|
||||||
|
.getRegistrationId())
|
||||||
|
.signingX509Credentials(c -> c.add(rpSigningCredentials))
|
||||||
|
.assertingPartyDetails(
|
||||||
|
party ->
|
||||||
|
party.wantAuthnRequestsSigned(true)
|
||||||
|
.verificationX509Credentials(
|
||||||
|
c -> c.add(apCredential)))
|
||||||
|
.singleLogoutServiceLocation("http://localhost:8090/logout/saml2/slo")
|
||||||
|
.build();
|
||||||
|
return new InMemoryRelyingPartyRegistrationRepository(registration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
|
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.unboundid.scim2.common.types.Email;
|
||||||
|
import com.unboundid.scim2.common.types.Name;
|
||||||
|
import com.unboundid.scim2.common.types.UserResource;
|
||||||
|
|
||||||
|
public class ScimSaml2AuthenticatedPrincipal implements AuthenticatedPrincipal, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final transient UserResource userResource;
|
||||||
|
|
||||||
|
public ScimSaml2AuthenticatedPrincipal(
|
||||||
|
final Assertion assertion,
|
||||||
|
final Map<String, List<Object>> attributes,
|
||||||
|
final SimpleScimMappings attributeMappings) {
|
||||||
|
Assert.notNull(assertion, "assertion cannot be null");
|
||||||
|
Assert.notNull(assertion.getSubject(), "assertion subject cannot be null");
|
||||||
|
Assert.notNull(
|
||||||
|
assertion.getSubject().getNameID(), "assertion subject NameID cannot be null");
|
||||||
|
Assert.notNull(attributes, "attributes cannot be null");
|
||||||
|
Assert.notNull(attributeMappings, "attributeMappings cannot be null");
|
||||||
|
|
||||||
|
final Name name =
|
||||||
|
new Name()
|
||||||
|
.setFamilyName(
|
||||||
|
getAttribute(
|
||||||
|
attributes,
|
||||||
|
attributeMappings,
|
||||||
|
SimpleScimMappings::getFamilyName))
|
||||||
|
.setGivenName(
|
||||||
|
getAttribute(
|
||||||
|
attributes,
|
||||||
|
attributeMappings,
|
||||||
|
SimpleScimMappings::getGivenName));
|
||||||
|
|
||||||
|
final List<Email> emails = new ArrayList<>(1);
|
||||||
|
emails.add(
|
||||||
|
new Email()
|
||||||
|
.setValue(
|
||||||
|
getAttribute(
|
||||||
|
attributes,
|
||||||
|
attributeMappings,
|
||||||
|
SimpleScimMappings::getEmail))
|
||||||
|
.setPrimary(true));
|
||||||
|
|
||||||
|
userResource =
|
||||||
|
new UserResource()
|
||||||
|
.setUserName(assertion.getSubject().getNameID().getValue())
|
||||||
|
.setName(name)
|
||||||
|
.setEmails(emails);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getAttribute(
|
||||||
|
final Map<String, List<Object>> attributes,
|
||||||
|
final SimpleScimMappings simpleScimMappings,
|
||||||
|
final Function<SimpleScimMappings, String> attributeMapper) {
|
||||||
|
|
||||||
|
final String key = attributeMapper.apply(simpleScimMappings);
|
||||||
|
|
||||||
|
final List<Object> values = attributes.getOrDefault(key, Collections.emptyList());
|
||||||
|
|
||||||
|
return values.stream()
|
||||||
|
.filter(String.class::isInstance)
|
||||||
|
.map(String.class::cast)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.userResource.getUserName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserResource getUserResource() {
|
||||||
|
return this.userResource;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SimpleScimMappings {
|
||||||
|
String givenName;
|
||||||
|
String familyName;
|
||||||
|
String email;
|
||||||
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml2;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.KeyFactory;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
|
||||||
|
|
||||||
import org.bouncycastle.util.io.pem.PemObject;
|
|
||||||
import org.bouncycastle.util.io.pem.PemReader;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
|
|
||||||
public class CertificateUtils {
|
|
||||||
|
|
||||||
public static X509Certificate readCertificate(Resource certificateResource) throws Exception {
|
|
||||||
try (PemReader pemReader =
|
|
||||||
new PemReader(
|
|
||||||
new InputStreamReader(
|
|
||||||
certificateResource.getInputStream(), StandardCharsets.UTF_8))) {
|
|
||||||
PemObject pemObject = pemReader.readPemObject();
|
|
||||||
byte[] decodedCert = pemObject.getContent();
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception {
|
|
||||||
try (PemReader pemReader =
|
|
||||||
new PemReader(
|
|
||||||
new InputStreamReader(
|
|
||||||
privateKeyResource.getInputStream(), StandardCharsets.UTF_8))) {
|
|
||||||
PemObject pemObject = pemReader.readPemObject();
|
|
||||||
byte[] decodedKey = pemObject.getContent();
|
|
||||||
return (RSAPrivateKey)
|
|
||||||
KeyFactory.getInstance("RSA")
|
|
||||||
.generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml2;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
|
||||||
|
|
||||||
public class CustomSaml2AuthenticatedPrincipal
|
|
||||||
implements Saml2AuthenticatedPrincipal, Serializable {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final Map<String, List<Object>> attributes;
|
|
||||||
private final String nameId;
|
|
||||||
private final List<String> sessionIndexes;
|
|
||||||
|
|
||||||
public CustomSaml2AuthenticatedPrincipal(
|
|
||||||
String name,
|
|
||||||
Map<String, List<Object>> attributes,
|
|
||||||
String nameId,
|
|
||||||
List<String> sessionIndexes) {
|
|
||||||
this.name = name;
|
|
||||||
this.attributes = attributes;
|
|
||||||
this.nameId = nameId;
|
|
||||||
this.sessionIndexes = sessionIndexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<Object>> getAttributes() {
|
|
||||||
return this.attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNameId() {
|
|
||||||
return this.nameId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getSessionIndexes() {
|
|
||||||
return this.sessionIndexes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml2;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.ProviderNotFoundException;
|
|
||||||
import org.springframework.security.core.AuthenticationException;
|
|
||||||
import org.springframework.security.saml2.core.Saml2Error;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
|
||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationFailure(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
AuthenticationException exception)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
if (exception instanceof Saml2AuthenticationException) {
|
|
||||||
Saml2Error error = ((Saml2AuthenticationException) exception).getSaml2Error();
|
|
||||||
getRedirectStrategy()
|
|
||||||
.sendRedirect(request, response, "/login?erroroauth=" + error.getErrorCode());
|
|
||||||
} else if (exception instanceof ProviderNotFoundException) {
|
|
||||||
getRedirectStrategy()
|
|
||||||
.sendRedirect(
|
|
||||||
request,
|
|
||||||
response,
|
|
||||||
"/login?erroroauth=not_authentication_provider_found");
|
|
||||||
}
|
|
||||||
log.error("AuthenticationException: " + exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml2;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.LockedException;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
|
||||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import jakarta.servlet.http.HttpSession;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import stirling.software.SPDF.config.security.LoginAttemptService;
|
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
|
||||||
import stirling.software.SPDF.utils.RequestUriUtils;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class CustomSaml2AuthenticationSuccessHandler
|
|
||||||
extends SavedRequestAwareAuthenticationSuccessHandler {
|
|
||||||
|
|
||||||
private LoginAttemptService loginAttemptService;
|
|
||||||
|
|
||||||
private ApplicationProperties applicationProperties;
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationSuccess(
|
|
||||||
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
|
||||||
throws ServletException, IOException {
|
|
||||||
|
|
||||||
Object principal = authentication.getPrincipal();
|
|
||||||
|
|
||||||
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
String username = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
|
||||||
// Get the saved request
|
|
||||||
HttpSession session = request.getSession(false);
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
SavedRequest savedRequest =
|
|
||||||
(session != null)
|
|
||||||
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (savedRequest != null
|
|
||||||
&& !RequestUriUtils.isStaticResource(
|
|
||||||
contextPath, savedRequest.getRedirectUrl())) {
|
|
||||||
// Redirect to the original destination
|
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
|
||||||
} else {
|
|
||||||
SAML2 saml2 = applicationProperties.getSecurity().getSaml2();
|
|
||||||
|
|
||||||
if (loginAttemptService.isBlocked(username)) {
|
|
||||||
if (session != null) {
|
|
||||||
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
|
||||||
}
|
|
||||||
throw new LockedException(
|
|
||||||
"Your account has been locked due to too many failed login attempts.");
|
|
||||||
}
|
|
||||||
if (userService.usernameExistsIgnoreCase(username)
|
|
||||||
&& userService.hasPassword(username)
|
|
||||||
&& !userService.isAuthenticationTypeByUsername(
|
|
||||||
username, AuthenticationType.OAUTH2)
|
|
||||||
&& saml2.getAutoCreateUser()) {
|
|
||||||
response.sendRedirect(
|
|
||||||
contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (saml2.getBlockRegistration()
|
|
||||||
&& !userService.usernameExistsIgnoreCase(username)) {
|
|
||||||
response.sendRedirect(
|
|
||||||
contextPath + "/login?erroroauth=oauth2_admin_blocked_user");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
userService.processOAuth2PostLogin(username, saml2.getAutoCreateUser());
|
|
||||||
response.sendRedirect(contextPath + "/");
|
|
||||||
return;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml2;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.opensaml.core.xml.XMLObject;
|
|
||||||
import org.opensaml.core.xml.schema.XSBoolean;
|
|
||||||
import org.opensaml.core.xml.schema.XSString;
|
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
|
||||||
import org.opensaml.saml.saml2.core.Attribute;
|
|
||||||
import org.opensaml.saml.saml2.core.AttributeStatement;
|
|
||||||
import org.opensaml.saml.saml2.core.AuthnStatement;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
|
||||||
import stirling.software.SPDF.model.User;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class CustomSaml2ResponseAuthenticationConverter
|
|
||||||
implements Converter<ResponseToken, Saml2Authentication> {
|
|
||||||
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
public CustomSaml2ResponseAuthenticationConverter(UserService userService) {
|
|
||||||
this.userService = userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Saml2Authentication convert(ResponseToken responseToken) {
|
|
||||||
// Extract the assertion from the response
|
|
||||||
Assertion assertion = responseToken.getResponse().getAssertions().get(0);
|
|
||||||
|
|
||||||
// Extract the NameID
|
|
||||||
String nameId = assertion.getSubject().getNameID().getValue();
|
|
||||||
|
|
||||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(nameId);
|
|
||||||
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
|
|
||||||
if (userOpt.isPresent()) {
|
|
||||||
User user = userOpt.get();
|
|
||||||
if (user != null) {
|
|
||||||
simpleGrantedAuthority =
|
|
||||||
new SimpleGrantedAuthority(userService.findRole(user).getAuthority());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the SessionIndexes
|
|
||||||
List<String> sessionIndexes = new ArrayList<>();
|
|
||||||
for (AuthnStatement authnStatement : assertion.getAuthnStatements()) {
|
|
||||||
sessionIndexes.add(authnStatement.getSessionIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the Attributes
|
|
||||||
Map<String, List<Object>> attributes = extractAttributes(assertion);
|
|
||||||
|
|
||||||
// Create the custom principal
|
|
||||||
CustomSaml2AuthenticatedPrincipal principal =
|
|
||||||
new CustomSaml2AuthenticatedPrincipal(nameId, attributes, nameId, sessionIndexes);
|
|
||||||
|
|
||||||
// Create the Saml2Authentication
|
|
||||||
return new Saml2Authentication(
|
|
||||||
principal,
|
|
||||||
responseToken.getToken().getSaml2Response(),
|
|
||||||
Collections.singletonList(simpleGrantedAuthority));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, List<Object>> extractAttributes(Assertion assertion) {
|
|
||||||
Map<String, List<Object>> attributes = new HashMap<>();
|
|
||||||
for (AttributeStatement attributeStatement : assertion.getAttributeStatements()) {
|
|
||||||
for (Attribute attribute : attributeStatement.getAttributes()) {
|
|
||||||
String attributeName = attribute.getName();
|
|
||||||
List<Object> values = new ArrayList<>();
|
|
||||||
for (XMLObject xmlObject : attribute.getAttributeValues()) {
|
|
||||||
log.info("BOOL: " + ((XSBoolean) xmlObject).getValue());
|
|
||||||
values.add(((XSString) xmlObject).getValue());
|
|
||||||
}
|
|
||||||
attributes.put(attributeName, values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
|
||||||
import stirling.software.SPDF.model.SessionEntity;
|
import stirling.software.SPDF.model.SessionEntity;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -51,8 +50,6 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
principalName = ((UserDetails) principal).getUsername();
|
principalName = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
principalName = ((OAuth2User) principal).getName();
|
principalName = ((OAuth2User) principal).getName();
|
||||||
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
principalName = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
principalName = (String) principal;
|
principalName = (String) principal;
|
||||||
}
|
}
|
||||||
@@ -82,8 +79,6 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
principalName = ((UserDetails) principal).getUsername();
|
principalName = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
principalName = ((OAuth2User) principal).getName();
|
principalName = ((OAuth2User) principal).getName();
|
||||||
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
principalName = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
principalName = (String) principal;
|
principalName = (String) principal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.springframework.http.ResponseEntity;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
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.model.api.PDFFile;
|
||||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
||||||
@@ -22,7 +21,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
||||||
@Tag(name = "General", description = "General APIs")
|
|
||||||
public class PdfImageRemovalController {
|
public class PdfImageRemovalController {
|
||||||
|
|
||||||
// Service for removing images from PDFs
|
// Service for removing images from PDFs
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public class ScalePagesController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PDRectangle getTargetSize(String targetPDRectangle, PDDocument sourceDocument) {
|
private PDRectangle getTargetSize(String targetPDRectangle, PDDocument sourceDocument) {
|
||||||
if ("KEEP".equals(targetPDRectangle)) {
|
if (targetPDRectangle.equals("KEEP")) {
|
||||||
if (sourceDocument.getNumberOfPages() == 0) {
|
if (sourceDocument.getNumberOfPages() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ public class SettingsController {
|
|||||||
}
|
}
|
||||||
GeneralUtils.saveKeyToConfig("system.enableAnalytics", String.valueOf(enabled), false);
|
GeneralUtils.saveKeyToConfig("system.enableAnalytics", String.valueOf(enabled), false);
|
||||||
applicationProperties.getSystem().setEnableAnalytics(String.valueOf(enabled));
|
applicationProperties.getSystem().setEnableAnalytics(String.valueOf(enabled));
|
||||||
|
|
||||||
return ResponseEntity.ok("Updated");
|
return ResponseEntity.ok("Updated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
import stirling.software.SPDF.model.Role;
|
import stirling.software.SPDF.model.Role;
|
||||||
@@ -337,8 +336,6 @@ public class UserController {
|
|||||||
userNameP = ((UserDetails) principal).getUsername();
|
userNameP = ((UserDetails) principal).getUsername();
|
||||||
} else if (principal instanceof OAuth2User) {
|
} else if (principal instanceof OAuth2User) {
|
||||||
userNameP = ((OAuth2User) principal).getName();
|
userNameP = ((OAuth2User) principal).getName();
|
||||||
} else if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
userNameP = ((CustomSaml2AuthenticatedPrincipal) principal).getName();
|
|
||||||
} else if (principal instanceof String) {
|
} else if (principal instanceof String) {
|
||||||
userNameP = (String) principal;
|
userNameP = (String) principal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@@ -15,6 +14,7 @@ import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
|||||||
import stirling.software.SPDF.utils.FileToPdf;
|
import stirling.software.SPDF.utils.FileToPdf;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
|
// Disabled for now
|
||||||
// @RestController
|
// @RestController
|
||||||
// @Tag(name = "Convert", description = "Convert APIs")
|
// @Tag(name = "Convert", description = "Convert APIs")
|
||||||
// @RequestMapping("/api/v1/convert")
|
// @RequestMapping("/api/v1/convert")
|
||||||
@@ -24,7 +24,7 @@ public class ConvertBookToPDFController {
|
|||||||
|
|
||||||
private final CustomPDDocumentFactory pdfDocumentFactory;
|
private final CustomPDDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
@Autowired
|
// @Autowired
|
||||||
public ConvertBookToPDFController(
|
public ConvertBookToPDFController(
|
||||||
CustomPDDocumentFactory pdfDocumentFactory,
|
CustomPDDocumentFactory pdfDocumentFactory,
|
||||||
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
|
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
|
||||||
@@ -66,8 +66,6 @@ public class ConvertBookToPDFController {
|
|||||||
}
|
}
|
||||||
byte[] pdfBytes = FileToPdf.convertBookTypeToPdf(fileInput.getBytes(), originalFilename);
|
byte[] pdfBytes = FileToPdf.convertBookTypeToPdf(fileInput.getBytes(), originalFilename);
|
||||||
|
|
||||||
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
|
|
||||||
|
|
||||||
String outputFilename =
|
String outputFilename =
|
||||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||||
+ ".pdf"; // Remove file extension and append .pdf
|
+ ".pdf"; // Remove file extension and append .pdf
|
||||||
|
|||||||
@@ -1,39 +1,27 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import io.github.pixee.security.Filenames;
|
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 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.utils.FileToPdf;
|
import stirling.software.SPDF.utils.FileToPdf;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
// Disabled for now
|
||||||
@Tag(name = "Convert", description = "Convert APIs")
|
// @RestController
|
||||||
@RequestMapping("/api/v1/convert")
|
// @Tag(name = "Convert", description = "Convert APIs")
|
||||||
|
// @RequestMapping("/api/v1/convert")
|
||||||
public class ConvertHtmlToPDF {
|
public class ConvertHtmlToPDF {
|
||||||
|
|
||||||
private final boolean bookAndHtmlFormatsInstalled;
|
// @Autowired
|
||||||
|
@Qualifier("bookAndHtmlFormatsInstalled")
|
||||||
private final CustomPDDocumentFactory pdfDocumentFactory;
|
private boolean bookAndHtmlFormatsInstalled;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ConvertHtmlToPDF(
|
|
||||||
CustomPDDocumentFactory pdfDocumentFactory,
|
|
||||||
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
|
|
||||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
|
||||||
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
@@ -61,8 +49,6 @@ public class ConvertHtmlToPDF {
|
|||||||
originalFilename,
|
originalFilename,
|
||||||
bookAndHtmlFormatsInstalled);
|
bookAndHtmlFormatsInstalled);
|
||||||
|
|
||||||
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
|
|
||||||
|
|
||||||
String outputFilename =
|
String outputFilename =
|
||||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||||
+ ".pdf"; // Remove file extension and append .pdf
|
+ ".pdf"; // Remove file extension and append .pdf
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class ConvertImgPDFController {
|
|||||||
result =
|
result =
|
||||||
PdfUtils.convertFromPdf(
|
PdfUtils.convertFromPdf(
|
||||||
pdfBytes,
|
pdfBytes,
|
||||||
"webp".equalsIgnoreCase(imageFormat) ? "png" : imageFormat.toUpperCase(),
|
imageFormat.equalsIgnoreCase("webp") ? "png" : imageFormat.toUpperCase(),
|
||||||
colorTypeResult,
|
colorTypeResult,
|
||||||
singleImage,
|
singleImage,
|
||||||
Integer.valueOf(dpi),
|
Integer.valueOf(dpi),
|
||||||
@@ -90,9 +90,9 @@ public class ConvertImgPDFController {
|
|||||||
if (result == null || result.length == 0) {
|
if (result == null || result.length == 0) {
|
||||||
logger.error("resultant bytes for {} is null, error converting ", filename);
|
logger.error("resultant bytes for {} is null, error converting ", filename);
|
||||||
}
|
}
|
||||||
if ("webp".equalsIgnoreCase(imageFormat) && !CheckProgramInstall.isPythonAvailable()) {
|
if (imageFormat.equalsIgnoreCase("webp") && !CheckProgramInstall.isPythonAvailable()) {
|
||||||
throw new IOException("Python is not installed. Required for WebP conversion.");
|
throw new IOException("Python is not installed. Required for WebP conversion.");
|
||||||
} else if ("webp".equalsIgnoreCase(imageFormat)
|
} else if (imageFormat.equalsIgnoreCase("webp")
|
||||||
&& CheckProgramInstall.isPythonAvailable()) {
|
&& CheckProgramInstall.isPythonAvailable()) {
|
||||||
// Write the output stream to a temp file
|
// Write the output stream to a temp file
|
||||||
Path tempFile = Files.createTempFile("temp_png", ".png");
|
Path tempFile = Files.createTempFile("temp_png", ".png");
|
||||||
|
|||||||
@@ -10,40 +10,28 @@ import org.commonmark.node.Node;
|
|||||||
import org.commonmark.parser.Parser;
|
import org.commonmark.parser.Parser;
|
||||||
import org.commonmark.renderer.html.AttributeProvider;
|
import org.commonmark.renderer.html.AttributeProvider;
|
||||||
import org.commonmark.renderer.html.HtmlRenderer;
|
import org.commonmark.renderer.html.HtmlRenderer;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import io.github.pixee.security.Filenames;
|
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 stirling.software.SPDF.model.api.GeneralFile;
|
import stirling.software.SPDF.model.api.GeneralFile;
|
||||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
|
||||||
import stirling.software.SPDF.utils.FileToPdf;
|
import stirling.software.SPDF.utils.FileToPdf;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
// Disabled for now
|
||||||
@Tag(name = "Convert", description = "Convert APIs")
|
// @RestController
|
||||||
@RequestMapping("/api/v1/convert")
|
// @Tag(name = "Convert", description = "Convert APIs")
|
||||||
|
// @RequestMapping("/api/v1/convert")
|
||||||
public class ConvertMarkdownToPdf {
|
public class ConvertMarkdownToPdf {
|
||||||
|
|
||||||
private final boolean bookAndHtmlFormatsInstalled;
|
// @Autowired
|
||||||
|
@Qualifier("bookAndHtmlFormatsInstalled")
|
||||||
private final CustomPDDocumentFactory pdfDocumentFactory;
|
private boolean bookAndHtmlFormatsInstalled;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ConvertMarkdownToPdf(
|
|
||||||
CustomPDDocumentFactory pdfDocumentFactory,
|
|
||||||
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
|
|
||||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
|
||||||
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
||||||
@Operation(
|
@Operation(
|
||||||
@@ -82,7 +70,7 @@ public class ConvertMarkdownToPdf {
|
|||||||
htmlContent.getBytes(),
|
htmlContent.getBytes(),
|
||||||
"converted.html",
|
"converted.html",
|
||||||
bookAndHtmlFormatsInstalled);
|
bookAndHtmlFormatsInstalled);
|
||||||
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
|
|
||||||
String outputFilename =
|
String outputFilename =
|
||||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||||
+ ".pdf"; // Remove file extension and append .pdf
|
+ ".pdf"; // Remove file extension and append .pdf
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@@ -21,12 +20,13 @@ import stirling.software.SPDF.utils.ProcessExecutor;
|
|||||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
|
// Disabled for now
|
||||||
// @RestController
|
// @RestController
|
||||||
// @Tag(name = "Convert", description = "Convert APIs")
|
// @Tag(name = "Convert", description = "Convert APIs")
|
||||||
// @RequestMapping("/api/v1/convert")
|
// @RequestMapping("/api/v1/convert")
|
||||||
public class ConvertPDFToBookController {
|
public class ConvertPDFToBookController {
|
||||||
|
|
||||||
@Autowired
|
// @Autowired
|
||||||
@Qualifier("bookAndHtmlFormatsInstalled")
|
@Qualifier("bookAndHtmlFormatsInstalled")
|
||||||
private boolean bookAndHtmlFormatsInstalled;
|
private boolean bookAndHtmlFormatsInstalled;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,4 @@ public interface UserServiceInterface {
|
|||||||
String getApiKeyForUser(String username);
|
String getApiKeyForUser(String username);
|
||||||
|
|
||||||
String getCurrentUsername();
|
String getCurrentUsername();
|
||||||
|
|
||||||
long getTotalUsersCount();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@@ -18,39 +14,12 @@ import java.security.UnrecoverableKeyException;
|
|||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.pdfbox.examples.signature.CreateSignatureBase;
|
import org.apache.pdfbox.examples.signature.CreateSignatureBase;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDResources;
|
|
||||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
|
||||||
import org.apache.pdfbox.pdmodel.common.PDStream;
|
|
||||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
|
||||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
|
||||||
import org.apache.pdfbox.pdmodel.font.Standard14Fonts.FontName;
|
|
||||||
import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
|
|
||||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
|
||||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
|
||||||
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
|
||||||
import org.apache.pdfbox.util.Matrix;
|
|
||||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||||
import org.bouncycastle.asn1.x500.RDN;
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
|
||||||
import org.bouncycastle.asn1.x500.style.IETFUtils;
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.openssl.PEMDecryptorProvider;
|
import org.bouncycastle.openssl.PEMDecryptorProvider;
|
||||||
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
||||||
@@ -66,7 +35,6 @@ import org.bouncycastle.pkcs.PKCSException;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -94,8 +62,6 @@ public class CertSignController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CreateSignature extends CreateSignatureBase {
|
class CreateSignature extends CreateSignatureBase {
|
||||||
File logoFile;
|
|
||||||
|
|
||||||
public CreateSignature(KeyStore keystore, char[] pin)
|
public CreateSignature(KeyStore keystore, char[] pin)
|
||||||
throws KeyStoreException,
|
throws KeyStoreException,
|
||||||
UnrecoverableKeyException,
|
UnrecoverableKeyException,
|
||||||
@@ -103,101 +69,6 @@ public class CertSignController {
|
|||||||
IOException,
|
IOException,
|
||||||
CertificateException {
|
CertificateException {
|
||||||
super(keystore, pin);
|
super(keystore, pin);
|
||||||
ClassPathResource resource = new ClassPathResource("static/images/signature.png");
|
|
||||||
try (InputStream is = resource.getInputStream()) {
|
|
||||||
logoFile = Files.createTempFile("signature", ".png").toFile();
|
|
||||||
FileUtils.copyInputStreamToFile(is, logoFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Failed to load image signature file");
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream createVisibleSignature(
|
|
||||||
PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showLogo)
|
|
||||||
throws IOException {
|
|
||||||
// modified from org.apache.pdfbox.examples.signature.CreateVisibleSignature2
|
|
||||||
try (PDDocument doc = new PDDocument()) {
|
|
||||||
PDPage page = new PDPage(srcDoc.getPage(pageNumber).getMediaBox());
|
|
||||||
doc.addPage(page);
|
|
||||||
PDAcroForm acroForm = new PDAcroForm(doc);
|
|
||||||
doc.getDocumentCatalog().setAcroForm(acroForm);
|
|
||||||
PDSignatureField signatureField = new PDSignatureField(acroForm);
|
|
||||||
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
|
|
||||||
List<PDField> acroFormFields = acroForm.getFields();
|
|
||||||
acroForm.setSignaturesExist(true);
|
|
||||||
acroForm.setAppendOnly(true);
|
|
||||||
acroForm.getCOSObject().setDirect(true);
|
|
||||||
acroFormFields.add(signatureField);
|
|
||||||
|
|
||||||
PDRectangle rect = new PDRectangle(0, 0, 200, 50);
|
|
||||||
|
|
||||||
widget.setRectangle(rect);
|
|
||||||
|
|
||||||
// from PDVisualSigBuilder.createHolderForm()
|
|
||||||
PDStream stream = new PDStream(doc);
|
|
||||||
PDFormXObject form = new PDFormXObject(stream);
|
|
||||||
PDResources res = new PDResources();
|
|
||||||
form.setResources(res);
|
|
||||||
form.setFormType(1);
|
|
||||||
PDRectangle bbox = new PDRectangle(rect.getWidth(), rect.getHeight());
|
|
||||||
float height = bbox.getHeight();
|
|
||||||
form.setBBox(bbox);
|
|
||||||
PDFont font = new PDType1Font(FontName.TIMES_BOLD);
|
|
||||||
|
|
||||||
// from PDVisualSigBuilder.createAppearanceDictionary()
|
|
||||||
PDAppearanceDictionary appearance = new PDAppearanceDictionary();
|
|
||||||
appearance.getCOSObject().setDirect(true);
|
|
||||||
PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
|
|
||||||
appearance.setNormalAppearance(appearanceStream);
|
|
||||||
widget.setAppearance(appearance);
|
|
||||||
|
|
||||||
try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) {
|
|
||||||
if (showLogo) {
|
|
||||||
cs.saveGraphicsState();
|
|
||||||
PDExtendedGraphicsState extState = new PDExtendedGraphicsState();
|
|
||||||
extState.setBlendMode(BlendMode.MULTIPLY);
|
|
||||||
extState.setNonStrokingAlphaConstant(0.5f);
|
|
||||||
cs.setGraphicsStateParameters(extState);
|
|
||||||
cs.transform(Matrix.getScaleInstance(0.08f, 0.08f));
|
|
||||||
PDImageXObject img =
|
|
||||||
PDImageXObject.createFromFileByExtension(logoFile, doc);
|
|
||||||
cs.drawImage(img, 100, 0);
|
|
||||||
cs.restoreGraphicsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// show text
|
|
||||||
float fontSize = 10;
|
|
||||||
float leading = fontSize * 1.5f;
|
|
||||||
cs.beginText();
|
|
||||||
cs.setFont(font, fontSize);
|
|
||||||
cs.setNonStrokingColor(Color.black);
|
|
||||||
cs.newLineAtOffset(fontSize, height - leading);
|
|
||||||
cs.setLeading(leading);
|
|
||||||
|
|
||||||
X509Certificate cert = (X509Certificate) getCertificateChain()[0];
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/2914521/
|
|
||||||
X500Name x500Name = new X500Name(cert.getSubjectX500Principal().getName());
|
|
||||||
RDN cn = x500Name.getRDNs(BCStyle.CN)[0];
|
|
||||||
String name = IETFUtils.valueToString(cn.getFirst().getValue());
|
|
||||||
|
|
||||||
String date = signature.getSignDate().getTime().toString();
|
|
||||||
String reason = signature.getReason();
|
|
||||||
|
|
||||||
cs.showText("Signed by " + name);
|
|
||||||
cs.newLine();
|
|
||||||
cs.showText(date);
|
|
||||||
cs.newLine();
|
|
||||||
cs.showText(reason);
|
|
||||||
|
|
||||||
cs.endText();
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
doc.save(baos);
|
|
||||||
return new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,8 +97,7 @@ public class CertSignController {
|
|||||||
String reason = request.getReason();
|
String reason = request.getReason();
|
||||||
String location = request.getLocation();
|
String location = request.getLocation();
|
||||||
String name = request.getName();
|
String name = request.getName();
|
||||||
Integer pageNumber = request.getPageNumber() - 1;
|
Integer pageNumber = request.getPageNumber();
|
||||||
Boolean showLogo = request.isShowLogo();
|
|
||||||
|
|
||||||
if (certType == null) {
|
if (certType == null) {
|
||||||
throw new IllegalArgumentException("Cert type must be provided");
|
throw new IllegalArgumentException("Cert type must be provided");
|
||||||
@@ -256,19 +126,11 @@ public class CertSignController {
|
|||||||
throw new IllegalArgumentException("Invalid cert type: " + certType);
|
throw new IllegalArgumentException("Invalid cert type: " + certType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: page number
|
||||||
|
|
||||||
CreateSignature createSignature = new CreateSignature(ks, password.toCharArray());
|
CreateSignature createSignature = new CreateSignature(ks, password.toCharArray());
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
sign(
|
sign(pdfDocumentFactory, pdf.getBytes(), baos, createSignature, name, location, reason);
|
||||||
pdfDocumentFactory,
|
|
||||||
pdf.getBytes(),
|
|
||||||
baos,
|
|
||||||
createSignature,
|
|
||||||
showSignature,
|
|
||||||
pageNumber,
|
|
||||||
name,
|
|
||||||
location,
|
|
||||||
reason,
|
|
||||||
showLogo);
|
|
||||||
return WebResponseUtils.boasToWebResponse(
|
return WebResponseUtils.boasToWebResponse(
|
||||||
baos,
|
baos,
|
||||||
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
|
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
|
||||||
@@ -280,12 +142,9 @@ public class CertSignController {
|
|||||||
byte[] input,
|
byte[] input,
|
||||||
OutputStream output,
|
OutputStream output,
|
||||||
CreateSignature instance,
|
CreateSignature instance,
|
||||||
Boolean showSignature,
|
|
||||||
Integer pageNumber,
|
|
||||||
String name,
|
String name,
|
||||||
String location,
|
String location,
|
||||||
String reason,
|
String reason) {
|
||||||
Boolean showLogo) {
|
|
||||||
try (PDDocument doc = pdfDocumentFactory.load(input)) {
|
try (PDDocument doc = pdfDocumentFactory.load(input)) {
|
||||||
PDSignature signature = new PDSignature();
|
PDSignature signature = new PDSignature();
|
||||||
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
|
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
|
||||||
@@ -295,17 +154,7 @@ public class CertSignController {
|
|||||||
signature.setReason(reason);
|
signature.setReason(reason);
|
||||||
signature.setSignDate(Calendar.getInstance());
|
signature.setSignDate(Calendar.getInstance());
|
||||||
|
|
||||||
if (showSignature) {
|
doc.addSignature(signature, instance);
|
||||||
SignatureOptions signatureOptions = new SignatureOptions();
|
|
||||||
signatureOptions.setVisualSignature(
|
|
||||||
instance.createVisibleSignature(doc, signature, pageNumber, showLogo));
|
|
||||||
signatureOptions.setPage(pageNumber);
|
|
||||||
|
|
||||||
doc.addSignature(signature, instance, signatureOptions);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
doc.addSignature(signature, instance);
|
|
||||||
}
|
|
||||||
doc.saveIncremental(output);
|
doc.saveIncremental(output);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("exception", e);
|
logger.error("exception", e);
|
||||||
|
|||||||
@@ -21,13 +21,10 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.*;
|
import stirling.software.SPDF.model.*;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
|
|
||||||
import stirling.software.SPDF.model.provider.GithubProvider;
|
import stirling.software.SPDF.model.provider.GithubProvider;
|
||||||
import stirling.software.SPDF.model.provider.GoogleProvider;
|
import stirling.software.SPDF.model.provider.GoogleProvider;
|
||||||
import stirling.software.SPDF.model.provider.KeycloakProvider;
|
import stirling.software.SPDF.model.provider.KeycloakProvider;
|
||||||
@@ -54,54 +51,38 @@ public class AccountWebController {
|
|||||||
|
|
||||||
Map<String, String> providerList = new HashMap<>();
|
Map<String, String> providerList = new HashMap<>();
|
||||||
|
|
||||||
Security securityProps = applicationProperties.getSecurity();
|
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
||||||
|
|
||||||
OAUTH2 oauth = securityProps.getOauth2();
|
|
||||||
if (oauth != null) {
|
if (oauth != null) {
|
||||||
if (oauth.getEnabled()) {
|
if (oauth.isSettingsValid()) {
|
||||||
if (oauth.isSettingsValid()) {
|
providerList.put("oidc", oauth.getProvider());
|
||||||
providerList.put("/oauth2/authorization/oidc", oauth.getProvider());
|
}
|
||||||
|
Client client = oauth.getClient();
|
||||||
|
if (client != null) {
|
||||||
|
GoogleProvider google = client.getGoogle();
|
||||||
|
if (google.isSettingsValid()) {
|
||||||
|
providerList.put(google.getName(), google.getClientName());
|
||||||
}
|
}
|
||||||
Client client = oauth.getClient();
|
|
||||||
if (client != null) {
|
|
||||||
GoogleProvider google = client.getGoogle();
|
|
||||||
if (google.isSettingsValid()) {
|
|
||||||
providerList.put(
|
|
||||||
"/oauth2/authorization/" + google.getName(),
|
|
||||||
google.getClientName());
|
|
||||||
}
|
|
||||||
|
|
||||||
GithubProvider github = client.getGithub();
|
GithubProvider github = client.getGithub();
|
||||||
if (github.isSettingsValid()) {
|
if (github.isSettingsValid()) {
|
||||||
providerList.put(
|
providerList.put(github.getName(), github.getClientName());
|
||||||
"/oauth2/authorization/" + github.getName(),
|
}
|
||||||
github.getClientName());
|
|
||||||
}
|
|
||||||
|
|
||||||
KeycloakProvider keycloak = client.getKeycloak();
|
KeycloakProvider keycloak = client.getKeycloak();
|
||||||
if (keycloak.isSettingsValid()) {
|
if (keycloak.isSettingsValid()) {
|
||||||
providerList.put(
|
providerList.put(keycloak.getName(), keycloak.getClientName());
|
||||||
"/oauth2/authorization/" + keycloak.getName(),
|
|
||||||
keycloak.getClientName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SAML2 saml2 = securityProps.getSaml2();
|
|
||||||
if (securityProps.isSaml2Activ()
|
|
||||||
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
|
|
||||||
providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2");
|
|
||||||
}
|
|
||||||
// Remove any null keys/values from the providerList
|
// Remove any null keys/values from the providerList
|
||||||
providerList
|
providerList
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
|
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
|
||||||
model.addAttribute("providerlist", providerList);
|
model.addAttribute("providerlist", providerList);
|
||||||
|
|
||||||
model.addAttribute("loginMethod", securityProps.getLoginMethod());
|
model.addAttribute("loginMethod", applicationProperties.getSecurity().getLoginMethod());
|
||||||
boolean altLogin = providerList.size() > 0 ? securityProps.isAltLogin() : false;
|
model.addAttribute(
|
||||||
model.addAttribute("altLogin", altLogin);
|
"oAuth2Enabled", applicationProperties.getSecurity().getOauth2().getEnabled());
|
||||||
|
|
||||||
model.addAttribute("currentPage", "login");
|
model.addAttribute("currentPage", "login");
|
||||||
|
|
||||||
@@ -164,17 +145,6 @@ public class AccountWebController {
|
|||||||
case "userIsDisabled":
|
case "userIsDisabled":
|
||||||
erroroauth = "login.userIsDisabled";
|
erroroauth = "login.userIsDisabled";
|
||||||
break;
|
break;
|
||||||
case "invalid_destination":
|
|
||||||
erroroauth = "login.invalid_destination";
|
|
||||||
break;
|
|
||||||
// Valid InResponseTo was not available from the validation context, unable to
|
|
||||||
// evaluate
|
|
||||||
case "invalid_in_response_to":
|
|
||||||
erroroauth = "login.invalid_in_response_to";
|
|
||||||
break;
|
|
||||||
case "not_authentication_provider_found":
|
|
||||||
erroroauth = "login.not_authentication_provider_found";
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -379,17 +349,6 @@ public class AccountWebController {
|
|||||||
// Add oAuth2 Login attributes to the model
|
// Add oAuth2 Login attributes to the model
|
||||||
model.addAttribute("oAuth2Login", true);
|
model.addAttribute("oAuth2Login", true);
|
||||||
}
|
}
|
||||||
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
|
|
||||||
// Cast the principal object to OAuth2User
|
|
||||||
CustomSaml2AuthenticatedPrincipal userDetails =
|
|
||||||
(CustomSaml2AuthenticatedPrincipal) principal;
|
|
||||||
|
|
||||||
// Retrieve username and other attributes
|
|
||||||
username = userDetails.getName();
|
|
||||||
// Add oAuth2 Login attributes to the model
|
|
||||||
model.addAttribute("oAuth2Login", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
// Fetch user details from the database
|
// Fetch user details from the database
|
||||||
Optional<User> user =
|
Optional<User> user =
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import io.swagger.v3.oas.annotations.Hidden;
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
|
||||||
import stirling.software.SPDF.model.SignatureFile;
|
|
||||||
import stirling.software.SPDF.service.SignatureService;
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@Tag(name = "General", description = "General APIs")
|
@Tag(name = "General", description = "General APIs")
|
||||||
public class GeneralWebController {
|
public class GeneralWebController {
|
||||||
@@ -175,28 +171,11 @@ public class GeneralWebController {
|
|||||||
return "split-pdfs";
|
return "split-pdfs";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String SIGNATURE_BASE_PATH = "customFiles/static/signatures/";
|
|
||||||
private static final String ALL_USERS_FOLDER = "ALL_USERS";
|
|
||||||
|
|
||||||
@Autowired private SignatureService signatureService;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private UserServiceInterface userService;
|
|
||||||
|
|
||||||
@GetMapping("/sign")
|
@GetMapping("/sign")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String signForm(Model model) {
|
public String signForm(Model model) {
|
||||||
String username = "";
|
|
||||||
if (userService != null) {
|
|
||||||
username = userService.getCurrentUsername();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get signatures from both personal and ALL_USERS folders
|
|
||||||
List<SignatureFile> signatures = signatureService.getAvailableSignatures(username);
|
|
||||||
|
|
||||||
model.addAttribute("currentPage", "sign");
|
model.addAttribute("currentPage", "sign");
|
||||||
model.addAttribute("fonts", getFontNames());
|
model.addAttribute("fonts", getFontNames());
|
||||||
model.addAttribute("signatures", signatures);
|
|
||||||
return "sign";
|
return "sign";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package stirling.software.SPDF.controller.web;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
|
|
||||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
|
||||||
import stirling.software.SPDF.service.SignatureService;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/api/v1/general/")
|
|
||||||
public class SignatureController {
|
|
||||||
|
|
||||||
@Autowired private SignatureService signatureService;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private UserServiceInterface userService;
|
|
||||||
|
|
||||||
@GetMapping("/sign/{fileName}")
|
|
||||||
public ResponseEntity<byte[]> getSignature(@PathVariable(name = "fileName") String fileName)
|
|
||||||
throws IOException {
|
|
||||||
String username = "NON_SECURITY_USER";
|
|
||||||
if (userService != null) {
|
|
||||||
username = userService.getCurrentUsername();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify access permission
|
|
||||||
if (!signatureService.hasAccessToFile(username, fileName)) {
|
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] imageBytes = signatureService.getSignatureBytes(username, fileName);
|
|
||||||
return ResponseEntity.ok()
|
|
||||||
.contentType(MediaType.IMAGE_JPEG) // Adjust based on file type
|
|
||||||
.body(imageBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +1,20 @@
|
|||||||
package stirling.software.SPDF.model;
|
package stirling.software.SPDF.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
||||||
import stirling.software.SPDF.model.provider.GithubProvider;
|
import stirling.software.SPDF.model.provider.GithubProvider;
|
||||||
@@ -47,6 +38,7 @@ public class ApplicationProperties {
|
|||||||
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
||||||
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
||||||
private AutoPipeline autoPipeline = new AutoPipeline();
|
private AutoPipeline autoPipeline = new AutoPipeline();
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ApplicationProperties.class);
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class AutoPipeline {
|
public static class AutoPipeline {
|
||||||
@@ -68,110 +60,48 @@ public class ApplicationProperties {
|
|||||||
private Boolean csrfDisabled;
|
private Boolean csrfDisabled;
|
||||||
private InitialLogin initialLogin = new InitialLogin();
|
private InitialLogin initialLogin = new InitialLogin();
|
||||||
private OAUTH2 oauth2 = new OAUTH2();
|
private OAUTH2 oauth2 = new OAUTH2();
|
||||||
private SAML2 saml2 = new SAML2();
|
private SAML saml = new SAML();
|
||||||
private int loginAttemptCount;
|
private int loginAttemptCount;
|
||||||
private long loginResetTimeMinutes;
|
private long loginResetTimeMinutes;
|
||||||
private String loginMethod = "all";
|
private String loginMethod = "all";
|
||||||
|
|
||||||
public Boolean isAltLogin() {
|
|
||||||
return saml2.getEnabled() || oauth2.getEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum LoginMethods {
|
|
||||||
ALL("all"),
|
|
||||||
NORMAL("normal"),
|
|
||||||
OAUTH2("oauth2"),
|
|
||||||
SAML2("saml2");
|
|
||||||
|
|
||||||
private String method;
|
|
||||||
|
|
||||||
LoginMethods(String method) {
|
|
||||||
this.method = method;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUserPass() {
|
|
||||||
return (loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString())
|
|
||||||
|| loginMethod.equalsIgnoreCase(LoginMethods.ALL.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOauth2Activ() {
|
|
||||||
return (oauth2 != null
|
|
||||||
&& oauth2.getEnabled()
|
|
||||||
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSaml2Activ() {
|
|
||||||
return (saml2 != null
|
|
||||||
&& saml2.getEnabled()
|
|
||||||
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class InitialLogin {
|
public static class InitialLogin {
|
||||||
private String username;
|
private String username;
|
||||||
@ToString.Exclude private String password;
|
@ToString.Exclude private String password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Data
|
||||||
@Setter
|
public static class SAML {
|
||||||
public static class SAML2 {
|
|
||||||
private Boolean enabled = false;
|
private Boolean enabled = false;
|
||||||
private Boolean autoCreateUser = false;
|
private String entityId;
|
||||||
private Boolean blockRegistration = false;
|
private String registrationId;
|
||||||
private String registrationId = "stirling";
|
private String spBaseUrl;
|
||||||
private String idpMetadataUri;
|
private String idpMetadataLocation;
|
||||||
private String idpSingleLogoutUrl;
|
// private KeyStore keystore;
|
||||||
private String idpSingleLoginUrl;
|
private String privateKeyLocation;
|
||||||
private String idpIssuer;
|
private String certificateLocation;
|
||||||
private String idpCert;
|
private String singleLogoutBinding;
|
||||||
private String privateKey;
|
private String singleLogoutResponseUri;
|
||||||
private String spCert;
|
private String signingCertificate;
|
||||||
|
|
||||||
public InputStream getIdpMetadataUri() throws IOException {
|
// @Data
|
||||||
if (idpMetadataUri.startsWith("classpath:")) {
|
// public static class KeyStore {
|
||||||
return new ClassPathResource(idpMetadataUri.substring("classpath".length()))
|
// private String keystoreLocation;
|
||||||
.getInputStream();
|
// private String keystorePassword;
|
||||||
}
|
// private String keyAlias;
|
||||||
try {
|
// private String keyPassword;
|
||||||
URI uri = new URI(idpMetadataUri);
|
// private String realmCertificateAlias;
|
||||||
URL url = uri.toURL();
|
//
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
// public Resource getKeystoreResource() {
|
||||||
connection.setRequestMethod("GET");
|
// if (keystoreLocation.startsWith("classpath:")) {
|
||||||
return connection.getInputStream();
|
// return new ClassPathResource(
|
||||||
} catch (URISyntaxException e) {
|
// keystoreLocation.substring("classpath:".length()));
|
||||||
throw new IOException("Invalid URI format: " + idpMetadataUri, e);
|
// } else {
|
||||||
}
|
// return new FileSystemResource(keystoreLocation);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
public Resource getSpCert() {
|
// }
|
||||||
if (spCert.startsWith("classpath:")) {
|
|
||||||
return new ClassPathResource(spCert.substring("classpath:".length()));
|
|
||||||
} else {
|
|
||||||
return new FileSystemResource(spCert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resource getidpCert() {
|
|
||||||
if (idpCert.startsWith("classpath:")) {
|
|
||||||
return new ClassPathResource(idpCert.substring("classpath:".length()));
|
|
||||||
} else {
|
|
||||||
return new FileSystemResource(idpCert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resource getPrivateKey() {
|
|
||||||
if (privateKey.startsWith("classpath:")) {
|
|
||||||
return new ClassPathResource(privateKey.substring("classpath:".length()));
|
|
||||||
} else {
|
|
||||||
return new FileSystemResource(privateKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -290,7 +220,6 @@ public class ApplicationProperties {
|
|||||||
public static class EnterpriseEdition {
|
public static class EnterpriseEdition {
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
@ToString.Exclude private String key;
|
@ToString.Exclude private String key;
|
||||||
private int maxUsers;
|
|
||||||
private CustomMetadata customMetadata = new CustomMetadata();
|
private CustomMetadata customMetadata = new CustomMetadata();
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class Provider implements ProviderInterface {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
// throw new IllegalArgumentException(getName() + ": " + name + " is required!");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isValid(Collection<String> value, String name) {
|
protected boolean isValid(Collection<String> value, String name) {
|
||||||
@@ -26,55 +27,66 @@ public class Provider implements ProviderInterface {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
// throw new IllegalArgumentException(getName() + ": " + name + " is required!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getScopes() {
|
public Collection<String> getScopes() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getScope'");
|
throw new UnsupportedOperationException("Unimplemented method 'getScope'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setScopes(String scopes) {
|
public void setScopes(String scopes) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setScope'");
|
throw new UnsupportedOperationException("Unimplemented method 'setScope'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUseAsUsername() {
|
public String getUseAsUsername() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getUseAsUsername'");
|
throw new UnsupportedOperationException("Unimplemented method 'getUseAsUsername'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUseAsUsername(String useAsUsername) {
|
public void setUseAsUsername(String useAsUsername) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setUseAsUsername'");
|
throw new UnsupportedOperationException("Unimplemented method 'setUseAsUsername'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIssuer() {
|
public String getIssuer() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getIssuer'");
|
throw new UnsupportedOperationException("Unimplemented method 'getIssuer'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIssuer(String issuer) {
|
public void setIssuer(String issuer) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setIssuer'");
|
throw new UnsupportedOperationException("Unimplemented method 'setIssuer'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientSecret() {
|
public String getClientSecret() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getClientSecret'");
|
throw new UnsupportedOperationException("Unimplemented method 'getClientSecret'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setClientSecret(String clientSecret) {
|
public void setClientSecret(String clientSecret) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setClientSecret'");
|
throw new UnsupportedOperationException("Unimplemented method 'setClientSecret'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientId() {
|
public String getClientId() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getClientId'");
|
throw new UnsupportedOperationException("Unimplemented method 'getClientId'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setClientId(String clientId) {
|
public void setClientId(String clientId) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'setClientId'");
|
throw new UnsupportedOperationException("Unimplemented method 'setClientId'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package stirling.software.SPDF.model;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class SignatureFile {
|
|
||||||
private String fileName;
|
|
||||||
private String category; // "Personal" or "Shared"
|
|
||||||
}
|
|
||||||
@@ -50,7 +50,4 @@ public class SignPDFWithCertRequest extends PDFFile {
|
|||||||
description =
|
description =
|
||||||
"The page number where the signature should be visible. This is required if showSignature is set to true")
|
"The page number where the signature should be visible. This is required if showSignature is set to true")
|
||||||
private Integer pageNumber;
|
private Integer pageNumber;
|
||||||
|
|
||||||
@Schema(description = "Whether to visually show a signature logo along with the signature")
|
|
||||||
private boolean showLogo;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,36 +34,6 @@ public class CustomPDDocumentFactory {
|
|||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] createNewBytesBasedOnOldDocument(byte[] oldDocument) throws IOException {
|
|
||||||
PDDocument document = Loader.loadPDF(oldDocument);
|
|
||||||
return createNewBytesBasedOnOldDocument(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] createNewBytesBasedOnOldDocument(File oldDocument) throws IOException {
|
|
||||||
PDDocument document = Loader.loadPDF(oldDocument);
|
|
||||||
return createNewBytesBasedOnOldDocument(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] createNewBytesBasedOnOldDocument(PDDocument oldDocument) throws IOException {
|
|
||||||
pdfMetadataService.setMetadataToPdf(
|
|
||||||
oldDocument, pdfMetadataService.extractMetadataFromPdf(oldDocument), true);
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
oldDocument.save(baos);
|
|
||||||
oldDocument.close();
|
|
||||||
return baos.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PDDocument createNewDocumentBasedOnOldDocument(byte[] oldDocument) throws IOException {
|
|
||||||
PDDocument document = Loader.loadPDF(oldDocument);
|
|
||||||
return createNewDocumentBasedOnOldDocument(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PDDocument createNewDocumentBasedOnOldDocument(File oldDocument) throws IOException {
|
|
||||||
PDDocument document = Loader.loadPDF(oldDocument);
|
|
||||||
return createNewDocumentBasedOnOldDocument(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PDDocument createNewDocumentBasedOnOldDocument(PDDocument oldDocument)
|
public PDDocument createNewDocumentBasedOnOldDocument(PDDocument oldDocument)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
PDDocument document = new PDDocument();
|
PDDocument document = new PDDocument();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import com.posthog.java.PostHog;
|
import com.posthog.java.PostHog;
|
||||||
|
|
||||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -27,23 +26,20 @@ public class PostHogService {
|
|||||||
private final PostHog postHog;
|
private final PostHog postHog;
|
||||||
private final String uniqueId;
|
private final String uniqueId;
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
private final UserServiceInterface userService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PostHogService(
|
public PostHogService(
|
||||||
PostHog postHog,
|
PostHog postHog,
|
||||||
@Qualifier("UUID") String uuid,
|
@Qualifier("UUID") String uuid,
|
||||||
ApplicationProperties applicationProperties,
|
ApplicationProperties applicationProperties) {
|
||||||
@Autowired(required = false) UserServiceInterface userService) {
|
|
||||||
this.postHog = postHog;
|
this.postHog = postHog;
|
||||||
this.uniqueId = uuid;
|
this.uniqueId = uuid;
|
||||||
this.applicationProperties = applicationProperties;
|
this.applicationProperties = applicationProperties;
|
||||||
this.userService = userService;
|
|
||||||
captureSystemInfo();
|
captureSystemInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void captureSystemInfo() {
|
private void captureSystemInfo() {
|
||||||
if (!Boolean.parseBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -54,7 +50,7 @@ public class PostHogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void captureEvent(String eventName, Map<String, Object> properties) {
|
public void captureEvent(String eventName, Map<String, Object> properties) {
|
||||||
if (!Boolean.parseBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
postHog.capture(uniqueId, eventName, properties);
|
postHog.capture(uniqueId, eventName, properties);
|
||||||
@@ -138,10 +134,6 @@ public class PostHogService {
|
|||||||
}
|
}
|
||||||
metrics.put("application_properties", captureApplicationProperties());
|
metrics.put("application_properties", captureApplicationProperties());
|
||||||
|
|
||||||
if (userService != null) {
|
|
||||||
metrics.put("total_users_created", userService.getTotalUsersCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
metrics.put("error", e.getMessage());
|
metrics.put("error", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
package stirling.software.SPDF.service;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.thymeleaf.util.StringUtils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import stirling.software.SPDF.model.SignatureFile;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Slf4j
|
|
||||||
public class SignatureService {
|
|
||||||
|
|
||||||
private static final String SIGNATURE_BASE_PATH = "customFiles/signatures/";
|
|
||||||
private static final String ALL_USERS_FOLDER = "ALL_USERS";
|
|
||||||
|
|
||||||
public boolean hasAccessToFile(String username, String fileName) throws IOException {
|
|
||||||
validateFileName(fileName);
|
|
||||||
// Check if file exists in user's personal folder or ALL_USERS folder
|
|
||||||
Path userPath = Paths.get(SIGNATURE_BASE_PATH, username, fileName);
|
|
||||||
Path allUsersPath = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName);
|
|
||||||
|
|
||||||
return Files.exists(userPath) || Files.exists(allUsersPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<SignatureFile> getAvailableSignatures(String username) {
|
|
||||||
List<SignatureFile> signatures = new ArrayList<>();
|
|
||||||
|
|
||||||
// Get signatures from user's personal folder
|
|
||||||
if (!StringUtils.isEmptyOrWhitespace(username)) {
|
|
||||||
Path userFolder = Paths.get(SIGNATURE_BASE_PATH, username);
|
|
||||||
if (Files.exists(userFolder)) {
|
|
||||||
try {
|
|
||||||
signatures.addAll(getSignaturesFromFolder(userFolder, "Personal"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error reading user signatures folder", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get signatures from ALL_USERS folder
|
|
||||||
Path allUsersFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER);
|
|
||||||
if (Files.exists(allUsersFolder)) {
|
|
||||||
try {
|
|
||||||
signatures.addAll(getSignaturesFromFolder(allUsersFolder, "Shared"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error reading shared signatures folder", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return signatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SignatureFile> getSignaturesFromFolder(Path folder, String category)
|
|
||||||
throws IOException {
|
|
||||||
return Files.list(folder)
|
|
||||||
.filter(path -> isImageFile(path))
|
|
||||||
.map(path -> new SignatureFile(path.getFileName().toString(), category))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getSignatureBytes(String username, String fileName) throws IOException {
|
|
||||||
validateFileName(fileName);
|
|
||||||
// First try user's personal folder
|
|
||||||
Path userPath = Paths.get(SIGNATURE_BASE_PATH, username, fileName);
|
|
||||||
if (Files.exists(userPath)) {
|
|
||||||
return Files.readAllBytes(userPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then try ALL_USERS folder
|
|
||||||
Path allUsersPath = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName);
|
|
||||||
if (Files.exists(allUsersPath)) {
|
|
||||||
return Files.readAllBytes(allUsersPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new FileNotFoundException("Signature file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isImageFile(Path path) {
|
|
||||||
String fileName = path.getFileName().toString().toLowerCase();
|
|
||||||
return fileName.endsWith(".jpg")
|
|
||||||
|| fileName.endsWith(".jpeg")
|
|
||||||
|| fileName.endsWith(".png")
|
|
||||||
|| fileName.endsWith(".gif");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateFileName(String fileName) {
|
|
||||||
if (fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
|
|
||||||
throw new IllegalArgumentException("Invalid filename");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package stirling.software.SPDF.utils;
|
|
||||||
|
|
||||||
import org.owasp.html.HtmlPolicyBuilder;
|
|
||||||
import org.owasp.html.PolicyFactory;
|
|
||||||
import org.owasp.html.Sanitizers;
|
|
||||||
|
|
||||||
public class CustomHtmlSanitizer {
|
|
||||||
private static final PolicyFactory POLICY =
|
|
||||||
Sanitizers.FORMATTING
|
|
||||||
.and(Sanitizers.BLOCKS)
|
|
||||||
.and(Sanitizers.STYLES)
|
|
||||||
.and(Sanitizers.LINKS)
|
|
||||||
.and(Sanitizers.TABLES)
|
|
||||||
.and(Sanitizers.IMAGES)
|
|
||||||
.and(new HtmlPolicyBuilder().disallowElements("noscript").toFactory());
|
|
||||||
|
|
||||||
public static String sanitize(String html) {
|
|
||||||
String htmlAfter = POLICY.sanitize(html);
|
|
||||||
return htmlAfter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,23 +2,16 @@ package stirling.software.SPDF.utils;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.FileVisitResult;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
import io.github.pixee.security.ZipSecurity;
|
import io.github.pixee.security.ZipSecurity;
|
||||||
|
|
||||||
@@ -40,25 +33,19 @@ public class FileToPdf {
|
|||||||
try {
|
try {
|
||||||
if (fileName.endsWith(".html")) {
|
if (fileName.endsWith(".html")) {
|
||||||
tempInputFile = Files.createTempFile("input_", ".html");
|
tempInputFile = Files.createTempFile("input_", ".html");
|
||||||
String sanitizedHtml =
|
Files.write(tempInputFile, fileBytes);
|
||||||
sanitizeHtmlContent(new String(fileBytes, StandardCharsets.UTF_8));
|
} else {
|
||||||
Files.write(tempInputFile, sanitizedHtml.getBytes(StandardCharsets.UTF_8));
|
|
||||||
} 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);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unsupported file format: " + fileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> command = new ArrayList<>();
|
List<String> command = new ArrayList<>();
|
||||||
if (!htmlFormatsInstalled) {
|
if (!htmlFormatsInstalled) {
|
||||||
command.add("weasyprint");
|
command.add("weasyprint");
|
||||||
command.add("-e");
|
command.add("-e utf-8");
|
||||||
command.add("utf-8");
|
|
||||||
command.add("-v");
|
|
||||||
command.add(tempInputFile.toString());
|
command.add(tempInputFile.toString());
|
||||||
command.add(tempOutputFile.toString());
|
command.add(tempOutputFile.toString());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
command.add("ebook-convert");
|
command.add("ebook-convert");
|
||||||
command.add(tempInputFile.toString());
|
command.add(tempInputFile.toString());
|
||||||
@@ -67,8 +54,10 @@ public class FileToPdf {
|
|||||||
command.add("a4");
|
command.add("a4");
|
||||||
|
|
||||||
if (request != null && request.getZoom() != 1.0) {
|
if (request != null && request.getZoom() != 1.0) {
|
||||||
|
// Create a temporary CSS file
|
||||||
File tempCssFile = Files.createTempFile("customStyle", ".css").toFile();
|
File tempCssFile = Files.createTempFile("customStyle", ".css").toFile();
|
||||||
try (FileWriter writer = new FileWriter(tempCssFile)) {
|
try (FileWriter writer = new FileWriter(tempCssFile)) {
|
||||||
|
// Write the CSS rule to the file
|
||||||
writer.write("body { zoom: " + request.getZoom() + "; }");
|
writer.write("body { zoom: " + request.getZoom() + "; }");
|
||||||
}
|
}
|
||||||
command.add("--extra-css");
|
command.add("--extra-css");
|
||||||
@@ -76,7 +65,9 @@ public class FileToPdf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessExecutorResult returnCode =
|
ProcessExecutorResult returnCode;
|
||||||
|
|
||||||
|
returnCode =
|
||||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||||
.runCommandWithOutputHandling(command);
|
.runCommandWithOutputHandling(command);
|
||||||
|
|
||||||
@@ -87,6 +78,8 @@ public class FileToPdf {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
||||||
|
// Clean up temporary files
|
||||||
Files.deleteIfExists(tempOutputFile);
|
Files.deleteIfExists(tempOutputFile);
|
||||||
Files.deleteIfExists(tempInputFile);
|
Files.deleteIfExists(tempInputFile);
|
||||||
}
|
}
|
||||||
@@ -94,81 +87,6 @@ public class FileToPdf {
|
|||||||
return pdfBytes;
|
return pdfBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String sanitizeHtmlContent(String htmlContent) {
|
|
||||||
return CustomHtmlSanitizer.sanitize(htmlContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sanitizeHtmlFilesInZip(Path zipFilePath) throws IOException {
|
|
||||||
Path tempUnzippedDir = Files.createTempDirectory("unzipped_");
|
|
||||||
try (ZipInputStream zipIn =
|
|
||||||
ZipSecurity.createHardenedInputStream(
|
|
||||||
new ByteArrayInputStream(Files.readAllBytes(zipFilePath)))) {
|
|
||||||
ZipEntry entry = zipIn.getNextEntry();
|
|
||||||
while (entry != null) {
|
|
||||||
Path filePath = tempUnzippedDir.resolve(entry.getName());
|
|
||||||
if (!entry.isDirectory()) {
|
|
||||||
Files.createDirectories(filePath.getParent());
|
|
||||||
if (entry.getName().toLowerCase().endsWith(".html")
|
|
||||||
|| entry.getName().toLowerCase().endsWith(".htm")) {
|
|
||||||
String content = new String(zipIn.readAllBytes(), StandardCharsets.UTF_8);
|
|
||||||
String sanitizedContent = sanitizeHtmlContent(content);
|
|
||||||
Files.write(filePath, sanitizedContent.getBytes(StandardCharsets.UTF_8));
|
|
||||||
} else {
|
|
||||||
Files.copy(zipIn, filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zipIn.closeEntry();
|
|
||||||
entry = zipIn.getNextEntry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repack the sanitized files
|
|
||||||
zipDirectory(tempUnzippedDir, zipFilePath);
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
deleteDirectory(tempUnzippedDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void zipDirectory(Path sourceDir, Path zipFilePath) throws IOException {
|
|
||||||
try (ZipOutputStream zos =
|
|
||||||
new ZipOutputStream(new FileOutputStream(zipFilePath.toFile()))) {
|
|
||||||
Files.walk(sourceDir)
|
|
||||||
.filter(path -> !Files.isDirectory(path))
|
|
||||||
.forEach(
|
|
||||||
path -> {
|
|
||||||
ZipEntry zipEntry =
|
|
||||||
new ZipEntry(sourceDir.relativize(path).toString());
|
|
||||||
try {
|
|
||||||
zos.putNextEntry(zipEntry);
|
|
||||||
Files.copy(path, zos);
|
|
||||||
zos.closeEntry();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void deleteDirectory(Path dir) throws IOException {
|
|
||||||
Files.walkFileTree(
|
|
||||||
dir,
|
|
||||||
new SimpleFileVisitor<Path>() {
|
|
||||||
@Override
|
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
|
||||||
throws IOException {
|
|
||||||
Files.delete(file);
|
|
||||||
return FileVisitResult.CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
|
|
||||||
throws IOException {
|
|
||||||
Files.delete(dir);
|
|
||||||
return FileVisitResult.CONTINUE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Path unzipAndGetMainHtml(byte[] fileBytes) throws IOException {
|
private static Path unzipAndGetMainHtml(byte[] fileBytes) throws IOException {
|
||||||
Path tempDirectory = Files.createTempDirectory("unzipped_");
|
Path tempDirectory = Files.createTempDirectory("unzipped_");
|
||||||
try (ZipInputStream zipIn =
|
try (ZipInputStream zipIn =
|
||||||
|
|||||||
@@ -1,31 +1,13 @@
|
|||||||
package stirling.software.SPDF.utils;
|
package stirling.software.SPDF.utils;
|
||||||
|
|
||||||
import java.awt.geom.AffineTransform;
|
|
||||||
import java.awt.image.AffineTransformOp;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DataBuffer;
|
import java.awt.image.DataBuffer;
|
||||||
import java.awt.image.DataBufferByte;
|
import java.awt.image.DataBufferByte;
|
||||||
import java.awt.image.DataBufferInt;
|
import java.awt.image.DataBufferInt;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import com.drew.imaging.ImageMetadataReader;
|
|
||||||
import com.drew.imaging.ImageProcessingException;
|
|
||||||
import com.drew.metadata.Metadata;
|
|
||||||
import com.drew.metadata.MetadataException;
|
|
||||||
import com.drew.metadata.exif.ExifSubIFDDirectory;
|
|
||||||
|
|
||||||
public class ImageProcessingUtils {
|
public class ImageProcessingUtils {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
|
|
||||||
|
|
||||||
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
|
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
|
||||||
BufferedImage convertedImage;
|
BufferedImage convertedImage;
|
||||||
switch (colorType) {
|
switch (colorType) {
|
||||||
@@ -77,51 +59,4 @@ public class ImageProcessingUtils {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double extractImageOrientation(InputStream is) throws IOException {
|
|
||||||
try {
|
|
||||||
Metadata metadata = ImageMetadataReader.readMetadata(is);
|
|
||||||
ExifSubIFDDirectory directory =
|
|
||||||
metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
|
|
||||||
if (directory == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int orientationTag = directory.getInt(ExifSubIFDDirectory.TAG_ORIENTATION);
|
|
||||||
switch (orientationTag) {
|
|
||||||
case 1:
|
|
||||||
return 0;
|
|
||||||
case 6:
|
|
||||||
return 90;
|
|
||||||
case 3:
|
|
||||||
return 180;
|
|
||||||
case 8:
|
|
||||||
return 270;
|
|
||||||
default:
|
|
||||||
logger.warn("Unknown orientation tag: {}", orientationTag);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} catch (ImageProcessingException | MetadataException e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BufferedImage applyOrientation(BufferedImage image, double orientation) {
|
|
||||||
if (orientation == 0) {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
AffineTransform transform =
|
|
||||||
AffineTransform.getRotateInstance(
|
|
||||||
Math.toRadians(orientation),
|
|
||||||
image.getWidth() / 2.0,
|
|
||||||
image.getHeight() / 2.0);
|
|
||||||
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
|
|
||||||
return op.filter(image, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BufferedImage loadImageWithExifOrientation(MultipartFile file)
|
|
||||||
throws IOException {
|
|
||||||
BufferedImage image = ImageIO.read(file.getInputStream());
|
|
||||||
double orientation = extractImageOrientation(file.getInputStream());
|
|
||||||
return applyOrientation(image, orientation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,8 +194,7 @@ public class PdfUtils {
|
|||||||
|
|
||||||
pdfDocument.close();
|
pdfDocument.close();
|
||||||
|
|
||||||
// Assumes the expectedPageSize is in the format "widthxheight", e.g. "595x842"
|
// Assumes the expectedPageSize is in the format "widthxheight", e.g. "595x842" for A4
|
||||||
// for A4
|
|
||||||
String[] dimensions = expectedPageSize.split("x");
|
String[] dimensions = expectedPageSize.split("x");
|
||||||
float expectedPageWidth = Float.parseFloat(dimensions[0]);
|
float expectedPageWidth = Float.parseFloat(dimensions[0]);
|
||||||
float expectedPageHeight = Float.parseFloat(dimensions[1]);
|
float expectedPageHeight = Float.parseFloat(dimensions[1]);
|
||||||
@@ -408,7 +407,7 @@ public class PdfUtils {
|
|||||||
addImageToDocument(doc, pdImage, fitOption, autoRotate);
|
addImageToDocument(doc, pdImage, fitOption, autoRotate);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BufferedImage image = ImageProcessingUtils.loadImageWithExifOrientation(file);
|
BufferedImage image = ImageIO.read(file.getInputStream());
|
||||||
BufferedImage convertedImage =
|
BufferedImage convertedImage =
|
||||||
ImageProcessingUtils.convertColorType(image, colorType);
|
ImageProcessingUtils.convertColorType(image, colorType);
|
||||||
// Use JPEGFactory if it's JPEG since JPEG is lossy
|
// Use JPEGFactory if it's JPEG since JPEG is lossy
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -54,7 +53,7 @@ public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a temporary file, with the original filename from the multipart file
|
// Create a temporary file, with the original filename from the multipart file
|
||||||
File file = Files.createTempFile("temp", getFileInput().getOriginalFilename()).toFile();
|
File file = File.createTempFile("temp", getFileInput().getOriginalFilename());
|
||||||
|
|
||||||
// Transfer the content of the multipart file to the file
|
// Transfer the content of the multipart file to the file
|
||||||
getFileInput().transferTo(file);
|
getFileInput().transferTo(file);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ public class InvertFullColorStrategy extends ReplaceAndInvertColorStrategy {
|
|||||||
public InputStreamResource replace() throws IOException {
|
public InputStreamResource replace() throws IOException {
|
||||||
|
|
||||||
// Create a temporary file, with the original filename from the multipart file
|
// Create a temporary file, with the original filename from the multipart file
|
||||||
File file = Files.createTempFile("temp", getFileInput().getOriginalFilename()).toFile();
|
File file = File.createTempFile("temp", getFileInput().getOriginalFilename());
|
||||||
|
|
||||||
// Transfer the content of the multipart file to the file
|
// Transfer the content of the multipart file to the file
|
||||||
getFileInput().transferTo(file);
|
getFileInput().transferTo(file);
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=تبرع
|
|||||||
color=لون
|
color=لون
|
||||||
sponsor=راعٍ
|
sponsor=راعٍ
|
||||||
info=معلومات
|
info=معلومات
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=خط الأنابيب:
|
|||||||
pipelineOptions.saveButton=تنزيل
|
pipelineOptions.saveButton=تنزيل
|
||||||
pipelineOptions.validateButton=تحقق
|
pipelineOptions.validateButton=تحقق
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=تحويل من PDF
|
|||||||
navbar.sections.security=التوقيع والأمان
|
navbar.sections.security=التوقيع والأمان
|
||||||
navbar.sections.advance=متقدم
|
navbar.sections.advance=متقدم
|
||||||
navbar.sections.edit=عرض وتعديل
|
navbar.sections.edit=عرض وتعديل
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=لم يتم العثور على الملف
|
|||||||
database.fileNullOrEmpty=يجب ألا يكون الملف فارغًا أو خاليًا
|
database.fileNullOrEmpty=يجب ألا يكون الملف فارغًا أو خاليًا
|
||||||
database.failedImportFile=فشل استيراد الملف
|
database.failedImportFile=فشل استيراد الملف
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=إزالة الصورة
|
|||||||
home.removeImagePdf.desc=إزالة الصورة من PDF لتقليل حجم الملف
|
home.removeImagePdf.desc=إزالة الصورة من PDF لتقليل حجم الملف
|
||||||
removeImagePdf.tags=إزالة الصورة,عمليات الصفحة,الخلفية,جانب الخادم
|
removeImagePdf.tags=إزالة الصورة,عمليات الصفحة,الخلفية,جانب الخادم
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=تم رفض الوصول
|
|||||||
login.oauth2InvalidTokenResponse=استجابة الرمز المميز غير صالحة
|
login.oauth2InvalidTokenResponse=استجابة الرمز المميز غير صالحة
|
||||||
login.oauth2InvalidIdToken=رمز الهوية غير صالح
|
login.oauth2InvalidIdToken=رمز الهوية غير صالح
|
||||||
login.userIsDisabled=تم تعطيل المستخدم، تم حظر تسجيل الدخول حاليًا باستخدام اسم المستخدم هذا. يرجى الاتصال بالمسؤول.
|
login.userIsDisabled=تم تعطيل المستخدم، تم حظر تسجيل الدخول حاليًا باستخدام اسم المستخدم هذا. يرجى الاتصال بالمسؤول.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=حجب تلقائي
|
autoRedact.title=حجب تلقائي
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=لون التظليل 2:
|
|||||||
compare.document.1=المستند 1
|
compare.document.1=المستند 1
|
||||||
compare.document.2=المستند 2
|
compare.document.2=المستند 2
|
||||||
compare.submit=مقارنة
|
compare.submit=مقارنة
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=الكتب والكوميكس إلى PDF
|
BookToPDF.title=الكتب والكوميكس إلى PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=رسم التوقيع
|
|||||||
sign.text=إدخال النص
|
sign.text=إدخال النص
|
||||||
sign.clear=مسح
|
sign.clear=مسح
|
||||||
sign.add=إضافة
|
sign.add=إضافة
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=الترخيص
|
|||||||
survey.nav=استطلاع
|
survey.nav=استطلاع
|
||||||
survey.title=استطلاع Stirling-PDF
|
survey.title=استطلاع Stirling-PDF
|
||||||
survey.description=Stirling-PDF لا يحتوي على تتبع لذا نريد أن نسمع من مستخدمينا لتحسين Stirling-PDF!
|
survey.description=Stirling-PDF لا يحتوي على تتبع لذا نريد أن نسمع من مستخدمينا لتحسين Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=يرجى النظر في المشاركة في استطلاعنا!
|
survey.please=يرجى النظر في المشاركة في استطلاعنا!
|
||||||
survey.disabled=(سيتم تعطيل النافذة المنبثقة للاستطلاع في التحديثات التالية ولكنها ستكون متاحة في أسفل الصفحة)
|
survey.disabled=(سيتم تعطيل النافذة المنبثقة للاستطلاع في التحديثات التالية ولكنها ستكون متاحة في أسفل الصفحة)
|
||||||
survey.button=المشاركة في الاستطلاع
|
survey.button=المشاركة في الاستطلاع
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=إزالة الصورة
|
|||||||
removeImage.header=إزالة الصورة
|
removeImage.header=إزالة الصورة
|
||||||
removeImage.removeImage=إزالة الصورة
|
removeImage.removeImage=إزالة الصورة
|
||||||
removeImage.submit=إزالة الصورة
|
removeImage.submit=إزالة الصورة
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
###########
|
###########
|
||||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||||
language.direction=ltr
|
language.direction=ltr
|
||||||
addPageNumbers.fontSize=Размер на шрифт
|
addPageNumbers.fontSize=Font Size
|
||||||
addPageNumbers.fontName=Име на шрифт
|
addPageNumbers.fontName=Font Name
|
||||||
pdfPrompt=Изберете PDF(и)
|
pdfPrompt=Изберете PDF(и)
|
||||||
multiPdfPrompt=Изберете PDF (2+)
|
multiPdfPrompt=Изберете PDF (2+)
|
||||||
multiPdfDropPrompt=Изберете (или плъзнете и пуснете) всички PDF файлове, от които се нуждаете
|
multiPdfDropPrompt=Изберете (или плъзнете и пуснете) всички PDF файлове, от които се нуждаете
|
||||||
@@ -56,12 +56,12 @@ userNotFoundMessage=Потребителят не е намерен
|
|||||||
incorrectPasswordMessage=Текущата парола е неправилна.
|
incorrectPasswordMessage=Текущата парола е неправилна.
|
||||||
usernameExistsMessage=Новият потребител вече съществува.
|
usernameExistsMessage=Новият потребител вече съществува.
|
||||||
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
|
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
|
||||||
invalidPasswordMessage=Паролата не трябва да е празна и не трябва да има интервали в началото или в края.
|
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
||||||
confirmPasswordErrorMessage=Нова парола и Потвърждаване на новата парола трябва да съвпадат.
|
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||||
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
|
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
|
||||||
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
||||||
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
||||||
disabledCurrentUserMessage=Текущият потребител не може да бъде деактивиран
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
|
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
|
||||||
userAlreadyExistsOAuthMessage=Потребителят вече съществува като OAuth2 потребител.
|
userAlreadyExistsOAuthMessage=Потребителят вече съществува като OAuth2 потребител.
|
||||||
userAlreadyExistsWebMessage=Потребителят вече съществува като уеб-потребител.
|
userAlreadyExistsWebMessage=Потребителят вече съществува като уеб-потребител.
|
||||||
@@ -75,18 +75,15 @@ visitGithub=Посетете Github Repository
|
|||||||
donate=Направете дарение
|
donate=Направете дарение
|
||||||
color=Цвят
|
color=Цвят
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Информация
|
info=Info
|
||||||
pro=Pro
|
page=Page
|
||||||
page=Страница
|
pages=Pages
|
||||||
pages=Страници
|
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Политика за поверителност
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Правила и условия
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=Достъпност
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Политика за бисквитки
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=Отпечатък
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -98,7 +95,7 @@ pipeline.defaultOption=Персонализиран
|
|||||||
pipeline.submitButton=Подайте
|
pipeline.submitButton=Подайте
|
||||||
pipeline.help=Pipeline Помощ
|
pipeline.help=Pipeline Помощ
|
||||||
pipeline.scanHelp=Помощ за сканиране на папки
|
pipeline.scanHelp=Помощ за сканиране на папки
|
||||||
pipeline.deletePrompt=Сигурни ли сте, че искате да изтриете pipeline
|
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Изтегли
|
pipelineOptions.saveButton=Изтегли
|
||||||
pipelineOptions.validateButton=Валидирай
|
pipelineOptions.validateButton=Валидирай
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Направете надстройка до Pro версията
|
|
||||||
enterpriseEdition.warning=Тази функция е достъпна само за потребители на Pro версията.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro поддържа YAML конфигурационни файлове и други SSO функции.
|
|
||||||
enterpriseEdition.ssoAdvert=Търсите повече функции за управление на потребителите? Погледнете за Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Искате ли да подобрите Stirling PDF?
|
|
||||||
analytics.paragraph1=Stirling PDF включва анализи, за да ни помогне да подобрим продукта. Ние не проследяваме лична информация или съдържание на файлове.
|
|
||||||
analytics.paragraph2=Моля, обмислете възможността за анализ, за да помогнете на Stirling-PDF да расте и да ни позволи да разберем по-добре нашите потребители.
|
|
||||||
analytics.enable=Активиране на анализа
|
|
||||||
analytics.disable=Деактивиране на анализа
|
|
||||||
analytics.settings=Можете да промените настройките за анализ във config/settings.yml файла
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Преобразуване от PDF
|
|||||||
navbar.sections.security=Подписване и сигурност
|
navbar.sections.security=Подписване и сигурност
|
||||||
navbar.sections.advance=Разширено
|
navbar.sections.advance=Разширено
|
||||||
navbar.sections.edit=Преглед и редактиране
|
navbar.sections.edit=Преглед и редактиране
|
||||||
navbar.sections.popular=Популярни
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -204,9 +184,9 @@ adminUserSettings.header=Настройки за администраторск
|
|||||||
adminUserSettings.admin=Администратор
|
adminUserSettings.admin=Администратор
|
||||||
adminUserSettings.user=Потребител
|
adminUserSettings.user=Потребител
|
||||||
adminUserSettings.addUser=Добавяне на нов потребител
|
adminUserSettings.addUser=Добавяне на нов потребител
|
||||||
adminUserSettings.deleteUser=Изтриване на потребител
|
adminUserSettings.deleteUser=Delete User
|
||||||
adminUserSettings.confirmDeleteUser=Трябва ли потребителят да бъде изтрит?
|
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||||
adminUserSettings.confirmChangeUserStatus=Трябва ли потребителят да бъде деактивиран/активиран?
|
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
||||||
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
|
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
|
||||||
adminUserSettings.roles=Роли
|
adminUserSettings.roles=Роли
|
||||||
adminUserSettings.role=Роля
|
adminUserSettings.role=Роля
|
||||||
@@ -220,32 +200,30 @@ adminUserSettings.forceChange=Принудете потребителя да п
|
|||||||
adminUserSettings.submit=Съхранете потребителя
|
adminUserSettings.submit=Съхранете потребителя
|
||||||
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
||||||
adminUserSettings.authenticated=Удостоверен
|
adminUserSettings.authenticated=Удостоверен
|
||||||
adminUserSettings.editOwnProfil=Редактиране на собствен профил
|
adminUserSettings.editOwnProfil=Edit own profile
|
||||||
adminUserSettings.enabledUser=активиран потребител
|
adminUserSettings.enabledUser=enabled user
|
||||||
adminUserSettings.disabledUser=деактивиран потребител
|
adminUserSettings.disabledUser=disabled user
|
||||||
adminUserSettings.activeUsers=Активни потребители:
|
adminUserSettings.activeUsers=Active Users:
|
||||||
adminUserSettings.disabledUsers=Деактивирани потребители:
|
adminUserSettings.disabledUsers=Disabled Users:
|
||||||
adminUserSettings.totalUsers=Общо потребители:
|
adminUserSettings.totalUsers=Total Users:
|
||||||
adminUserSettings.lastRequest=Последна заявка
|
adminUserSettings.lastRequest=Last Request
|
||||||
|
|
||||||
|
|
||||||
database.title=Импорт/Експорт на база данни
|
database.title=Database Import/Export
|
||||||
database.header=Импорт/Експорт на база данни
|
database.header=Database Import/Export
|
||||||
database.fileName=Име на файл
|
database.fileName=File Name
|
||||||
database.creationDate=Дата на създаване
|
database.creationDate=Creation Date
|
||||||
database.fileSize=Размер на файла
|
database.fileSize=File Size
|
||||||
database.deleteBackupFile=Изтриване на архивен файл
|
database.deleteBackupFile=Delete Backup File
|
||||||
database.importBackupFile=Импортиране на архивен файл
|
database.importBackupFile=Import Backup File
|
||||||
database.downloadBackupFile=Изтеглете архивен файл
|
database.downloadBackupFile=Download Backup File
|
||||||
database.info_1=Когато импортирате данни, е от решаващо значение да осигурите правилната структура. Ако не сте сигурни в това, което правите, потърсете съвет и подкрепа от професионалист. Грешка в структурата може да причини неизправност на приложението, включително пълна невъзможност за стартиране на приложението.
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
database.info_2=Името на файла няма значение при качване. След това ще бъде преименуван, за да следва формата backup_user_yyyyMMddHHmm.sql, осигурявайки последователна конвенция за именуване.
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
database.submit=Импортиране на резервно копие
|
database.submit=Import Backup
|
||||||
database.importIntoDatabaseSuccessed=Импортирането в базата данни бе успешно
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
database.fileNotFound=Файлът не е намерен
|
database.fileNotFound=File not Found
|
||||||
database.fileNullOrEmpty=Файлът не трябва да е нулев или празен
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Неуспешно импортиране на файл
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Вашата сесия е изтекла. Моля, опреснете страницата и опитайте отново.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -392,9 +370,9 @@ home.certSign.title=Подпишете със сертификат
|
|||||||
home.certSign.desc=Подписва PDF със сертификат/ключ (PEM/P12)
|
home.certSign.desc=Подписва PDF със сертификат/ключ (PEM/P12)
|
||||||
certSign.tags=удостоверяване,PEM,P12,официален,шифроване
|
certSign.tags=удостоверяване,PEM,P12,официален,шифроване
|
||||||
|
|
||||||
home.removeCertSign.title=Премахване на знака за сертификат
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
home.removeCertSign.desc=Премахване на подпис на сертификат от PDF
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
removeCertSign.tags=удостоверяване,PEM,P12,официален,декриптиране
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Оформление с няколко страници
|
home.pageLayout.title=Оформление с няколко страници
|
||||||
home.pageLayout.desc=Слейте няколко страници от PDF документ в една страница
|
home.pageLayout.desc=Слейте няколко страници от PDF документ в една страница
|
||||||
@@ -500,33 +478,28 @@ home.BookToPDF.title=Книга към PDF
|
|||||||
home.BookToPDF.desc=Преобразува формати на книги/комикси в PDF с помощта на calibre
|
home.BookToPDF.desc=Преобразува формати на книги/комикси в PDF с помощта на calibre
|
||||||
BookToPDF.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
|
BookToPDF.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Премахване на изображение
|
home.removeImagePdf.title=Remove image
|
||||||
home.removeImagePdf.desc=Премахнете изображението от PDF, за да намалите размера на файла
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Премахване на изображение, операции на страници, админ страна, страна на сървъра
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Разделете PDF по глави
|
|
||||||
home.splitPdfByChapters.desc=Разделете PDF на множество файлове въз основа на неговата структура на глави.
|
|
||||||
splitPdfByChapters.tags=разделяне, глави, отметки, организиране
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Замени-инвертиране-на-цвят
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Замяна-инвертиране на цвят PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Замяна и обръщане на цвят
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Заменете цвета на текста и фона в PDF и обърнете пълния цвят на PDF, за да намалите размера на файла
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Замяна на цвят, операции на страници, заден край, страна на сървъра
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Опции за замяна или инвертиране на цвят
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=По подразбиране (цветове с висок контраст по подразбиране)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=По избор (персонализирани цветове)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Пълно инвертиране (Инвертиране на всички цветове)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Цветови опции с висок контраст
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=Бял текст на черен фон
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Черен текст на бял фон
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Жълт текст на черен фон
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Зелен текст на черен фон
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Изберете цвят на текста
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Изберете цвят на фона
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Замени
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -545,17 +518,15 @@ login.locked=Вашият акаунт е заключен.
|
|||||||
login.signinTitle=Моля впишете се
|
login.signinTitle=Моля впишете се
|
||||||
login.ssoSignIn=Влизане чрез еднократно влизане
|
login.ssoSignIn=Влизане чрез еднократно влизане
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
|
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
|
||||||
login.oauth2AdminBlockedUser=Регистрацията или влизането на нерегистрирани потребители в момента е блокирано. Моля, свържете се с администратора.
|
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
||||||
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
|
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
|
||||||
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
|
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
|
||||||
login.oauth2invalidRequest=Невалидна заявка
|
login.oauth2invalidRequest=Невалидна заявка
|
||||||
login.oauth2AccessDenied=Отказан достъп
|
login.oauth2AccessDenied=Отказан достъп
|
||||||
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
||||||
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
||||||
login.userIsDisabled=Потребителят е деактивиран, влизането в момента е блокирано с това потребителско име. Моля, свържете се с администратора.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=Вече сте влезли в
|
|
||||||
login.alreadyLoggedIn2=устройства. Моля, излезте от устройствата и опитайте отново.
|
|
||||||
login.toManySessions=Имате твърде много активни сесии
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматично редактиране
|
autoRedact.title=Автоматично редактиране
|
||||||
@@ -730,7 +701,7 @@ pageLayout.submit=Подайте
|
|||||||
scalePages.title=Коригиране на мащаба на страницата
|
scalePages.title=Коригиране на мащаба на страницата
|
||||||
scalePages.header=Коригиране на мащаба на страницата
|
scalePages.header=Коригиране на мащаба на страницата
|
||||||
scalePages.pageSize=Размер на страница от документа.
|
scalePages.pageSize=Размер на страница от документа.
|
||||||
scalePages.keepPageSize=Оригинален размер
|
scalePages.keepPageSize=Original Size
|
||||||
scalePages.scaleFactor=Ниво на мащабиране (изрязване) на страница.
|
scalePages.scaleFactor=Ниво на мащабиране (изрязване) на страница.
|
||||||
scalePages.submit=Подайте
|
scalePages.submit=Подайте
|
||||||
|
|
||||||
@@ -754,10 +725,10 @@ certSign.submit=Подпишете PDF
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Премахване на подписа на сертификата
|
removeCertSign.title=Remove Certificate Signature
|
||||||
removeCertSign.header=Премахнете цифровия сертификат от PDF
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
removeCertSign.selectPDF=Изберете PDF файл:
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
removeCertSign.submit=Премахване на подпис
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
@@ -779,14 +750,11 @@ removeAnnotations.submit=Премахване
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Сравнявай
|
compare.title=Сравнявай
|
||||||
compare.header=Сравнявай PDF-и
|
compare.header=Сравнявай PDF-и
|
||||||
compare.highlightColor.1=Цвят на маркирането 1:
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
compare.highlightColor.2=Цвят на маркирането 2:
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Сравнявай
|
compare.submit=Сравнявай
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Книги и комикси в PDF
|
BookToPDF.title=Книги и комикси в PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Начертайте подпис
|
|||||||
sign.text=Въвеждане на текст
|
sign.text=Въвеждане на текст
|
||||||
sign.clear=Изчисти
|
sign.clear=Изчисти
|
||||||
sign.add=Добави
|
sign.add=Добави
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -840,7 +803,7 @@ ScannerImageSplit.selectText.7=Минимална контурна площ:
|
|||||||
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
|
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
|
||||||
ScannerImageSplit.selectText.9=Размер на рамката:
|
ScannerImageSplit.selectText.9=Размер на рамката:
|
||||||
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
|
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
|
||||||
ScannerImageSplit.info=Python не е инсталиран. Изисква се да се изпълнява.
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -867,7 +830,7 @@ ocr.submit=Обработка на PDF чрез OCR
|
|||||||
extractImages.title=Извличане на изображения
|
extractImages.title=Извличане на изображения
|
||||||
extractImages.header=Извличане на изображения
|
extractImages.header=Извличане на изображения
|
||||||
extractImages.selectText=Изберете формат на изображението, в който да преобразувате извлечените изображения
|
extractImages.selectText=Изберете формат на изображението, в който да преобразувате извлечените изображения
|
||||||
extractImages.allowDuplicates=Запазване на дублирани изображения
|
extractImages.allowDuplicates=Save duplicate images
|
||||||
extractImages.submit=Извличане
|
extractImages.submit=Извличане
|
||||||
|
|
||||||
|
|
||||||
@@ -905,7 +868,7 @@ merge.title=Обединяване
|
|||||||
merge.header=Обединяване на множество PDF файлове (2+)
|
merge.header=Обединяване на множество PDF файлове (2+)
|
||||||
merge.sortByName=Сортиране по име
|
merge.sortByName=Сортиране по име
|
||||||
merge.sortByDate=Сортиране по дата
|
merge.sortByDate=Сортиране по дата
|
||||||
merge.removeCertSign=Премахване на цифровия подпис в обединения файл?
|
merge.removeCertSign=Remove digital signature in the merged file?
|
||||||
merge.submit=Обединяване
|
merge.submit=Обединяване
|
||||||
|
|
||||||
|
|
||||||
@@ -923,7 +886,7 @@ pdfOrganiser.mode.6=Четно-нечетно разделяне
|
|||||||
pdfOrganiser.mode.7=Премахни първо
|
pdfOrganiser.mode.7=Премахни първо
|
||||||
pdfOrganiser.mode.8=Премахване на последния
|
pdfOrganiser.mode.8=Премахване на последния
|
||||||
pdfOrganiser.mode.9=Премахване на първия и последния
|
pdfOrganiser.mode.9=Премахване на първия и последния
|
||||||
pdfOrganiser.mode.10=Обединяване на четно и нечетно
|
pdfOrganiser.mode.10=Odd-Even Merge
|
||||||
pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
|
pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
|
||||||
|
|
||||||
|
|
||||||
@@ -992,7 +955,7 @@ pdfToImage.color=Цвят
|
|||||||
pdfToImage.grey=Скала на сивото
|
pdfToImage.grey=Скала на сивото
|
||||||
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
|
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
|
||||||
pdfToImage.submit=Преобразуване
|
pdfToImage.submit=Преобразуване
|
||||||
pdfToImage.info=Python не е инсталиран. Изисква се за конвертиране на WebP.
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1029,7 +992,7 @@ watermark.selectText.6=дължинаSpacer (Разстояние между в
|
|||||||
watermark.selectText.7=Непрозрачност (0% - 100%):
|
watermark.selectText.7=Непрозрачност (0% - 100%):
|
||||||
watermark.selectText.8=Тип воден знак:
|
watermark.selectText.8=Тип воден знак:
|
||||||
watermark.selectText.9=Изображение за воден знак:
|
watermark.selectText.9=Изображение за воден знак:
|
||||||
watermark.selectText.10=Конвертирайте PDF в PDF-изображение
|
watermark.selectText.10=Convert PDF to PDF-Image
|
||||||
watermark.submit=Добавяне на воден знак
|
watermark.submit=Добавяне на воден знак
|
||||||
watermark.type.1=Текст
|
watermark.type.1=Текст
|
||||||
watermark.type.2=Изображение
|
watermark.type.2=Изображение
|
||||||
@@ -1086,7 +1049,7 @@ pdfToPDFA.credit=Тази услуга използва ghostscript за PDF/A
|
|||||||
pdfToPDFA.submit=Преобразуване
|
pdfToPDFA.submit=Преобразуване
|
||||||
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
|
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
|
||||||
pdfToPDFA.outputFormat=Изходен формат
|
pdfToPDFA.outputFormat=Изходен формат
|
||||||
pdfToPDFA.pdfWithDigitalSignature=PDF файлът съдържа цифров подпис. Това ще бъде премахнато в следващата стъпка.
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
@@ -1127,10 +1090,10 @@ PDFToXML.credit=Тази услуга използва LibreOffice за прео
|
|||||||
PDFToXML.submit=Преобразуване
|
PDFToXML.submit=Преобразуване
|
||||||
|
|
||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF към CSV
|
PDFToCSV.title=PDF ??? CSV
|
||||||
PDFToCSV.header=PDF към CSV
|
PDFToCSV.header=PDF ??? CSV
|
||||||
PDFToCSV.prompt=Изберете страница за извличане на таблица
|
PDFToCSV.prompt=Изберете страница за извличане на таблица
|
||||||
PDFToCSV.submit=Преобразуване
|
PDFToCSV.submit=????
|
||||||
|
|
||||||
#split-by-size-or-count
|
#split-by-size-or-count
|
||||||
split-by-size-or-count.title=Разделяне на PDF по размер или брой
|
split-by-size-or-count.title=Разделяне на PDF по размер или брой
|
||||||
@@ -1188,15 +1151,13 @@ licenses.version=Версия
|
|||||||
licenses.license=Лиценз
|
licenses.license=Лиценз
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Анкета
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Анкета
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF няма проследяване, така че искаме да чуем мнението на нашите потребители за подобряване на Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF се промени от последното проучване! За да научите повече, моля, проверете публикацията в нашия блог тук:
|
survey.please=Please consider taking our survey!
|
||||||
survey.changes2=С тези промени получаваме платена бизнес подкрепа и финансиране
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.please=Моля, помислете дали да не участвате в нашата анкета!
|
survey.button=Take Survey
|
||||||
survey.disabled=(Изскачащият прозорец с анкетата ще бъде деактивиран при следващите актуализации, но ще бъде наличен в долната част на страницата)
|
survey.dontShowAgain=Don't show again
|
||||||
survey.button=Участвайте в анкетата
|
|
||||||
survey.dontShowAgain=Не показвай повече
|
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
@@ -1214,19 +1175,7 @@ error.discordSubmit=Discord - Изпратете запитване за под
|
|||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Премахване на изображението
|
removeImage.title=Remove image
|
||||||
removeImage.header=Премахване на изображението
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Премахване на изображението
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Премахване на изображението
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Разделете PDF по глави
|
|
||||||
splitByChapters.header=Разделете PDF по глави
|
|
||||||
splitByChapters.bookmarkLevel=Ниво на отметка
|
|
||||||
splitByChapters.includeMetadata=Включете метаданни
|
|
||||||
splitByChapters.allowDuplicates=Разрешаване на дубликати
|
|
||||||
splitByChapters.desc.1=Този инструмент разделя PDF файл на множество PDF файлове въз основа на неговата структура на глави.
|
|
||||||
splitByChapters.desc.2=Ниво на отметка: Изберете нивото на отметките, които да използвате за разделяне (0 за най-високо ниво, 1 за второ ниво и т.н.).
|
|
||||||
splitByChapters.desc.3=Включване на метаданни: Ако е отметнато, метаданните на оригиналния PDF ще бъдат включени във всеки разделен PDF.
|
|
||||||
splitByChapters.desc.4=Разрешаване на дубликати: Ако е отметнато, позволява множество отметки на една и съща страница за създаване на отделни PDF файлове.
|
|
||||||
splitByChapters.submit=Разделяне на PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validate
|
pipelineOptions.validateButton=Validate
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Dibuixa la signatura
|
|||||||
sign.text=Entrada de text
|
sign.text=Entrada de text
|
||||||
sign.clear=Esborrar
|
sign.clear=Esborrar
|
||||||
sign.add=Afegeix
|
sign.add=Afegeix
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=License
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Přispějte
|
|||||||
color=Barva
|
color=Barva
|
||||||
sponsor=Sponzor
|
sponsor=Sponzor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Stáhnout
|
pipelineOptions.saveButton=Stáhnout
|
||||||
pipelineOptions.validateButton=Ověřit
|
pipelineOptions.validateButton=Ověřit
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Převést z PDF
|
|||||||
navbar.sections.security=Podpis a Bezpečnost
|
navbar.sections.security=Podpis a Bezpečnost
|
||||||
navbar.sections.advance=Pokročilé
|
navbar.sections.advance=Pokročilé
|
||||||
navbar.sections.edit=Prohlédnout a Upravit
|
navbar.sections.edit=Prohlédnout a Upravit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porovnat
|
compare.submit=Porovnat
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Knihy a komiksy do PDF
|
BookToPDF.title=Knihy a komiksy do PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Nakreslit podpis
|
|||||||
sign.text=Vstup textu
|
sign.text=Vstup textu
|
||||||
sign.clear=Vymazat
|
sign.clear=Vymazat
|
||||||
sign.add=Přidat
|
sign.add=Přidat
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licence
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donér
|
|||||||
color=Farve
|
color=Farve
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validér
|
pipelineOptions.validateButton=Validér
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Konvertér fra PDF
|
|||||||
navbar.sections.security=Signér & Sikkerhed
|
navbar.sections.security=Signér & Sikkerhed
|
||||||
navbar.sections.advance=Avanceret
|
navbar.sections.advance=Avanceret
|
||||||
navbar.sections.edit=Vis & Redigér
|
navbar.sections.edit=Vis & Redigér
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=Fil ikke fundet
|
|||||||
database.fileNullOrEmpty=Fil må ikke være null eller tom
|
database.fileNullOrEmpty=Fil må ikke være null eller tom
|
||||||
database.failedImportFile=Kunne ikke importere fil
|
database.failedImportFile=Kunne ikke importere fil
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Fjern billede
|
|||||||
home.removeImagePdf.desc=Fjern billede fra PDF for at reducere filstørrelse
|
home.removeImagePdf.desc=Fjern billede fra PDF for at reducere filstørrelse
|
||||||
removeImagePdf.tags=Fjern Billede,Sideoperationer,Back end,server side
|
removeImagePdf.tags=Fjern Billede,Sideoperationer,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Adgang Nægtet
|
|||||||
login.oauth2InvalidTokenResponse=Ugyldigt Token Svar
|
login.oauth2InvalidTokenResponse=Ugyldigt Token Svar
|
||||||
login.oauth2InvalidIdToken=Ugyldigt Id Token
|
login.oauth2InvalidIdToken=Ugyldigt Id Token
|
||||||
login.userIsDisabled=Bruger er deaktiveret, login er i øjeblikket blokeret med dette brugernavn. Kontakt venligst administratoren.
|
login.userIsDisabled=Bruger er deaktiveret, login er i øjeblikket blokeret med dette brugernavn. Kontakt venligst administratoren.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Rediger
|
autoRedact.title=Auto Rediger
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Fremhævningsfarve 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Sammenlign
|
compare.submit=Sammenlign
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Bøger og Tegneserier til PDF
|
BookToPDF.title=Bøger og Tegneserier til PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Tegn Underskrift
|
|||||||
sign.text=Tekstinput
|
sign.text=Tekstinput
|
||||||
sign.clear=Ryd
|
sign.clear=Ryd
|
||||||
sign.add=Tilføj
|
sign.add=Tilføj
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=License
|
|||||||
survey.nav=Undersøgelse
|
survey.nav=Undersøgelse
|
||||||
survey.title=Stirling-PDF Undersøgelse
|
survey.title=Stirling-PDF Undersøgelse
|
||||||
survey.description=Stirling-PDF har ingen sporing, så vi vil gerne høre fra vores brugere for at forbedre Stirling-PDF!
|
survey.description=Stirling-PDF har ingen sporing, så vi vil gerne høre fra vores brugere for at forbedre Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Overvej venligst at deltage i vores undersøgelse!
|
survey.please=Overvej venligst at deltage i vores undersøgelse!
|
||||||
survey.disabled=(Undersøgelsespop-up vil blive deaktiveret i følgende opdateringer, men vil være tilgængelig i bunden af siden)
|
survey.disabled=(Undersøgelsespop-up vil blive deaktiveret i følgende opdateringer, men vil være tilgængelig i bunden af siden)
|
||||||
survey.button=Tag Undersøgelsen
|
survey.button=Tag Undersøgelsen
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Fjern billede
|
|||||||
removeImage.header=Fjern billede
|
removeImage.header=Fjern billede
|
||||||
removeImage.removeImage=Fjern billede
|
removeImage.removeImage=Fjern billede
|
||||||
removeImage.submit=Fjern
|
removeImage.submit=Fjern
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Spenden
|
|||||||
color=Farbe
|
color=Farbe
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Informationen
|
info=Informationen
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Datenschutz
|
legal.privacy=Datenschutz
|
||||||
legal.terms=AGB
|
legal.terms=AGB
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Herunterladen
|
pipelineOptions.saveButton=Herunterladen
|
||||||
pipelineOptions.validateButton=Validieren
|
pipelineOptions.validateButton=Validieren
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Auf Pro-Version umsteigen
|
|
||||||
enterpriseEdition.warning=Diese Funktion ist nur für Pro-Nutzer verfügbar.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling-PDF Pro unterstützt YAML Konfigurationsdateien, SSO und weitere Funktionen.
|
|
||||||
enterpriseEdition.ssoAdvert=Suchen Sie weitere Funktionen in der Benutzerverwaltung? Steigen Sie auf die Pro-Version um
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Möchten Sie Stirling-PDF verbessern?
|
|
||||||
analytics.paragraph1=Stirling-PDF verfügt über Opt-in-Analytics, die uns helfen, das Produkt zu verbessern. Wir zeichnen keine persönlichen Informationen oder Dateiinhalte auf.
|
|
||||||
analytics.paragraph2=Bitte erwägen Sie die Analytics zu aktivieren, um Stirling-PDF beim Wachsen zu helfen und um unsere User besser zu verstehen.
|
|
||||||
analytics.enable=Analytics aktivieren
|
|
||||||
analytics.disable=Analytics deaktivieren
|
|
||||||
analytics.settings=Sie können die Einstellungen für die Analytics in der config/settings.yml Datei bearbeiten
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Konvertieren von PDF
|
|||||||
navbar.sections.security=Zeichen und Sicherheit
|
navbar.sections.security=Zeichen und Sicherheit
|
||||||
navbar.sections.advance=Fortschrittlich
|
navbar.sections.advance=Fortschrittlich
|
||||||
navbar.sections.edit=Anzeigen und Bearbeiten
|
navbar.sections.edit=Anzeigen und Bearbeiten
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ 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
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -394,7 +372,7 @@ certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
|
|||||||
|
|
||||||
home.removeCertSign.title=Zertifikatsignatur entfernen
|
home.removeCertSign.title=Zertifikatsignatur entfernen
|
||||||
home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
|
home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
|
||||||
removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln
|
removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Mehrseitiges Layout
|
home.pageLayout.title=Mehrseitiges Layout
|
||||||
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
||||||
@@ -504,29 +482,24 @@ home.removeImagePdf.title=Bild entfernen
|
|||||||
home.removeImagePdf.desc=Bild aus PDF entfernen, um die Dateigröße zu verringern
|
home.removeImagePdf.desc=Bild aus PDF entfernen, um die Dateigröße zu verringern
|
||||||
removeImagePdf.tags=bild entfernen,seitenoperationen,back end,server side
|
removeImagePdf.tags=bild entfernen,seitenoperationen,back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=PDF-Datei nach Kapiteln aufteilen
|
|
||||||
home.splitPdfByChapters.desc=Aufteilung einer PDF-Datei in mehrere Dateien auf Basis der Kapitelstruktur.
|
|
||||||
splitPdfByChapters.tags=aufteilen,kapitel,lesezeichen,organisieren
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Farbe Ersetzen-Invertieren
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Farb-PDF Ersetzen-Invertieren
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Farbe ersetzen und invertieren
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Ersetzen Sie die Farbe des Texts und Hintergrund der PDF-Datei und invertieren Sie die komplette Farbe der PDF-Datei, um die Dateigröße zu reduzieren
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Farbe ersetzen,Seiteneinstellungen,Backend,Serverseite
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Ersetzen oder Invertieren von Farboptionen
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Standard(Standardfarben mit hohem Kontrast)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Benutzerdefiniert(Benutzerdefinierte Farben)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Vollinvertierung(Invertierung aller Farben)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Farboptionen mit hohem Kontrast
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=Weißer Text auf schwarzem Hintergrund
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Schwarzer Text auf weißem Hintergrund
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Gelber Text auf schwarzem Hintergrund
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Grüner Text auf schwarzem Hintergrund
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Textfarbe auswählen
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Hintergrundfarbe auswählen
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Ersetzen
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Zugriff abgelehnt
|
|||||||
login.oauth2InvalidTokenResponse=Ungültige Token-Antwort
|
login.oauth2InvalidTokenResponse=Ungültige Token-Antwort
|
||||||
login.oauth2InvalidIdToken=Ungültiges ID-Token
|
login.oauth2InvalidIdToken=Ungültiges ID-Token
|
||||||
login.userIsDisabled=Benutzer ist deaktiviert, die Anmeldung ist mit diesem Benutzernamen derzeit gesperrt. Bitte wenden Sie sich an den Administrator.
|
login.userIsDisabled=Benutzer ist deaktiviert, die Anmeldung ist mit diesem Benutzernamen derzeit gesperrt. Bitte wenden Sie sich an den Administrator.
|
||||||
login.alreadyLoggedIn=Sie sind bereits an
|
|
||||||
login.alreadyLoggedIn2=Geräten angemeldet. Bitte melden Sie sich dort ab und versuchen es dann erneut.
|
|
||||||
login.toManySessions=Sie haben zu viele aktive Sitzungen
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisch zensieren/schwärzen
|
autoRedact.title=Automatisch zensieren/schwärzen
|
||||||
@@ -705,7 +676,7 @@ autoSplitPDF.header=PDF automatisch teilen
|
|||||||
autoSplitPDF.description=Drucken Sie, fügen Sie ein, scannen Sie, laden Sie hoch und lassen Sie uns Ihre Dokumente automatisch trennen. Kein manuelles Sortieren erforderlich.
|
autoSplitPDF.description=Drucken Sie, fügen Sie ein, scannen Sie, laden Sie hoch und lassen Sie uns Ihre Dokumente automatisch trennen. Kein manuelles Sortieren erforderlich.
|
||||||
autoSplitPDF.selectText.1=Drucken Sie einige Trennblätter aus (schwarz/weiß ist ausreichend).
|
autoSplitPDF.selectText.1=Drucken Sie einige Trennblätter aus (schwarz/weiß ist ausreichend).
|
||||||
autoSplitPDF.selectText.2=Scannen Sie alle Dokumente auf einmal, indem Sie das Trennblatt zwischen die Dokumente einlegen.
|
autoSplitPDF.selectText.2=Scannen Sie alle Dokumente auf einmal, indem Sie das Trennblatt zwischen die Dokumente einlegen.
|
||||||
autoSplitPDF.selectText.3=Laden Sie die einzelne große gescannte PDF-Datei hoch und überlassen Sie Stirling-PDF den Rest.
|
autoSplitPDF.selectText.3=Laden Sie die einzelne große gescannte PDF-Datei hoch und überlassen Sie Stirling PDF den Rest.
|
||||||
autoSplitPDF.selectText.4=Trennseiten werden automatisch erkannt und entfernt, so dass ein sauberes Enddokument garantiert ist.
|
autoSplitPDF.selectText.4=Trennseiten werden automatisch erkannt und entfernt, so dass ein sauberes Enddokument garantiert ist.
|
||||||
autoSplitPDF.formPrompt=PDF mit Stirling-PDF Seitentrennern hochladen:
|
autoSplitPDF.formPrompt=PDF mit Stirling-PDF Seitentrennern hochladen:
|
||||||
autoSplitPDF.duplexMode=Duplex-Modus (Scannen von Vorder- und Rückseite)
|
autoSplitPDF.duplexMode=Duplex-Modus (Scannen von Vorder- und Rückseite)
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight-Farbe 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Vergleichen
|
compare.submit=Vergleichen
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Bücher und Comics zu PDF
|
BookToPDF.title=Bücher und Comics zu PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Signatur zeichnen
|
|||||||
sign.text=Texteingabe
|
sign.text=Texteingabe
|
||||||
sign.clear=Leeren
|
sign.clear=Leeren
|
||||||
sign.add=Signieren
|
sign.add=Signieren
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Lizenz
|
|||||||
survey.nav=Umfrage
|
survey.nav=Umfrage
|
||||||
survey.title=Stirling-PDF-Umfrage
|
survey.title=Stirling-PDF-Umfrage
|
||||||
survey.description=Stirling-PDF hat kein Tracking, daher möchten wir von unseren Benutzern hören, wie wir Stirling-PDF verbessern können!
|
survey.description=Stirling-PDF hat kein Tracking, daher möchten wir von unseren Benutzern hören, wie wir Stirling-PDF verbessern können!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Bitte nehmen Sie an unserer Umfrage teil!
|
survey.please=Bitte nehmen Sie an unserer Umfrage teil!
|
||||||
survey.disabled=(Das Umfrage-Popup wird in folgenden Updates deaktiviert, ist aber am Fuß der Seite verfügbar.)
|
survey.disabled=(Das Umfrage-Popup wird in folgenden Updates deaktiviert, ist aber am Fuß der Seite verfügbar.)
|
||||||
survey.button=Umfrage durchführen
|
survey.button=Umfrage durchführen
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Bild entfernen
|
|||||||
removeImage.header=Bild entfernen
|
removeImage.header=Bild entfernen
|
||||||
removeImage.removeImage=Bild entfernen
|
removeImage.removeImage=Bild entfernen
|
||||||
removeImage.submit=Bild entfernen
|
removeImage.submit=Bild entfernen
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=PDF nach Kapiteln aufteilen
|
|
||||||
splitByChapters.header=PDF nach Kapiteln aufteilen
|
|
||||||
splitByChapters.bookmarkLevel=Lesezeichenebene
|
|
||||||
splitByChapters.includeMetadata=Metadaten einschließen
|
|
||||||
splitByChapters.allowDuplicates=Duplikate erlauben
|
|
||||||
splitByChapters.desc.1=Dieses Werkzeug teilt eine PDF-Datei auf der Grundlage ihrer Kapitelstruktur in mehrere PDF-Dateien auf.
|
|
||||||
splitByChapters.desc.2=Lesezeichenebene: Wählen Sie die Ebene der Lesezeichen, die für die Aufteilung verwendet werden soll (0 für die erste Ebene, 1 für die zweite Ebene usw.).
|
|
||||||
splitByChapters.desc.3=Metadaten einschließen: Wenn diese Option aktiviert ist, werden die Metadaten der ursprünglichen PDF-Datei in jede aufgeteilte PDF-Datei übernommen.
|
|
||||||
splitByChapters.desc.4=Duplikate erlauben: Wenn diese Option aktiviert ist, können mehrere Lesezeichen auf derselben Seite separate PDF Dateien erstellen.
|
|
||||||
splitByChapters.submit=PDF teilen
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Δωρισε
|
|||||||
color=Χρώμα
|
color=Χρώμα
|
||||||
sponsor=Yποστηρικτής
|
sponsor=Yποστηρικτής
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Λήψη
|
pipelineOptions.saveButton=Λήψη
|
||||||
pipelineOptions.validateButton=Επικυρώνω
|
pipelineOptions.validateButton=Επικυρώνω
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
|
autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Έγγραφο 1
|
compare.document.1=Έγγραφο 1
|
||||||
compare.document.2=Έγγραφο 2
|
compare.document.2=Έγγραφο 2
|
||||||
compare.submit=Σύγκριση
|
compare.submit=Σύγκριση
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books και Comics σε PDF
|
BookToPDF.title=Books και Comics σε PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Σχεδίαση υπογραφής
|
|||||||
sign.text=Εισαγωγή κειμένου
|
sign.text=Εισαγωγή κειμένου
|
||||||
sign.clear=Καθάρισμα
|
sign.clear=Καθάρισμα
|
||||||
sign.add=Προσθήκη
|
sign.add=Προσθήκη
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Άδεια
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ info=Info
|
|||||||
pro=Pro
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -556,6 +554,7 @@ login.userIsDisabled=User is deactivated, login is currently blocked with this u
|
|||||||
login.alreadyLoggedIn=You are already logged in to
|
login.alreadyLoggedIn=You are already logged in to
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||||
login.toManySessions=You have too many active sessions
|
login.toManySessions=You have too many active sessions
|
||||||
|
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -750,7 +749,6 @@ certSign.showSig=Show Signature
|
|||||||
certSign.reason=Reason
|
certSign.reason=Reason
|
||||||
certSign.location=Location
|
certSign.location=Location
|
||||||
certSign.name=Name
|
certSign.name=Name
|
||||||
certSign.showLogo=Show Logo
|
|
||||||
certSign.submit=Sign PDF
|
certSign.submit=Sign PDF
|
||||||
|
|
||||||
|
|
||||||
@@ -785,9 +783,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Compare
|
compare.submit=Compare
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -810,11 +805,6 @@ sign.draw=Draw Signature
|
|||||||
sign.text=Text Input
|
sign.text=Text Input
|
||||||
sign.clear=Clear
|
sign.clear=Clear
|
||||||
sign.add=Add
|
sign.add=Add
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1231,3 +1221,5 @@ splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for
|
|||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
||||||
splitByChapters.submit=Split PDF
|
splitByChapters.submit=Split PDF
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validate
|
pipelineOptions.validateButton=Validate
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -750,7 +721,6 @@ certSign.showSig=Show Signature
|
|||||||
certSign.reason=Reason
|
certSign.reason=Reason
|
||||||
certSign.location=Location
|
certSign.location=Location
|
||||||
certSign.name=Name
|
certSign.name=Name
|
||||||
certSign.showLogo=Show Logo
|
|
||||||
certSign.submit=Sign PDF
|
certSign.submit=Sign PDF
|
||||||
|
|
||||||
|
|
||||||
@@ -785,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Compare
|
compare.submit=Compare
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -810,11 +777,6 @@ sign.draw=Draw Signature
|
|||||||
sign.text=Text Input
|
sign.text=Text Input
|
||||||
sign.clear=Clear
|
sign.clear=Clear
|
||||||
sign.add=Add
|
sign.add=Add
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1192,8 +1154,6 @@ licenses.license=License
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1219,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
###########
|
###########
|
||||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||||
language.direction=ltr
|
language.direction=ltr
|
||||||
addPageNumbers.fontSize=Tamaño de Letra
|
addPageNumbers.fontSize=Font Size
|
||||||
addPageNumbers.fontName=Nombre de Letra
|
addPageNumbers.fontName=Font Name
|
||||||
pdfPrompt=Seleccionar PDF(s)
|
pdfPrompt=Seleccionar PDF(s)
|
||||||
multiPdfPrompt=Seleccionar PDFs (2+)
|
multiPdfPrompt=Seleccionar PDFs (2+)
|
||||||
multiPdfDropPrompt=Seleccione (o arrastre y suelte) todos los PDFs que quiera
|
multiPdfDropPrompt=Seleccione (o arrastre y suelte) todos los PDFs que quiera
|
||||||
@@ -50,7 +50,7 @@ WorkInProgess=Tarea en progreso, puede no funcionar o ralentizarse; ¡por favor,
|
|||||||
poweredBy=Desarrollado por
|
poweredBy=Desarrollado por
|
||||||
yes=Sí
|
yes=Sí
|
||||||
no=No
|
no=No
|
||||||
changedCredsMessage=¡Se cambiaron las credenciales!
|
changedCredsMessage=Se cambiaron las credenciales!
|
||||||
notAuthenticatedMessage=Usuario no autentificado.
|
notAuthenticatedMessage=Usuario no autentificado.
|
||||||
userNotFoundMessage=Usuario no encontrado.
|
userNotFoundMessage=Usuario no encontrado.
|
||||||
incorrectPasswordMessage=La contraseña actual no es correcta.
|
incorrectPasswordMessage=La contraseña actual no es correcta.
|
||||||
@@ -76,17 +76,14 @@ donate=Donar
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Patrocinador
|
sponsor=Patrocinador
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
page=Page
|
||||||
page=Página
|
pages=Pages
|
||||||
pages=Páginas
|
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Política de Privacidad
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Términos y Condiciones
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=Accesibilidad
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Política de Cookies
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=Impresión
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Canalización:
|
|||||||
pipelineOptions.saveButton=Descargar
|
pipelineOptions.saveButton=Descargar
|
||||||
pipelineOptions.validateButton=Validar
|
pipelineOptions.validateButton=Validar
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Actualiza a Pro
|
|
||||||
enterpriseEdition.warning=Esta característica está únicamente disponible para usuarios Pro.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro soporta configuración de ficheros YAML y otras características SSO.
|
|
||||||
enterpriseEdition.ssoAdvert=¿Busca más funciones de administración de usuarios? Consulte Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=¿Quieres mejorar Stirling PDF?
|
|
||||||
analytics.paragraph1=Stirling PDF ha optado por analíticas para ayudarnos a mejorar el producto. No rastreamos ninguna información personal ni contenido de archivos.
|
|
||||||
analytics.paragraph2=Considere habilitar analíticas para ayudar a Stirling-PDF a crecer y permitirnos comprender mejor a nuestros usuarios.
|
|
||||||
analytics.enable=Habilitar analíticas
|
|
||||||
analytics.disable=Deshabilitar analíticas
|
|
||||||
analytics.settings=Puede cambiar la configuración de analíticas en el archivo config/settings.yml
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convertir desde PDF
|
|||||||
navbar.sections.security=Señalización y seguridad
|
navbar.sections.security=Señalización y seguridad
|
||||||
navbar.sections.advance=Avanzado
|
navbar.sections.advance=Avanzado
|
||||||
navbar.sections.edit=Ver y Editar
|
navbar.sections.edit=Ver y Editar
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=Archivo no encontrado
|
|||||||
database.fileNullOrEmpty=El archivo no debe ser nulo o vacío.
|
database.fileNullOrEmpty=El archivo no debe ser nulo o vacío.
|
||||||
database.failedImportFile=Archivo de importación fallido
|
database.failedImportFile=Archivo de importación fallido
|
||||||
|
|
||||||
session.expired=Tu sesión ha caducado. Actualice la página e inténtelo de nuevo.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -394,7 +372,7 @@ certSign.tags=autentificar,PEM,P12,oficial,encriptar
|
|||||||
|
|
||||||
home.removeCertSign.title=Quitar signo de certificado
|
home.removeCertSign.title=Quitar signo de certificado
|
||||||
home.removeCertSign.desc=Eliminar firma de certificado de PDF
|
home.removeCertSign.desc=Eliminar firma de certificado de PDF
|
||||||
removeCertSign.tags=autenticar,PEM,P12,oficial,desencriptar
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Diseño de varias páginas
|
home.pageLayout.title=Diseño de varias páginas
|
||||||
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
||||||
@@ -504,29 +482,24 @@ home.removeImagePdf.title=Eliminar imagen
|
|||||||
home.removeImagePdf.desc=Eliminar imagen del PDF> para reducir el tamaño de archivo
|
home.removeImagePdf.desc=Eliminar imagen del PDF> para reducir el tamaño de archivo
|
||||||
removeImagePdf.tags=Eliminar imagen,Operaciones de página,Back end,lado del servidor
|
removeImagePdf.tags=Eliminar imagen,Operaciones de página,Back end,lado del servidor
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Dividir PDF por capítulos
|
|
||||||
home.splitPdfByChapters.desc=Divida un PDF en varios archivos según su estructura de capítulos.
|
|
||||||
splitPdfByChapters.tags=dividir,capítulos,marcadores,organizar
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Reemplazar-Invertir-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Reemplazar-Invertir Color en PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Reemplazar e Invertir Color
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Reemplaza el color del texto y el fondo en el PDF e invierte el color completo del PDF para reducir el tamaño del archivo
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Reemplazar Color,Operaciones de Página,Back end,Lado del servidor
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Opciones para Reemplazar o Invertir color
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Predeterminado (Colores de alto contraste predeterminados)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Personalizado (Colores personalizados)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Invertir Completo (Invertir todos los colores)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Opciones de color de alto contraste
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=Texto blanco sobre fondo negro
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Texto negro sobre fondo blanco
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Texto amarillo sobre fondo negro
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Texto verde sobre fondo negro
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Elegir Color de Texto
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Elegir Color de Fondo
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Reemplazar
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Acceso denegado
|
|||||||
login.oauth2InvalidTokenResponse=Respuesta de token no válida
|
login.oauth2InvalidTokenResponse=Respuesta de token no válida
|
||||||
login.oauth2InvalidIdToken=Token de identificación no válido
|
login.oauth2InvalidIdToken=Token de identificación no válido
|
||||||
login.userIsDisabled=El usuario está desactivado, actualmente el acceso está bloqueado para ese nombre de usuario. Por favor, póngase en contacto con el administrador.
|
login.userIsDisabled=El usuario está desactivado, actualmente el acceso está bloqueado para ese nombre de usuario. Por favor, póngase en contacto con el administrador.
|
||||||
login.alreadyLoggedIn=Ya has iniciado sesión en
|
|
||||||
login.alreadyLoggedIn2=dispositivos. Cierra sesión en los dispositivos y vuelve a intentarlo.
|
|
||||||
login.toManySessions=Tienes demasiadas sesiones activas
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redactar
|
autoRedact.title=Auto Redactar
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Color resaltado 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Libros y Cómics a PDF
|
BookToPDF.title=Libros y Cómics a PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Dibujar firma
|
|||||||
sign.text=Entrada de texto
|
sign.text=Entrada de texto
|
||||||
sign.clear=Borrar
|
sign.clear=Borrar
|
||||||
sign.add=Agregar
|
sign.add=Agregar
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -897,7 +860,7 @@ addImage.title=Añadir imagen
|
|||||||
addImage.header=Añadir imagen de PDF
|
addImage.header=Añadir imagen de PDF
|
||||||
addImage.everyPage=¿Todas las páginas?
|
addImage.everyPage=¿Todas las páginas?
|
||||||
addImage.upload=Añadir imagen
|
addImage.upload=Añadir imagen
|
||||||
addImage.submit=Enviar imagen
|
addImage.submit=Añadir imagen
|
||||||
|
|
||||||
|
|
||||||
#merge
|
#merge
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licencia
|
|||||||
survey.nav=Encuesta
|
survey.nav=Encuesta
|
||||||
survey.title=Encuesta Stirling-PDF
|
survey.title=Encuesta Stirling-PDF
|
||||||
survey.description=Stirling-PDF no tiene seguimiento, por lo que queremos escuchar a nuestros usuarios para mejorar Stirling-PDF.
|
survey.description=Stirling-PDF no tiene seguimiento, por lo que queremos escuchar a nuestros usuarios para mejorar Stirling-PDF.
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=¡Considere realizar nuestra encuesta!
|
survey.please=¡Considere realizar nuestra encuesta!
|
||||||
survey.disabled=(La ventana emergente de la encuesta se desactivará en las siguientes actualizaciones, pero estará disponible al pie de la página.)
|
survey.disabled=(La ventana emergente de la encuesta se desactivará en las siguientes actualizaciones, pero estará disponible al pie de la página.)
|
||||||
survey.button=Realizar encuesta
|
survey.button=Realizar encuesta
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Eliminar imagen
|
|||||||
removeImage.header=Eliminar imagen
|
removeImage.header=Eliminar imagen
|
||||||
removeImage.removeImage=Eliminar imagen
|
removeImage.removeImage=Eliminar imagen
|
||||||
removeImage.submit=Eliminar imagen
|
removeImage.submit=Eliminar imagen
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Dividir PDF por Capítulos
|
|
||||||
splitByChapters.header=Dividir PDF por Capítulos
|
|
||||||
splitByChapters.bookmarkLevel=Nivel de Marcador
|
|
||||||
splitByChapters.includeMetadata=Incluir Metadatos
|
|
||||||
splitByChapters.allowDuplicates=Permitir Duplicados
|
|
||||||
splitByChapters.desc.1=Esta herramienta divide un archivo PDF en múltiples archivos PDF según su estructura de capítulos.
|
|
||||||
splitByChapters.desc.2=Nivel de Marcador: Elige el nivel de marcadores para dividir (0 para el nivel superior, 1 para el segundo nivel, etc.).
|
|
||||||
splitByChapters.desc.3=Incluir Metadatos: Si está seleccionado, los metadatos del PDF original se incluirán en cada PDF dividido.
|
|
||||||
splitByChapters.desc.4=Permitir Duplicados: Si está seleccionado, permite que múltiples marcadores en la misma página creen archivos PDF separados.
|
|
||||||
splitByChapters.submit=Dividir PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validate
|
pipelineOptions.validateButton=Validate
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Idatzi
|
autoRedact.title=Auto Idatzi
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=1. dokumentua
|
compare.document.1=1. dokumentua
|
||||||
compare.document.2=2. dokumentua
|
compare.document.2=2. dokumentua
|
||||||
compare.submit=Konparatu
|
compare.submit=Konparatu
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Marraztu sinadura
|
|||||||
sign.text=Testua sartzea
|
sign.text=Testua sartzea
|
||||||
sign.clear=Garbitu
|
sign.clear=Garbitu
|
||||||
sign.add=Gehitu
|
sign.add=Gehitu
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=License
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
###########
|
###########
|
||||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||||
language.direction=ltr
|
language.direction=ltr
|
||||||
addPageNumbers.fontSize=Taille de Police
|
addPageNumbers.fontSize=Font Size
|
||||||
addPageNumbers.fontName=Nom de la Police
|
addPageNumbers.fontName=Font Name
|
||||||
pdfPrompt=Sélectionnez le(s) PDF
|
pdfPrompt=Sélectionnez le(s) PDF
|
||||||
multiPdfPrompt=Sélectionnez les PDF
|
multiPdfPrompt=Sélectionnez les PDF
|
||||||
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
|
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
|
||||||
imgPrompt=Choisir une image
|
imgPrompt=Choisir une image
|
||||||
genericSubmit=Envoyer
|
genericSubmit=Envoyer
|
||||||
processTimeWarning=Attention, ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier.
|
processTimeWarning=Attention, ce processus peut prendre jusqu’à une minute en fonction de la taille du fichier.
|
||||||
pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
||||||
pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
|
||||||
goToPage=Aller
|
goToPage=Aller
|
||||||
@@ -23,7 +23,7 @@ close=Fermer
|
|||||||
filesSelected=fichiers sélectionnés
|
filesSelected=fichiers sélectionnés
|
||||||
noFavourites=Aucun favori ajouté
|
noFavourites=Aucun favori ajouté
|
||||||
downloadComplete=Téléchargement terminé
|
downloadComplete=Téléchargement terminé
|
||||||
bored=Marre d'attendre ?
|
bored=Marre d’attendre ?
|
||||||
alphabet=Alphabet
|
alphabet=Alphabet
|
||||||
downloadPdf=Télécharger le PDF
|
downloadPdf=Télécharger le PDF
|
||||||
text=Texte
|
text=Texte
|
||||||
@@ -34,9 +34,9 @@ sizes.small=Petit
|
|||||||
sizes.medium=Moyen
|
sizes.medium=Moyen
|
||||||
sizes.large=Grand
|
sizes.large=Grand
|
||||||
sizes.x-large=Très grand
|
sizes.x-large=Très grand
|
||||||
error.pdfPassword=Le document PDF est protégé par un mot de passe qui n'a pas été fourni ou était incorrect
|
error.pdfPassword=Le document PDF est protégé par un mot de passe qui n’a pas été fourni ou était incorrect
|
||||||
delete=Supprimer
|
delete=Supprimer
|
||||||
username=Nom d'utilisateur
|
username=Nom d’utilisateur
|
||||||
password=Mot de passe
|
password=Mot de passe
|
||||||
welcome=Bienvenue
|
welcome=Bienvenue
|
||||||
property=Propriété
|
property=Propriété
|
||||||
@@ -54,12 +54,12 @@ changedCredsMessage=Les identifiants ont été mis à jour !
|
|||||||
notAuthenticatedMessage=Utilisateur non authentifié.
|
notAuthenticatedMessage=Utilisateur non authentifié.
|
||||||
userNotFoundMessage=Utilisateur non trouvé.
|
userNotFoundMessage=Utilisateur non trouvé.
|
||||||
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
|
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
|
||||||
usernameExistsMessage=Le nouveau nom d'utilisateur existe déjà.
|
usernameExistsMessage=Le nouveau nom d’utilisateur existe déjà.
|
||||||
invalidUsernameMessage=Nom d'utilisateur invalide, le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
invalidUsernameMessage=Nom d’utilisateur invalide, le nom d’utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
||||||
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
||||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||||
deleteCurrentUserMessage=Impossible de supprimer l'utilisateur actuellement connecté.
|
deleteCurrentUserMessage=Impossible de supprimer l’utilisateur actuellement connecté.
|
||||||
deleteUsernameExistsMessage=Le nom d'utilisateur n'existe pas et ne peut pas être supprimé.
|
deleteUsernameExistsMessage=Le nom d’utilisateur n’existe pas et ne peut pas être supprimé.
|
||||||
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
|
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
|
||||||
disabledCurrentUserMessage=The current user cannot be disabled
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
|
downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
|
||||||
@@ -68,7 +68,7 @@ userAlreadyExistsWebMessage=L'utilisateur existe déjà en tant qu'utilisateur W
|
|||||||
error=Erreur
|
error=Erreur
|
||||||
oops=Oups !
|
oops=Oups !
|
||||||
help=Aide
|
help=Aide
|
||||||
goHomepage=Aller à la page d'accueil
|
goHomepage=Aller à la page d’accueil
|
||||||
joinDiscord=Rejoignez notre serveur Discord
|
joinDiscord=Rejoignez notre serveur Discord
|
||||||
seeDockerHub=Consulter le Docker Hub
|
seeDockerHub=Consulter le Docker Hub
|
||||||
visitGithub=Visiter le dépôt Github
|
visitGithub=Visiter le dépôt Github
|
||||||
@@ -76,17 +76,14 @@ donate=Faire un don
|
|||||||
color=Couleur
|
color=Couleur
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Politique de Confidentialité
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Conditions Générales
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=Accessibilité
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Politique des Cookies
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=Mentions Légales
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Télécharger
|
pipelineOptions.saveButton=Télécharger
|
||||||
pipelineOptions.validateButton=Valider
|
pipelineOptions.validateButton=Valider
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Passer à Pro
|
|
||||||
enterpriseEdition.warning=Cette fonctionnalité est uniquement disponible pour les utilisateurs Pro.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro prend en charge les fichiers de configuration YAML et d'autres fonctionnalités SSO.
|
|
||||||
enterpriseEdition.ssoAdvert=Vous cherchez plus de fonctionnalités de gestion des utilisateurs ? Découvrez Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Souhaitez-vous améliorer Stirling PDF ?
|
|
||||||
analytics.paragraph1=Stirling PDF utilise des analyses volontaires pour nous aider à améliorer le produit. Nous ne suivons aucune information personnelle ni le contenu des fichiers.
|
|
||||||
analytics.paragraph2=Veuillez envisager d'activer les analyses pour aider Stirling-PDF à se développer et pour nous permettre de mieux comprendre nos utilisateurs.
|
|
||||||
analytics.enable=Activer les analyses
|
|
||||||
analytics.disable=Désactiver les analyses
|
|
||||||
analytics.settings=Vous pouvez modifier les paramètres des analyses dans le fichier config/settings.yml
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convertir depuis PDF
|
|||||||
navbar.sections.security=Signature et sécurité
|
navbar.sections.security=Signature et sécurité
|
||||||
navbar.sections.advance=Mode avancé
|
navbar.sections.advance=Mode avancé
|
||||||
navbar.sections.edit=Voir et modifier
|
navbar.sections.edit=Voir et modifier
|
||||||
navbar.sections.popular=Populaire
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -155,8 +135,8 @@ navbar.sections.popular=Populaire
|
|||||||
settings.title=Paramètres
|
settings.title=Paramètres
|
||||||
settings.update=Mise à jour disponible
|
settings.update=Mise à jour disponible
|
||||||
settings.updateAvailable={0} est la version actuellement installée. Une nouvelle version ({1}) est disponible.
|
settings.updateAvailable={0} est la version actuellement installée. Une nouvelle version ({1}) est disponible.
|
||||||
settings.appVersion=Version de l'application :
|
settings.appVersion=Version de l’application :
|
||||||
settings.downloadOption.title=Choisissez l'option de téléchargement (pour les téléchargements à fichier unique non ZIP) :
|
settings.downloadOption.title=Choisissez l’option de téléchargement (pour les téléchargements à fichier unique non ZIP) :
|
||||||
settings.downloadOption.1=Ouvrir dans la même fenêtre
|
settings.downloadOption.1=Ouvrir dans la même fenêtre
|
||||||
settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre
|
settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre
|
||||||
settings.downloadOption.3=Télécharger le fichier
|
settings.downloadOption.3=Télécharger le fichier
|
||||||
@@ -170,7 +150,7 @@ settings.cacheInputs.help=Permet de stocker les entrées précédemment utilisé
|
|||||||
changeCreds.title=Modifiez vos identifiants
|
changeCreds.title=Modifiez vos identifiants
|
||||||
changeCreds.header=Mettez à jour vos identifiants de connexion
|
changeCreds.header=Mettez à jour vos identifiants de connexion
|
||||||
changeCreds.changePassword=Vous utilisez les identifiants de connexion par défaut. Veuillez saisir un nouveau mot de passe
|
changeCreds.changePassword=Vous utilisez les identifiants de connexion par défaut. Veuillez saisir un nouveau mot de passe
|
||||||
changeCreds.newUsername=Nouveau nom d'utilisateur
|
changeCreds.newUsername=Nouveau nom d’utilisateur
|
||||||
changeCreds.oldPassword=Mot de passe actuel
|
changeCreds.oldPassword=Mot de passe actuel
|
||||||
changeCreds.newPassword=Nouveau mot de passe
|
changeCreds.newPassword=Nouveau mot de passe
|
||||||
changeCreds.confirmNewPassword=Confirmer le nouveau mot de passe
|
changeCreds.confirmNewPassword=Confirmer le nouveau mot de passe
|
||||||
@@ -180,10 +160,10 @@ changeCreds.submit=Soumettre les modifications
|
|||||||
|
|
||||||
account.title=Paramètres du compte
|
account.title=Paramètres du compte
|
||||||
account.accountSettings=Paramètres du compte
|
account.accountSettings=Paramètres du compte
|
||||||
account.adminSettings=Paramètres d'administration – Voir et ajouter des utilisateurs
|
account.adminSettings=Paramètres d’administration – Voir et ajouter des utilisateurs
|
||||||
account.userControlSettings=Contrôle des paramètres des utilisateurs
|
account.userControlSettings=Contrôle des paramètres des utilisateurs
|
||||||
account.changeUsername=Modifier le nom d'utilisateur
|
account.changeUsername=Modifier le nom d’utilisateur
|
||||||
account.newUsername=Nouveau nom d'utilisateur
|
account.newUsername=Nouveau nom d’utilisateur
|
||||||
account.password=Mot de passe de confirmation
|
account.password=Mot de passe de confirmation
|
||||||
account.oldPassword=Ancien mot de passe
|
account.oldPassword=Ancien mot de passe
|
||||||
account.newPassword=Nouveau mot de passe
|
account.newPassword=Nouveau mot de passe
|
||||||
@@ -204,29 +184,29 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
|
|||||||
adminUserSettings.admin=Administateur
|
adminUserSettings.admin=Administateur
|
||||||
adminUserSettings.user=Utilisateur
|
adminUserSettings.user=Utilisateur
|
||||||
adminUserSettings.addUser=Ajouter un utilisateur
|
adminUserSettings.addUser=Ajouter un utilisateur
|
||||||
adminUserSettings.deleteUser=Supprimer l'utilisateur
|
adminUserSettings.deleteUser=Delete User
|
||||||
adminUserSettings.confirmDeleteUser=Voulez vous vraiment supprimer l'utilisateur ?
|
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||||
adminUserSettings.confirmChangeUserStatus=Voulez vous vraiment déactiver/réactiver l'utilisateur ?
|
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
||||||
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
||||||
adminUserSettings.roles=Rôles
|
adminUserSettings.roles=Rôles
|
||||||
adminUserSettings.role=Rôle
|
adminUserSettings.role=Rôle
|
||||||
adminUserSettings.actions=Actions
|
adminUserSettings.actions=Actions
|
||||||
adminUserSettings.apiUser=Utilisateur API limité
|
adminUserSettings.apiUser=Utilisateur API limité
|
||||||
adminUserSettings.extraApiUser=Utilisateur limité supplémentaire de l'API
|
adminUserSettings.extraApiUser=Utilisateur limité supplémentaire de l’API
|
||||||
adminUserSettings.webOnlyUser=Utilisateur Web uniquement
|
adminUserSettings.webOnlyUser=Utilisateur Web uniquement
|
||||||
adminUserSettings.demoUser=Demo User (Paramètres par défaut)
|
adminUserSettings.demoUser=Demo User (Paramètres par défaut)
|
||||||
adminUserSettings.internalApiUser=Utilisateur de l'API interne
|
adminUserSettings.internalApiUser=Utilisateur de l'API interne
|
||||||
adminUserSettings.forceChange=Forcer l'utilisateur à changer son nom d'utilisateur/mot de passe lors de la connexion
|
adminUserSettings.forceChange=Forcer l’utilisateur à changer son nom d’utilisateur/mot de passe lors de la connexion
|
||||||
adminUserSettings.submit=Ajouter
|
adminUserSettings.submit=Ajouter
|
||||||
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
|
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
|
||||||
adminUserSettings.authenticated=Authentifié
|
adminUserSettings.authenticated=Authentifié
|
||||||
adminUserSettings.editOwnProfil=Éditer son propre profil
|
adminUserSettings.editOwnProfil=Edit own profile
|
||||||
adminUserSettings.enabledUser=Utilisateur activé
|
adminUserSettings.enabledUser=enabled user
|
||||||
adminUserSettings.disabledUser=Utilisateur désactivé
|
adminUserSettings.disabledUser=disabled user
|
||||||
adminUserSettings.activeUsers=Utilisateurs actifs :
|
adminUserSettings.activeUsers=Active Users:
|
||||||
adminUserSettings.disabledUsers=Utilisateurs désactivés :
|
adminUserSettings.disabledUsers=Disabled Users:
|
||||||
adminUserSettings.totalUsers=Utilisateurs au total :
|
adminUserSettings.totalUsers=Total Users:
|
||||||
adminUserSettings.lastRequest=Dernière requête
|
adminUserSettings.lastRequest=Last Request
|
||||||
|
|
||||||
|
|
||||||
database.title=Database Import/Export
|
database.title=Database Import/Export
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Votre session a expiré. Veuillez recharger la page et réessayer.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -284,7 +262,7 @@ home.pdfToImage.desc=Convertissez un PDF en image (PNG, JPEG, GIF).
|
|||||||
pdfToImage.tags=conversion,img,jpg,image,photo
|
pdfToImage.tags=conversion,img,jpg,image,photo
|
||||||
|
|
||||||
home.pdfOrganiser.title=Organiser
|
home.pdfOrganiser.title=Organiser
|
||||||
home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n'importe quel ordre.
|
home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n’importe quel ordre.
|
||||||
pdfOrganiser.tags=organiser,recto-verso,duplex,even,odd,sort,move
|
pdfOrganiser.tags=organiser,recto-verso,duplex,even,odd,sort,move
|
||||||
|
|
||||||
|
|
||||||
@@ -294,7 +272,7 @@ addImage.tags=img,jpg,image,photo
|
|||||||
|
|
||||||
home.watermark.title=Ajouter un filigrane
|
home.watermark.title=Ajouter un filigrane
|
||||||
home.watermark.desc=Ajoutez un filigrane personnalisé à votre PDF.
|
home.watermark.desc=Ajoutez un filigrane personnalisé à votre PDF.
|
||||||
watermark.tags=texte,filigrane,label,propriété,droit d'auteur,marque déposée,img,jpg,image,photo,copyright,trademark
|
watermark.tags=texte,filigrane,label,propriété,droit d’auteur,marque déposée,img,jpg,image,photo,copyright,trademark
|
||||||
|
|
||||||
home.permissions.title=Modifier les permissions
|
home.permissions.title=Modifier les permissions
|
||||||
home.permissions.desc=Modifiez les permissions de votre PDF.
|
home.permissions.desc=Modifiez les permissions de votre PDF.
|
||||||
@@ -323,16 +301,16 @@ home.changeMetadata.desc=Modifiez, supprimez ou ajoutez des métadonnées à un
|
|||||||
changeMetadata.tags=métadonnées,titre,auteur,date,création,heure,éditeur,statistiques,title,author,date,creation,time,publisher,producer,stats,metadata
|
changeMetadata.tags=métadonnées,titre,auteur,date,création,heure,éditeur,statistiques,title,author,date,creation,time,publisher,producer,stats,metadata
|
||||||
|
|
||||||
home.fileToPDF.title=Fichier en PDF
|
home.fileToPDF.title=Fichier en PDF
|
||||||
home.fileToPDF.desc=Convertissez presque n'importe quel fichier en PDF (DOCX, PNG, XLS, PPT, TXT, etc.).
|
home.fileToPDF.desc=Convertissez presque n’importe quel fichiers en PDF (DOCX, PNG, XLS, PPT, TXT et plus).
|
||||||
fileToPDF.tags=convertion,transformation,format,document,image,slide,texte,conversion,office,docs,word,excel,powerpoint
|
fileToPDF.tags=convertion,transformation,format,document,image,slide,texte,conversion,office,docs,word,excel,powerpoint
|
||||||
|
|
||||||
home.ocr.title=OCR / Nettoyage des numérisations
|
home.ocr.title=OCR / Nettoyage des numérisations
|
||||||
home.ocr.desc=Utilisez l'OCR pour analyser et détecter le texte des images d'un PDF et le rajouter en tant que tel.
|
home.ocr.desc=Utilisez l’OCR pour analyser et détecter le texte des images d’un PDF et le rajouter en tant que tel.
|
||||||
ocr.tags=ocr,reconnaissance,texte,image,numérisation,scan,read,identify,detection,editable
|
ocr.tags=ocr,reconnaissance,texte,image,numérisation,scan,read,identify,detection,editable
|
||||||
|
|
||||||
|
|
||||||
home.extractImages.title=Extraire les images
|
home.extractImages.title=Extraire les images
|
||||||
home.extractImages.desc=Extrayez toutes les images d'un PDF et enregistrez-les dans un ZIP.
|
home.extractImages.desc=Extrayez toutes les images d’un PDF et enregistrez-les dans un ZIP.
|
||||||
extractImages.tags=image,photo,save,archive,zip,capture,grab
|
extractImages.tags=image,photo,save,archive,zip,capture,grab
|
||||||
|
|
||||||
home.pdfToPDFA.title=PDF en PDF/A
|
home.pdfToPDFA.title=PDF en PDF/A
|
||||||
@@ -361,7 +339,7 @@ home.PDFToXML.desc=Convertissez un PDF au format XML.
|
|||||||
PDFToXML.tags=xml,extraction de données,contenu structuré,interopérabilité,data-extraction,structured-content,interop,transformation,convert
|
PDFToXML.tags=xml,extraction de données,contenu structuré,interopérabilité,data-extraction,structured-content,interop,transformation,convert
|
||||||
|
|
||||||
home.ScannerImageSplit.title=Diviser les photos numérisées
|
home.ScannerImageSplit.title=Diviser les photos numérisées
|
||||||
home.ScannerImageSplit.desc=Divisez plusieurs photos à partir d'une photo ou d'un PDF.
|
home.ScannerImageSplit.desc=Divisez plusieurs photos à partir d’une photo ou d’un PDF.
|
||||||
ScannerImageSplit.tags=diviser,détecter automatiquement,numériser,separate,auto-detect,scans,multi-photo,organize
|
ScannerImageSplit.tags=diviser,détecter automatiquement,numériser,separate,auto-detect,scans,multi-photo,organize
|
||||||
|
|
||||||
home.sign.title=Signer
|
home.sign.title=Signer
|
||||||
@@ -369,7 +347,7 @@ home.sign.desc=Ajoutez une signature au PDF avec un dessin, du texte ou une imag
|
|||||||
sign.tags=signer,authorize,initials,drawn-signature,text-sign,image-signature
|
sign.tags=signer,authorize,initials,drawn-signature,text-sign,image-signature
|
||||||
|
|
||||||
home.flatten.title=Rendre inerte
|
home.flatten.title=Rendre inerte
|
||||||
home.flatten.desc=Supprimez tous les éléments et formulaires interactifs d'un PDF.
|
home.flatten.desc=Supprimez tous les éléments et formulaires interactifs d’un PDF.
|
||||||
flatten.tags=inerte,static,deactivate,non-interactive,streamline
|
flatten.tags=inerte,static,deactivate,non-interactive,streamline
|
||||||
|
|
||||||
home.repair.title=Réparer
|
home.repair.title=Réparer
|
||||||
@@ -377,11 +355,11 @@ home.repair.desc=Essayez de réparer un PDF corrompu ou cassé.
|
|||||||
repair.tags=réparer,restaurer,corriger,récupérer,fix,restore,correction,recover
|
repair.tags=réparer,restaurer,corriger,récupérer,fix,restore,correction,recover
|
||||||
|
|
||||||
home.removeBlanks.title=Supprimer les pages vierges
|
home.removeBlanks.title=Supprimer les pages vierges
|
||||||
home.removeBlanks.desc=Détectez et supprimez les pages vierges d'un PDF.
|
home.removeBlanks.desc=Détectez et supprimez les pages vierges d’un PDF.
|
||||||
removeBlanks.tags=pages vierges,supprimer,nettoyer,cleanup,streamline,non-content,organize
|
removeBlanks.tags=pages vierges,supprimer,nettoyer,cleanup,streamline,non-content,organize
|
||||||
|
|
||||||
home.removeAnnotations.title=Supprimer les annotations
|
home.removeAnnotations.title=Supprimer les annotations
|
||||||
home.removeAnnotations.desc=Supprimer tous les commentaires/annotations d'un PDF.
|
home.removeAnnotations.desc=Supprimer tous les commentaires/annotations d’un PDF.
|
||||||
removeAnnotations.tags=commentaires,supprimer,annotations,highlight,notes,markup,remove
|
removeAnnotations.tags=commentaires,supprimer,annotations,highlight,notes,markup,remove
|
||||||
|
|
||||||
home.compare.title=Comparer
|
home.compare.title=Comparer
|
||||||
@@ -392,16 +370,16 @@ home.certSign.title=Signer avec un certificat
|
|||||||
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
|
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
|
||||||
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
|
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
home.removeCertSign.title=Supprimer la signature par certificat
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
home.removeCertSign.desc=Supprimez la signature par certificat d'un PDF
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
removeCertSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Fusionner des pages
|
home.pageLayout.title=Fusionner des pages
|
||||||
home.pageLayout.desc=Fusionnez plusieurs pages d'un PDF en une seule.
|
home.pageLayout.desc=Fusionnez plusieurs pages d’un PDF en une seule.
|
||||||
pageLayout.tags=fusionner,merge,composite,single-view,organize
|
pageLayout.tags=fusionner,merge,composite,single-view,organize
|
||||||
|
|
||||||
home.scalePages.title=Ajuster l'échelle ou la taille
|
home.scalePages.title=Ajuster l’échelle ou la taille
|
||||||
home.scalePages.desc=Modifiez la taille ou l'échelle d'une page et/ou de son contenu.
|
home.scalePages.desc=Modifiez la taille ou l’échelle d’une page et/ou de son contenu.
|
||||||
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
|
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Pipeline
|
home.pipeline.title=Pipeline
|
||||||
@@ -417,7 +395,7 @@ home.auto-rename.desc=Renommez automatiquement un fichier PDF en fonction de son
|
|||||||
auto-rename.tags=renommer,détection automatique,réétiqueter,auto-detect,header-based,organize,relabel
|
auto-rename.tags=renommer,détection automatique,réétiqueter,auto-detect,header-based,organize,relabel
|
||||||
|
|
||||||
home.adjust-contrast.title=Ajuster les couleurs
|
home.adjust-contrast.title=Ajuster les couleurs
|
||||||
home.adjust-contrast.desc=Ajustez le contraste, la saturation et la luminosité d'un PDF.
|
home.adjust-contrast.desc=Ajustez le contraste, la saturation et la luminosité d’un PDF.
|
||||||
adjust-contrast.tags=ajuster,couleurs,amélioration,color-correction,tune,modify,enhance
|
adjust-contrast.tags=ajuster,couleurs,amélioration,color-correction,tune,modify,enhance
|
||||||
|
|
||||||
home.crop.title=Redimensionner
|
home.crop.title=Redimensionner
|
||||||
@@ -433,16 +411,16 @@ home.sanitizePdf.desc=Supprimez les scripts et autres éléments des PDF.
|
|||||||
sanitizePdf.tags=assainir,sécurisé,clean,secure,safe,remove-threats
|
sanitizePdf.tags=assainir,sécurisé,clean,secure,safe,remove-threats
|
||||||
|
|
||||||
home.URLToPDF.title=URL en PDF
|
home.URLToPDF.title=URL en PDF
|
||||||
home.URLToPDF.desc=Convertissez n'importe quelle URL http(s) en PDF.
|
home.URLToPDF.desc=Convertissez n’importe quelle URL http(s) en PDF.
|
||||||
URLToPDF.tags=pdf,contenu Web,save-page,web-to-doc,archive
|
URLToPDF.tags=pdf,contenu Web,save-page,web-to-doc,archive
|
||||||
|
|
||||||
home.HTMLToPDF.title=HTML en PDF
|
home.HTMLToPDF.title=HTML en PDF
|
||||||
home.HTMLToPDF.desc=Convertissez n'importe quel fichier HTML ou ZIP en PDF.
|
home.HTMLToPDF.desc=Convertissez n’importe quel fichier HTML ou ZIP en PDF.
|
||||||
HTMLToPDF.tags=html,markup,contenu Web,transformation,convert
|
HTMLToPDF.tags=html,markup,contenu Web,transformation,convert
|
||||||
|
|
||||||
|
|
||||||
home.MarkdownToPDF.title=Markdown en PDF
|
home.MarkdownToPDF.title=Markdown en PDF
|
||||||
home.MarkdownToPDF.desc=Convertissez n'importe quel fichier Markdown en PDF.
|
home.MarkdownToPDF.desc=Convertissez n’importe quel fichier Markdown en PDF.
|
||||||
MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert
|
MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert
|
||||||
|
|
||||||
|
|
||||||
@@ -466,11 +444,11 @@ home.showJS.desc=Recherche et affiche tout JavaScript injecté dans un PDF.
|
|||||||
showJS.tags=JS
|
showJS.tags=JS
|
||||||
|
|
||||||
home.autoRedact.title=Caviarder automatiquement
|
home.autoRedact.title=Caviarder automatiquement
|
||||||
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d'un PDF.
|
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d’un PDF.
|
||||||
autoRedact.tags=caviarder,redact,auto
|
autoRedact.tags=caviarder,redact,auto
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF en CSV
|
home.tableExtraxt.title=PDF en CSV
|
||||||
home.tableExtraxt.desc=Extrait les tableaux d'un PDF et les transforme en CSV.
|
home.tableExtraxt.desc=Extrait les tableaux d’un PDF et les transforme en CSV.
|
||||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||||
|
|
||||||
|
|
||||||
@@ -480,15 +458,15 @@ autoSizeSplitPDF.tags=pdf,split,document,organization
|
|||||||
|
|
||||||
|
|
||||||
home.overlay-pdfs.title=Incrustation de PDF
|
home.overlay-pdfs.title=Incrustation de PDF
|
||||||
home.overlay-pdfs.desc=Incrustation d'un PDF sur un autre PDF.
|
home.overlay-pdfs.desc=Incrustation d’un PDF sur un autre PDF.
|
||||||
overlay-pdfs.tags=Overlay,incrustation
|
overlay-pdfs.tags=Overlay,incrustation
|
||||||
|
|
||||||
home.split-by-sections.title=Séparer un PDF en sections
|
home.split-by-sections.title=Séparer un PDF en sections
|
||||||
home.split-by-sections.desc=Diviser chaque page d'un PDF en sections horizontales/verticales plus petites.
|
home.split-by-sections.desc=Diviser chaque page d’un PDF en sections horizontales/verticales plus petites.
|
||||||
split-by-sections.tags=Sections,Diviser,Section Split, Divide, Customize
|
split-by-sections.tags=Sections,Diviser,Section Split, Divide, Customize
|
||||||
|
|
||||||
home.AddStampRequest.title=Ajouter un tampon sur un PDF
|
home.AddStampRequest.title=Ajouter un tampon sur un PDF
|
||||||
home.AddStampRequest.desc=Ajouter un texte ou l'image d'un tampon à un emplacement défini.
|
home.AddStampRequest.desc=Ajouter un texte ou l’image d’un tampon à un emplacement défini.
|
||||||
AddStampRequest.tags=Tampon,Ajouter,Stamp,Add image,center image,Watermark,PDF,Embed,Customize
|
AddStampRequest.tags=Tampon,Ajouter,Stamp,Add image,center image,Watermark,PDF,Embed,Customize
|
||||||
|
|
||||||
|
|
||||||
@@ -500,33 +478,28 @@ home.BookToPDF.title=eBook vers PDF
|
|||||||
home.BookToPDF.desc=Convertit les formats de livres/bandes dessinées en PDF à l'aide de calibre
|
home.BookToPDF.desc=Convertit les formats de livres/bandes dessinées en PDF à l'aide de calibre
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Supprimer les images
|
home.removeImagePdf.title=Remove image
|
||||||
home.removeImagePdf.desc=Supprimez les images d'un PDF pour réduire sa taille
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Images,Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Séparer un PDF par chapitres
|
|
||||||
home.splitPdfByChapters.desc=Séparez un PDF en fichiers multiples en fonction de sa structure par chapitres.
|
|
||||||
splitPdfByChapters.tags=séparer,chapitres,split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Remplacer-Inverser-Couleur
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Remplacer-Inverser Couleur PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Remplacer et Inverser Couleur
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Remplacer la couleur pour le texte et l'arrière-plan dans le PDF et inverser la couleur complète du PDF pour réduire la taille du fichier
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Remplacer Couleur,Opérations de Page,Back-end,Côté serveur
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Options de Remplacement ou d'Inversion de Couleur
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Par défaut (Couleurs à fort contraste par défaut)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Personnalisé (Couleurs personnalisées)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Inversion complète (Inverser toutes les couleurs)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Options de couleur à fort contraste
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=Texte blanc sur fond noir
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Texte noir sur fond blanc
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Texte jaune sur fond noir
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Texte vert sur fond noir
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Choisir la couleur du texte
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Choisir la couleur de l'arrière-plan
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Remplacer
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -540,7 +513,7 @@ login.title=Connexion
|
|||||||
login.header=Connexion
|
login.header=Connexion
|
||||||
login.signin=Connexion
|
login.signin=Connexion
|
||||||
login.rememberme=Se souvenir de moi
|
login.rememberme=Se souvenir de moi
|
||||||
login.invalid=Nom d'utilisateur ou mot de passe invalide.
|
login.invalid=Nom d’utilisateur ou mot de passe invalide.
|
||||||
login.locked=Votre compte a été verrouillé.
|
login.locked=Votre compte a été verrouillé.
|
||||||
login.signinTitle=Veuillez vous connecter
|
login.signinTitle=Veuillez vous connecter
|
||||||
login.ssoSignIn=Se connecter via l'authentification unique
|
login.ssoSignIn=Se connecter via l'authentification unique
|
||||||
@@ -552,10 +525,8 @@ login.oauth2invalidRequest=Requête invalide
|
|||||||
login.oauth2AccessDenied=Accès refusé
|
login.oauth2AccessDenied=Accès refusé
|
||||||
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
|
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
|
||||||
login.oauth2InvalidIdToken=Jeton d'identification invalide
|
login.oauth2InvalidIdToken=Jeton d'identification invalide
|
||||||
login.userIsDisabled=L'utilisateur est désactivé, la connexion est actuellement bloquée avec ce nom d'utilisateur. Veuillez contacter l'administrateur.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=Vous êtes déjà connecté sur
|
|
||||||
login.alreadyLoggedIn2=appareils. Veuillez vous déconnecter des appareils et réessayer.
|
|
||||||
login.toManySessions=Vous avez trop de sessions actives.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Caviarder automatiquement
|
autoRedact.title=Caviarder automatiquement
|
||||||
@@ -619,15 +590,15 @@ HTMLToPDF.header=HTML en PDF
|
|||||||
HTMLToPDF.help=Accepte les fichiers HTML et les ZIP contenant du HTML, du CSS, des images, etc. (requis).
|
HTMLToPDF.help=Accepte les fichiers HTML et les ZIP contenant du HTML, du CSS, des images, etc. (requis).
|
||||||
HTMLToPDF.submit=Convertir
|
HTMLToPDF.submit=Convertir
|
||||||
HTMLToPDF.credit=Utilise WeasyPrint.
|
HTMLToPDF.credit=Utilise WeasyPrint.
|
||||||
HTMLToPDF.zoom=Niveau de zoom pour l'affichage du site web.
|
HTMLToPDF.zoom=Niveau de zoom pour l’affichage du site web.
|
||||||
HTMLToPDF.pageWidth=Largeur de la page en centimètres. (Vide par défaut)
|
HTMLToPDF.pageWidth=Largeur de la page en centimètres. (Vide par défaut)
|
||||||
HTMLToPDF.pageHeight=Hauteur de la page en centimètres. (Vide par défaut)
|
HTMLToPDF.pageHeight=Hauteur de la page en centimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginTop=Marge supérieure de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginTop=Marge supérieure de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginBottom=Marge inférieure de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginBottom=Marge inférieure de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginLeft=Marge gauche de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginLeft=Marge gauche de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.marginRight=Marge droite de la page en millimètres. (Vide par défaut)
|
HTMLToPDF.marginRight=Marge droite de la page en millimètres. (Vide par défaut)
|
||||||
HTMLToPDF.printBackground=Restituer l'image de fond des sites web.
|
HTMLToPDF.printBackground=Restituer l’image de fond des sites web.
|
||||||
HTMLToPDF.defaultHeader=Activer l'entête par défaut (Nom et numéro de page)
|
HTMLToPDF.defaultHeader=Activer l’entête par défaut (Nom et numéro de page)
|
||||||
HTMLToPDF.cssMediaType=Modifier le type de média CSS de la page.
|
HTMLToPDF.cssMediaType=Modifier le type de média CSS de la page.
|
||||||
HTMLToPDF.none=Aucun
|
HTMLToPDF.none=Aucun
|
||||||
HTMLToPDF.print=Imprimer
|
HTMLToPDF.print=Imprimer
|
||||||
@@ -705,7 +676,7 @@ autoSplitPDF.header=Séparer automatiquement les pages
|
|||||||
autoSplitPDF.description=Imprimez, insérez, numérisez, téléchargez et laissez-nous séparer automatiquement vos documents. Aucun travail de tri manuel nécessaire.
|
autoSplitPDF.description=Imprimez, insérez, numérisez, téléchargez et laissez-nous séparer automatiquement vos documents. Aucun travail de tri manuel nécessaire.
|
||||||
autoSplitPDF.selectText.1=Imprimez des feuilles de séparation ci-dessous (le mode noir et blanc convient).
|
autoSplitPDF.selectText.1=Imprimez des feuilles de séparation ci-dessous (le mode noir et blanc convient).
|
||||||
autoSplitPDF.selectText.2=Numérisez tous vos documents en une seule fois en insérant les feuilles intercalaires entre eux.
|
autoSplitPDF.selectText.2=Numérisez tous vos documents en une seule fois en insérant les feuilles intercalaires entre eux.
|
||||||
autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Stirling PDF s'occuper du reste.
|
autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Stirling PDF s’occuper du reste.
|
||||||
autoSplitPDF.selectText.4=Les feuilles de séparation sont automatiquement détectées et supprimées, garantissant un document final soigné.
|
autoSplitPDF.selectText.4=Les feuilles de séparation sont automatiquement détectées et supprimées, garantissant un document final soigné.
|
||||||
autoSplitPDF.formPrompt=PDF contenant des feuilles de séparation de Stirling PDF :
|
autoSplitPDF.formPrompt=PDF contenant des feuilles de séparation de Stirling PDF :
|
||||||
autoSplitPDF.duplexMode=Mode recto-verso
|
autoSplitPDF.duplexMode=Mode recto-verso
|
||||||
@@ -727,11 +698,11 @@ pageLayout.submit=Fusionner
|
|||||||
|
|
||||||
|
|
||||||
#scalePages
|
#scalePages
|
||||||
scalePages.title=Ajuster la taille ou l'échelle
|
scalePages.title=Ajuster la taille ou l’échelle
|
||||||
scalePages.header=Ajuster la taille ou l'échelle
|
scalePages.header=Ajuster la taille ou l’échelle
|
||||||
scalePages.pageSize=Taille d'une page du document
|
scalePages.pageSize=Taille d’une page du document
|
||||||
scalePages.keepPageSize=Original Size
|
scalePages.keepPageSize=Original Size
|
||||||
scalePages.scaleFactor=Niveau de zoom (recadrage) d'une page
|
scalePages.scaleFactor=Niveau de zoom (recadrage) d’une page
|
||||||
scalePages.submit=Ajuster
|
scalePages.submit=Ajuster
|
||||||
|
|
||||||
|
|
||||||
@@ -739,10 +710,10 @@ scalePages.submit=Ajuster
|
|||||||
certSign.title=Signer avec un certificat
|
certSign.title=Signer avec un certificat
|
||||||
certSign.header=Signer avec un certificat (Travail en cours)
|
certSign.header=Signer avec un certificat (Travail en cours)
|
||||||
certSign.selectPDF=PDF à signer
|
certSign.selectPDF=PDF à signer
|
||||||
certSign.jksNote=Note: Si votre type de certificat n'est pas listé ci-dessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant l'outil en ligne de commande keytool. Puis choisissez l'option Fichier .jks ci-dessous.
|
certSign.jksNote=Note: Si votre type de certificat n’est pas listé ci-dessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant l’outil en ligne de commande keytool. Puis choisissez l’option Fichier .jks ci-dessous.
|
||||||
certSign.selectKey=Fichier de clé privée (format PKCS#8, peut être .pem ou .der)
|
certSign.selectKey=Fichier de clé privée (format PKCS#8, peut être .pem ou .der)
|
||||||
certSign.selectCert=Fichier de certificat (format X.509, peut être .pem ou .der)
|
certSign.selectCert=Fichier de certificat (format X.509, peut être .pem ou .der)
|
||||||
certSign.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s'il n'est fourni, il doit contenir votre clé privée et votre certificat)
|
certSign.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s’il n’est fourni, il doit contenir votre clé privée et votre certificat)
|
||||||
certSign.selectJKS=Sélectionner votre fichier Java Keystore File (.jks or .keystore):
|
certSign.selectJKS=Sélectionner votre fichier Java Keystore File (.jks or .keystore):
|
||||||
certSign.certType=Type de certificat
|
certSign.certType=Type de certificat
|
||||||
certSign.password=Mot de passe keystore ou clé privée le cas échéant
|
certSign.password=Mot de passe keystore ou clé privée le cas échéant
|
||||||
@@ -754,10 +725,10 @@ certSign.submit=Signer
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Supprimer la Signature de Certificat
|
removeCertSign.title=Remove Certificate Signature
|
||||||
removeCertSign.header=Supprimer le certificat numérique du PDF
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
removeCertSign.selectPDF=Sélectionnez un fichier PDF :
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
removeCertSign.submit=Supprimer la Signature
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
@@ -784,21 +755,18 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Comparer
|
compare.submit=Comparer
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Livres et BD vers PDF
|
BookToPDF.title=Livres et BD vers PDF
|
||||||
BookToPDF.header=Livre vers PDF
|
BookToPDF.header=Livre vers PDF
|
||||||
BookToPDF.credit=Utilise Calibre
|
BookToPDF.credit=Utiliser Calibre
|
||||||
BookToPDF.submit=Convertir
|
BookToPDF.submit=Convertir
|
||||||
|
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDF vers Livre
|
PDFToBook.title=PDF vers Livre
|
||||||
PDFToBook.header=PDF vers Livre
|
PDFToBook.header=PDF vers Livre
|
||||||
PDFToBook.selectText.1=Format
|
PDFToBook.selectText.1=Format
|
||||||
PDFToBook.credit=Utilise Calibre
|
PDFToBook.credit=Utiliser Calibre
|
||||||
PDFToBook.submit=Convertir
|
PDFToBook.submit=Convertir
|
||||||
|
|
||||||
#sign
|
#sign
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Dessiner une signature
|
|||||||
sign.text=Saisir de texte
|
sign.text=Saisir de texte
|
||||||
sign.clear=Effacer
|
sign.clear=Effacer
|
||||||
sign.add=Ajouter
|
sign.add=Ajouter
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -831,9 +794,9 @@ flatten.submit=Rendre inerte
|
|||||||
|
|
||||||
#ScannerImageSplit
|
#ScannerImageSplit
|
||||||
ScannerImageSplit.selectText.1=Seuil de rotation
|
ScannerImageSplit.selectText.1=Seuil de rotation
|
||||||
ScannerImageSplit.selectText.2=Définit l'angle absolu minimum requis pour la rotation de l'image (par défaut : 10).
|
ScannerImageSplit.selectText.2=Définit l’angle absolu minimum requis pour la rotation de l’image (par défaut : 10).
|
||||||
ScannerImageSplit.selectText.3=Tolérance
|
ScannerImageSplit.selectText.3=Tolérance
|
||||||
ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d'arrière-plan estimée (par défaut : 20).
|
ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d’arrière-plan estimée (par défaut : 20).
|
||||||
ScannerImageSplit.selectText.5=Surface minimale
|
ScannerImageSplit.selectText.5=Surface minimale
|
||||||
ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut : 8 000).
|
ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut : 8 000).
|
||||||
ScannerImageSplit.selectText.7=Surface de contour minimale
|
ScannerImageSplit.selectText.7=Surface de contour minimale
|
||||||
@@ -849,24 +812,24 @@ ocr.header=OCR (Reconnaissance optique de caractères) / Nettoyage des numérisa
|
|||||||
ocr.selectText.1=Langues à détecter dans le PDF (celles listées sont celles actuellement détectées)
|
ocr.selectText.1=Langues à détecter dans le PDF (celles listées sont celles actuellement détectées)
|
||||||
ocr.selectText.2=Produire un fichier texte contenant le texte détecté à côté du PDF
|
ocr.selectText.2=Produire un fichier texte contenant le texte détecté à côté du PDF
|
||||||
ocr.selectText.3=Corriger les pages qui ont été numérisées à un angle oblique en les remettant en place
|
ocr.selectText.3=Corriger les pages qui ont été numérisées à un angle oblique en les remettant en place
|
||||||
ocr.selectText.4=Nettoyer la page afin qu'il soit moins probable que l'OCR trouve du texte dans le bruit de fond, sans modifier la sortie
|
ocr.selectText.4=Nettoyer la page afin qu’il soit moins probable que l’OCR trouve du texte dans le bruit de fond, sans modifier la sortie
|
||||||
ocr.selectText.5=Nettoyer la page afin qu'il soit moins probable que l'OCR trouve du texte dans le bruit de fond, en modifiant la sortie
|
ocr.selectText.5=Nettoyer la page afin qu’il soit moins probable que l’OCR trouve du texte dans le bruit de fond, en modifiant la sortie
|
||||||
ocr.selectText.6=Ignorer les pages contenant du texte interactif, n'analyser que les pages qui sont des images
|
ocr.selectText.6=Ignorer les pages contenant du texte interactif, n’analyser que les pages qui sont des images
|
||||||
ocr.selectText.7=Forcer l'OCR, analyser chaque page et supprimer tous les éléments de texte d'origine
|
ocr.selectText.7=Forcer l’OCR, analyser chaque page et supprimer tous les éléments de texte d’origine
|
||||||
ocr.selectText.8=Normal (génère une erreur si le PDF contient du texte)
|
ocr.selectText.8=Normal (génère une erreur si le PDF contient du texte)
|
||||||
ocr.selectText.9=Paramètres additionnels
|
ocr.selectText.9=Paramètres additionnels
|
||||||
ocr.selectText.10=Mode OCR
|
ocr.selectText.10=Mode OCR
|
||||||
ocr.selectText.11=Supprimer les images après l'OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l'étape de conversion)
|
ocr.selectText.11=Supprimer les images après l’OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l’étape de conversion)
|
||||||
ocr.selectText.12=Type de rendu (avancé)
|
ocr.selectText.12=Type de rendu (avancé)
|
||||||
ocr.help=Veuillez lire cette documentation pour savoir comment utiliser l'OCR pour d'autres langues ou une utilisation hors Docker :
|
ocr.help=Veuillez lire cette documentation pour savoir comment utiliser l’OCR pour d’autres langues ou une utilisation hors Docker :
|
||||||
ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l'OCR.
|
ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l’OCR.
|
||||||
ocr.submit=Traiter
|
ocr.submit=Traiter
|
||||||
|
|
||||||
|
|
||||||
#extractImages
|
#extractImages
|
||||||
extractImages.title=Extraire les images
|
extractImages.title=Extraire les images
|
||||||
extractImages.header=Extraire les images
|
extractImages.header=Extraire les images
|
||||||
extractImages.selectText=Format d'image dans lequel convertir les images extraites
|
extractImages.selectText=Format d’image dans lequel convertir les images extraites
|
||||||
extractImages.allowDuplicates=Save duplicate images
|
extractImages.allowDuplicates=Save duplicate images
|
||||||
extractImages.submit=Extraire
|
extractImages.submit=Extraire
|
||||||
|
|
||||||
@@ -882,10 +845,10 @@ fileToPDF.submit=Convertir
|
|||||||
|
|
||||||
#compress
|
#compress
|
||||||
compress.title=Compresser un PDF
|
compress.title=Compresser un PDF
|
||||||
compress.header=Compresser un PDF (lorsque c'est possible!)
|
compress.header=Compresser un PDF (lorsque c’est possible!)
|
||||||
compress.credit=Ce service utilise Ghostscript pour la compression et l'optimisation des PDF.
|
compress.credit=Ce service utilise Ghostscript pour la compression et l’optimisation des PDF.
|
||||||
compress.selectText.1=Mode manuel – de 1 à 4
|
compress.selectText.1=Mode manuel – de 1 à 4
|
||||||
compress.selectText.2=Niveau d'optimisation
|
compress.selectText.2=Niveau d’optimisation
|
||||||
compress.selectText.3=4 (terrible pour les images textuelles)
|
compress.selectText.3=4 (terrible pour les images textuelles)
|
||||||
compress.selectText.4=Mode automatique – ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
|
compress.selectText.4=Mode automatique – ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
|
||||||
compress.selectText.5=Taille PDF attendue (par exemple, 25 MB, 10,8 MB, 25 KB)
|
compress.selectText.5=Taille PDF attendue (par exemple, 25 MB, 10,8 MB, 25 KB)
|
||||||
@@ -970,9 +933,9 @@ split.submit=Diviser
|
|||||||
imageToPDF.title=Image en PDF
|
imageToPDF.title=Image en PDF
|
||||||
imageToPDF.header=Image en PDF
|
imageToPDF.header=Image en PDF
|
||||||
imageToPDF.submit=Convertir
|
imageToPDF.submit=Convertir
|
||||||
imageToPDF.selectLabel=Options d'ajustement de l'image
|
imageToPDF.selectLabel=Options d’ajustement de l’image
|
||||||
imageToPDF.fillPage=Remplir la page
|
imageToPDF.fillPage=Remplir la page
|
||||||
imageToPDF.fitDocumentToImage=Ajuster la page à l'image
|
imageToPDF.fitDocumentToImage=Ajuster la page à l’image
|
||||||
imageToPDF.maintainAspectRatio=Maintenir les proportions
|
imageToPDF.maintainAspectRatio=Maintenir les proportions
|
||||||
imageToPDF.selectText.2=Rotation automatique du PDF
|
imageToPDF.selectText.2=Rotation automatique du PDF
|
||||||
imageToPDF.selectText.3=Logique multi-fichiers (uniquement activée si vous travaillez avec plusieurs images)
|
imageToPDF.selectText.3=Logique multi-fichiers (uniquement activée si vous travaillez avec plusieurs images)
|
||||||
@@ -983,11 +946,11 @@ imageToPDF.selectText.5=Convertir en PDF séparés
|
|||||||
#pdfToImage
|
#pdfToImage
|
||||||
pdfToImage.title=Image en PDF
|
pdfToImage.title=Image en PDF
|
||||||
pdfToImage.header=Image en PDF
|
pdfToImage.header=Image en PDF
|
||||||
pdfToImage.selectText=Format d'image
|
pdfToImage.selectText=Format d’image
|
||||||
pdfToImage.singleOrMultiple=Type de résultat
|
pdfToImage.singleOrMultiple=Type de résultat
|
||||||
pdfToImage.single=Une seule grande image
|
pdfToImage.single=Une seule grande image
|
||||||
pdfToImage.multi=Plusieurs images
|
pdfToImage.multi=Plusieurs images
|
||||||
pdfToImage.colorType=Type d'impression
|
pdfToImage.colorType=Type d’impression
|
||||||
pdfToImage.color=Couleur
|
pdfToImage.color=Couleur
|
||||||
pdfToImage.grey=Niveaux de gris
|
pdfToImage.grey=Niveaux de gris
|
||||||
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
|
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
|
||||||
@@ -999,21 +962,21 @@ pdfToImage.info=Python is not installed. Required for WebP conversion.
|
|||||||
addPassword.title=Ajouter un mot de passe
|
addPassword.title=Ajouter un mot de passe
|
||||||
addPassword.header=Ajouter un mot de passe
|
addPassword.header=Ajouter un mot de passe
|
||||||
addPassword.selectText.1=PDF à chiffrer
|
addPassword.selectText.1=PDF à chiffrer
|
||||||
addPassword.selectText.2=Mot de passe de l'utilisateur
|
addPassword.selectText.2=Mot de passe de l’utilisateur
|
||||||
addPassword.selectText.3=Longueur de la clé de chiffrement
|
addPassword.selectText.3=Longueur de la clé de chiffrement
|
||||||
addPassword.selectText.4=Les valeurs plus élevées sont plus fortes, mais les valeurs plus faibles ont une meilleure compatibilité.
|
addPassword.selectText.4=Les valeurs plus élevées sont plus fortes, mais les valeurs plus faibles ont une meilleure compatibilité.
|
||||||
addPassword.selectText.5=Autorisations à définir (utilisation recommandée avec le mot de passe du propriétaire)
|
addPassword.selectText.5=Autorisations à définir (utilisation recommandée avec le mot de passe du propriétaire)
|
||||||
addPassword.selectText.6=Empêcher l'assemblage du document
|
addPassword.selectText.6=Empêcher l’assemblage du document
|
||||||
addPassword.selectText.7=Empêcher l'extraction de contenu
|
addPassword.selectText.7=Empêcher l’extraction de contenu
|
||||||
addPassword.selectText.8=Empêcher l'extraction pour l'accessibilité
|
addPassword.selectText.8=Empêcher l’extraction pour l’accessibilité
|
||||||
addPassword.selectText.9=Empêcher de remplir les formulaires
|
addPassword.selectText.9=Empêcher de remplir les formulaires
|
||||||
addPassword.selectText.10=Empêcher la modification
|
addPassword.selectText.10=Empêcher la modification
|
||||||
addPassword.selectText.11=Empêcher la modification des annotations
|
addPassword.selectText.11=Empêcher la modification des annotations
|
||||||
addPassword.selectText.12=Empêcher l'impression
|
addPassword.selectText.12=Empêcher l’impression
|
||||||
addPassword.selectText.13=Empêcher l'impression des différents formats
|
addPassword.selectText.13=Empêcher l’impression des différents formats
|
||||||
addPassword.selectText.14=Mot de passe du propriétaire
|
addPassword.selectText.14=Mot de passe du propriétaire
|
||||||
addPassword.selectText.15=Restreint ce qui peut être fait avec le document une fois qu'il est ouvert (non pris en charge par tous les lecteurs).
|
addPassword.selectText.15=Restreint ce qui peut être fait avec le document une fois qu’il est ouvert (non pris en charge par tous les lecteurs).
|
||||||
addPassword.selectText.16=Restreint l'ouverture du document lui-même.
|
addPassword.selectText.16=Restreint l’ouverture du document lui-même.
|
||||||
addPassword.submit=Chiffrer
|
addPassword.submit=Chiffrer
|
||||||
|
|
||||||
|
|
||||||
@@ -1041,14 +1004,14 @@ permissions.header=Modifier les permissions
|
|||||||
permissions.warning=Attention, pour que ces permissions soient immuables il est recommandé de les paramétrer avec un mot de passe via la page Ajouter un mot de passe.
|
permissions.warning=Attention, pour que ces permissions soient immuables il est recommandé de les paramétrer avec un mot de passe via la page Ajouter un mot de passe.
|
||||||
permissions.selectText.1=Sélectionnez le PDF
|
permissions.selectText.1=Sélectionnez le PDF
|
||||||
permissions.selectText.2=Permissions à définir
|
permissions.selectText.2=Permissions à définir
|
||||||
permissions.selectText.3=Empêcher l'assemblage du document
|
permissions.selectText.3=Empêcher l’assemblage du document
|
||||||
permissions.selectText.4=Empêcher l'extraction de contenu
|
permissions.selectText.4=Empêcher l’extraction de contenu
|
||||||
permissions.selectText.5=Empêcher l'extraction pour l'accessibilité
|
permissions.selectText.5=Empêcher l’extraction pour l’accessibilité
|
||||||
permissions.selectText.6=Empêcher de remplir les formulaires
|
permissions.selectText.6=Empêcher de remplir les formulaires
|
||||||
permissions.selectText.7=Empêcher la modification
|
permissions.selectText.7=Empêcher la modification
|
||||||
permissions.selectText.8=Empêcher la modification des annotations
|
permissions.selectText.8=Empêcher la modification des annotations
|
||||||
permissions.selectText.9=Empêcher l'impression
|
permissions.selectText.9=Empêcher l’impression
|
||||||
permissions.selectText.10=Empêcher l'impression des différents formats
|
permissions.selectText.10=Empêcher l’impression des différents formats
|
||||||
permissions.submit=Modifier
|
permissions.submit=Modifier
|
||||||
|
|
||||||
|
|
||||||
@@ -1073,7 +1036,7 @@ changeMetadata.keywords=Mots clés
|
|||||||
changeMetadata.modDate=Date de modification (yyyy/MM/dd HH:mm:ss)
|
changeMetadata.modDate=Date de modification (yyyy/MM/dd HH:mm:ss)
|
||||||
changeMetadata.producer=Producteur
|
changeMetadata.producer=Producteur
|
||||||
changeMetadata.subject=Sujet
|
changeMetadata.subject=Sujet
|
||||||
changeMetadata.trapped=Recouvrement (technique d'impression)
|
changeMetadata.trapped=Recouvrement (technique d’impression)
|
||||||
changeMetadata.selectText.4=Autres métadonnées
|
changeMetadata.selectText.4=Autres métadonnées
|
||||||
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée
|
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée
|
||||||
changeMetadata.submit=Modifier
|
changeMetadata.submit=Modifier
|
||||||
@@ -1086,7 +1049,7 @@ pdfToPDFA.credit=Ce service utilise ghostscript pour la conversion en PDF/A.
|
|||||||
pdfToPDFA.submit=Convertir
|
pdfToPDFA.submit=Convertir
|
||||||
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
|
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
|
||||||
pdfToPDFA.outputFormat=Format de sortie
|
pdfToPDFA.outputFormat=Format de sortie
|
||||||
pdfToPDFA.pdfWithDigitalSignature=Le PDF contient une signature numérique. Elle sera supprimée dans l'étape suivante.
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
@@ -1148,13 +1111,13 @@ split-by-size-or-count.submit=Séparer
|
|||||||
overlay-pdfs.header=Incrustation de PDF
|
overlay-pdfs.header=Incrustation de PDF
|
||||||
overlay-pdfs.baseFile.label=Sélectionner le fichier PDF de base
|
overlay-pdfs.baseFile.label=Sélectionner le fichier PDF de base
|
||||||
overlay-pdfs.overlayFiles.label=Sélectionner les fichiers PDF à superposer
|
overlay-pdfs.overlayFiles.label=Sélectionner les fichiers PDF à superposer
|
||||||
overlay-pdfs.mode.label=Sélectionner le mode d'incrustation
|
overlay-pdfs.mode.label=Sélectionner le mode d’incrustation
|
||||||
overlay-pdfs.mode.sequential=Superposition séquentielle
|
overlay-pdfs.mode.sequential=Superposition séquentielle
|
||||||
overlay-pdfs.mode.interleaved=Superposition entrelacée
|
overlay-pdfs.mode.interleaved=Superposition entrelacée
|
||||||
overlay-pdfs.mode.fixedRepeat=Superposition à répétition fixe
|
overlay-pdfs.mode.fixedRepeat=Superposition à répétition fixe
|
||||||
overlay-pdfs.counts.label=Nombre de superpositions (pour le mode de répétition fixe)
|
overlay-pdfs.counts.label=Nombre de superpositions (pour le mode de répétition fixe)
|
||||||
overlay-pdfs.counts.placeholder=Compteurs (séparés par des virgules, exemple : 2,3,1)
|
overlay-pdfs.counts.placeholder=Compteurs (séparés par des virgules, exemple : 2,3,1)
|
||||||
overlay-pdfs.position.label=Définir la position de l'incrustation
|
overlay-pdfs.position.label=Définir la position de l’incrustation
|
||||||
overlay-pdfs.position.foreground=Premier plan
|
overlay-pdfs.position.foreground=Premier plan
|
||||||
overlay-pdfs.position.background=Arrière-plan
|
overlay-pdfs.position.background=Arrière-plan
|
||||||
overlay-pdfs.submit=Soumettre
|
overlay-pdfs.submit=Soumettre
|
||||||
@@ -1188,45 +1151,31 @@ licenses.version=Version
|
|||||||
licenses.license=Licence
|
licenses.license=Licence
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Enquête
|
survey.nav=Survey
|
||||||
survey.title=Enquête Stirling-PDF
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF n'a pas de suivi, donc nous voulons entendre nos utilisateurs pour améliorer Stirling-PDF !
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF a changé depuis la dernière enquête ! Pour en savoir plus, veuillez consulter notre article de blog ici :
|
survey.please=Please consider taking our survey!
|
||||||
survey.changes2=Avec ces changements, nous obtenons un soutien commercial rémunéré et un financement
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.please=Veuillez envisager de répondre à notre enquête !
|
survey.button=Take Survey
|
||||||
survey.disabled=(La fenêtre contextuelle de l'enquête sera désactivée dans les mises à jour suivantes mais sera disponible en bas de page)
|
survey.dontShowAgain=Don't show again
|
||||||
survey.button=Répondre à l'enquête
|
|
||||||
survey.dontShowAgain=Ne plus afficher
|
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
error.sorry=Désolé pour ce problème !
|
error.sorry=Désolé pour ce problème !
|
||||||
error.needHelp=Besoin d'aide / Vous avez trouvé un problème ?
|
error.needHelp=Besoin d’aide / Vous avez trouvé un problème ?
|
||||||
error.contactTip=Si vous avez encore des problèmes, n'hésitez pas à nous contacter pour obtenir de l'aide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord :
|
error.contactTip=Si vous avez encore des problèmes, n’hésitez pas à nous contacter pour obtenir de l’aide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord :
|
||||||
error.404.head=404 - Page non trouvée | oups on s'est foiré !
|
error.404.head=404 - Page non trouvée | oups on s’est foiré !
|
||||||
error.404.1=Nous ne parvenons pas à trouver la page que vous recherchez.
|
error.404.1=Nous ne parvenons pas à trouver la page que vous recherchez.
|
||||||
error.404.2=Quelque chose n'a pas fonctionné
|
error.404.2=Quelque chose n’a pas fonctionné
|
||||||
error.github=Créer un ticket sur GitHub
|
error.github=Créer un ticket sur GitHub
|
||||||
error.showStack=Afficher la Stack Trace
|
error.showStack=Afficher la Stack Trace
|
||||||
error.copyStack=Copier la Stack Trace
|
error.copyStack=Copier la Stack Trace
|
||||||
error.githubSubmit=GitHub - Créer un ticket
|
error.githubSubmit=GitHub - Créer un ticket
|
||||||
error.discordSubmit=Discord - Poster un message de demande d'assistance
|
error.discordSubmit=Discord - Poster un message de demande d’assistance
|
||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Supprimer l'image
|
removeImage.title=Remove image
|
||||||
removeImage.header=Supprimer l'image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Supprimer l'image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Supprimer l'image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Diviser un PDF par Chapitres
|
|
||||||
splitByChapters.header=Diviser un PDF par Chapitres
|
|
||||||
splitByChapters.bookmarkLevel=Niveau de Signet
|
|
||||||
splitByChapters.includeMetadata=Inclure les Métadonnées
|
|
||||||
splitByChapters.allowDuplicates=Autoriser les Doublons
|
|
||||||
splitByChapters.desc.1=Cet outil divise un fichier PDF en plusieurs PDF en fonction de sa structure de chapitres.
|
|
||||||
splitByChapters.desc.2=Niveau de Signet : Choisissez le niveau de signets à utiliser pour la division (0 pour le niveau supérieur, 1 pour le deuxième niveau, etc...).
|
|
||||||
splitByChapters.desc.3=Inclure les Métadonnées : Si coché, les métadonnées du PDF original seront incluses dans chaque PDF divisé.
|
|
||||||
splitByChapters.desc.4=Autoriser les Doublons : Si coché, permet à plusieurs signets sur la même page de créer des PDF séparés.
|
|
||||||
splitByChapters.submit=Diviser le PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Síntiúis
|
|||||||
color=Dath
|
color=Dath
|
||||||
sponsor=Urraitheoir
|
sponsor=Urraitheoir
|
||||||
info=Eolas
|
info=Eolas
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Píblíne:
|
|||||||
pipelineOptions.saveButton=Íosluchtaigh
|
pipelineOptions.saveButton=Íosluchtaigh
|
||||||
pipelineOptions.validateButton=Bailíochtaigh
|
pipelineOptions.validateButton=Bailíochtaigh
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ 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=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ 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
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ 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.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redact
|
autoRedact.title=Auto Redact
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Dath Aibhsithe 2:
|
|||||||
compare.document.1=Doiciméad 1
|
compare.document.1=Doiciméad 1
|
||||||
compare.document.2=Doiciméad 2
|
compare.document.2=Doiciméad 2
|
||||||
compare.submit=Déan comparáid idir
|
compare.submit=Déan comparáid idir
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Leabhair agus comics a PDF
|
BookToPDF.title=Leabhair agus comics a PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Tarraing Síniú
|
|||||||
sign.text=Ionchur Téacs
|
sign.text=Ionchur Téacs
|
||||||
sign.clear=Glan
|
sign.clear=Glan
|
||||||
sign.add=Cuir
|
sign.add=Cuir
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ 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 has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
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é
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=पृष्ठ
|
page=पृष्ठ
|
||||||
pages=पृष्ठों
|
pages=पृष्ठों
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validate
|
pipelineOptions.validateButton=Validate
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=पीडीएफ से कनवर्ट कर
|
|||||||
navbar.sections.security=संकेत और सुरक्षा
|
navbar.sections.security=संकेत और सुरक्षा
|
||||||
navbar.sections.advance=उन्नत
|
navbar.sections.advance=उन्नत
|
||||||
navbar.sections.edit=देखें और संपादित करें
|
navbar.sections.edit=देखें और संपादित करें
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=स्वत: गोपनीयकरण
|
autoRedact.title=स्वत: गोपनीयकरण
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=दस्तावेज़ 1
|
compare.document.1=दस्तावेज़ 1
|
||||||
compare.document.2=दस्तावेज़ 2
|
compare.document.2=दस्तावेज़ 2
|
||||||
compare.submit=तुलना करें
|
compare.submit=तुलना करें
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=हस्ताक्षर बनाएँ
|
|||||||
sign.text=पाठ इनपुट
|
sign.text=पाठ इनपुट
|
||||||
sign.clear=साफ़ करें
|
sign.clear=साफ़ करें
|
||||||
sign.add=जोड़ें
|
sign.add=जोड़ें
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=License
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Doniraj
|
|||||||
color=Boja
|
color=Boja
|
||||||
sponsor=Sponzor
|
sponsor=Sponzor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Preuzmi datoteku
|
pipelineOptions.saveButton=Preuzmi datoteku
|
||||||
pipelineOptions.validateButton=Potvrdi
|
pipelineOptions.validateButton=Potvrdi
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Pretvori iz PDF
|
|||||||
navbar.sections.security=Potpis & sigurnost
|
navbar.sections.security=Potpis & sigurnost
|
||||||
navbar.sections.advance=Napredno
|
navbar.sections.advance=Napredno
|
||||||
navbar.sections.edit=Pregled & Uređivanje
|
navbar.sections.edit=Pregled & Uređivanje
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Pristup odbijen
|
|||||||
login.oauth2InvalidTokenResponse=Nevažeći odgovor tokena
|
login.oauth2InvalidTokenResponse=Nevažeći odgovor tokena
|
||||||
login.oauth2InvalidIdToken=Nevažeći ID token
|
login.oauth2InvalidIdToken=Nevažeći ID token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatsko uređivanje
|
autoRedact.title=Automatsko uređivanje
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Uporedi
|
compare.submit=Uporedi
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Knjige i stripovi u PDF
|
BookToPDF.title=Knjige i stripovi u PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Nacrtaj potpis
|
|||||||
sign.text=Tekstualni unos
|
sign.text=Tekstualni unos
|
||||||
sign.clear=Obriši
|
sign.clear=Obriši
|
||||||
sign.add=Dodaj
|
sign.add=Dodaj
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licenca
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validate
|
pipelineOptions.validateButton=Validate
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Érzékeny tartalom eltávolítása
|
autoRedact.title=Érzékeny tartalom eltávolítása
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokumentum 1
|
compare.document.1=Dokumentum 1
|
||||||
compare.document.2=Dokumentum 2
|
compare.document.2=Dokumentum 2
|
||||||
compare.submit=Összehasonlítás
|
compare.submit=Összehasonlítás
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Aláírás rajzolása
|
|||||||
sign.text=Szöveg beírása
|
sign.text=Szöveg beírása
|
||||||
sign.clear=Törlés
|
sign.clear=Törlés
|
||||||
sign.add=Hozzáadás
|
sign.add=Hozzáadás
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=License
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
###########
|
###########
|
||||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||||
language.direction=ltr
|
language.direction=ltr
|
||||||
addPageNumbers.fontSize=Ukuran Fonta
|
addPageNumbers.fontSize=Font Size
|
||||||
addPageNumbers.fontName=Nama Fonta
|
addPageNumbers.fontName=Font Name
|
||||||
pdfPrompt=Pilih PDF
|
pdfPrompt=Pilih PDF
|
||||||
multiPdfPrompt=Pilih PDF (2+)
|
multiPdfPrompt=Pilih PDF (2+)
|
||||||
multiPdfDropPrompt=Pilih (atau seret & letakkan)) semua PDF yang Anda butuhkan
|
multiPdfDropPrompt=Pilih (atau seret & letakkan)) semua PDF yang Anda butuhkan
|
||||||
@@ -12,17 +12,17 @@ imgPrompt=Pilih Gambar
|
|||||||
genericSubmit=Kirim
|
genericSubmit=Kirim
|
||||||
processTimeWarning=Peringatan: Proses ini dapat memakan waktu hingga satu menit, tergantung pada ukuran berkas
|
processTimeWarning=Peringatan: Proses ini dapat memakan waktu hingga satu menit, tergantung pada ukuran berkas
|
||||||
pageOrderPrompt=Urutan Halaman Khusus (Masukkan daftar nomor halaman yang dipisahkan dengan koma atau Fungsi seperti 2n + 1) :
|
pageOrderPrompt=Urutan Halaman Khusus (Masukkan daftar nomor halaman yang dipisahkan dengan koma atau Fungsi seperti 2n + 1) :
|
||||||
pageSelectionPrompt=Pemilihan Halaman Kustom (Masukkan daftar nomor halaman dipisahkan dengan koma 1,5,6 atau Fungsi seperti 2n+1) :
|
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||||
goToPage=Ke
|
goToPage=Ke
|
||||||
true=Benar
|
true=Benar
|
||||||
false=Salah
|
false=Salah
|
||||||
unknown=Tidak diketahui
|
unknown=Tidak diketahui
|
||||||
save=Simpan
|
save=Simpan
|
||||||
saveToBrowser=Simpan ke Peramban
|
saveToBrowser=Save to Browser
|
||||||
close=Tutup
|
close=Tutup
|
||||||
filesSelected=berkas dipilih
|
filesSelected=berkas dipilih
|
||||||
noFavourites=Tidak ada favorit yang ditambahkan
|
noFavourites=Tidak ada favorit yang ditambahkan
|
||||||
downloadComplete=Unduhan Lengkap
|
downloadComplete=Download Complete
|
||||||
bored=Bosan Menunggu?
|
bored=Bosan Menunggu?
|
||||||
alphabet=Abjad
|
alphabet=Abjad
|
||||||
downloadPdf=Unduh PDF
|
downloadPdf=Unduh PDF
|
||||||
@@ -46,115 +46,95 @@ red=Merah
|
|||||||
green=Hijau
|
green=Hijau
|
||||||
blue=Biru
|
blue=Biru
|
||||||
custom=Kustom...
|
custom=Kustom...
|
||||||
WorkInProgess=Pekerjaan sedang diproses, Mungkin tidak berfungsi atau terdapat kutu, Silakan laporkan masalah apa pun!
|
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||||
poweredBy=Ditenagai oleh
|
poweredBy=Powered by
|
||||||
yes=Ya
|
yes=Yes
|
||||||
no=Tidak
|
no=No
|
||||||
changedCredsMessage=Kredensial berubah!!
|
changedCredsMessage=Kredensial berubah!!
|
||||||
notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
|
notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
|
||||||
userNotFoundMessage=Pengguna tidak ditemukan.
|
userNotFoundMessage=Pengguna tidak ditemukan.
|
||||||
incorrectPasswordMessage=Kata sandi saat ini salah.
|
incorrectPasswordMessage=Kata sandi saat ini salah.
|
||||||
usernameExistsMessage=Nama pengguna baru sudah ada.
|
usernameExistsMessage=Nama pengguna baru sudah ada.
|
||||||
invalidUsernameMessage=Nama pengguna tidak valid, nama pengguna hanya boleh mengandung huruf, angka, dan karakter khusus berikut @._+- atau harus berupa alamat email yang valid.
|
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||||
invalidPasswordMessage=Kata sandi tidak boleh kosong dan tidak boleh memiliki spasi di awal atau akhir.
|
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
||||||
confirmPasswordErrorMessage=Kata Sandi Baru dan Konfirmasi Kata Sandi Baru harus sama.
|
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||||
deleteCurrentUserMessage=Pengguna yang sedang masuk tidak dapat dihapus.
|
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||||
deleteUsernameExistsMessage=Nama pengguna tidak ada dan tidak dapat dihapus.
|
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||||
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
|
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
|
||||||
disabledCurrentUserMessage=Pengguna saat ini tidak dapat dinonaktifkan
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
|
downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
|
||||||
userAlreadyExistsOAuthMessage=Pengguna sudah ada sebagai pengguna OAuth2.
|
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
|
||||||
userAlreadyExistsWebMessage=Pengguna sudah ada sebagai pengguna web.
|
userAlreadyExistsWebMessage=The user already exists as an web user.
|
||||||
error=Kesalahan
|
error=Error
|
||||||
oops=Ups!
|
oops=Oops!
|
||||||
help=Bantuan
|
help=Help
|
||||||
goHomepage=Kembali ke Beranda
|
goHomepage=Go to Homepage
|
||||||
joinDiscord=Bergabung dengan server Discord kami
|
joinDiscord=Join our Discord server
|
||||||
seeDockerHub=Lihat Docker Hub
|
seeDockerHub=See Docker Hub
|
||||||
visitGithub=Kunjungi Repositori Github
|
visitGithub=Visit Github Repository
|
||||||
donate=Donasi
|
donate=Donate
|
||||||
color=Warna
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
page=Page
|
||||||
page=Halaman
|
pages=Pages
|
||||||
pages=Halaman-halaman
|
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Kebijakan Privasi
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Syarat dan Ketentuan
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=Aksesibilitas
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Kebijakan Kuki
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=Impresum
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=Menu Pipeline (Beta)
|
pipeline.header=Pipeline Menu (Beta)
|
||||||
pipeline.uploadButton=Unggah Kustom
|
pipeline.uploadButton=Upload Custom
|
||||||
pipeline.configureButton=Konfigurasi
|
pipeline.configureButton=Configure
|
||||||
pipeline.defaultOption=Kustom
|
pipeline.defaultOption=Custom
|
||||||
pipeline.submitButton=Kirim
|
pipeline.submitButton=Submit
|
||||||
pipeline.help=Bantuan Pipeline
|
pipeline.help=Pipeline Help
|
||||||
pipeline.scanHelp=Bantuan Pemindaian Folder
|
pipeline.scanHelp=Folder Scanning Help
|
||||||
pipeline.deletePrompt=Apakah Anda yakin ingin menghapus pipeline
|
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
######################
|
######################
|
||||||
pipelineOptions.header=Konfigurasi Pipeline
|
pipelineOptions.header=Pipeline Configuration
|
||||||
pipelineOptions.pipelineNameLabel=Nama Pipeline
|
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||||
pipelineOptions.saveSettings=Simpan Pengaturan Operasi
|
pipelineOptions.saveSettings=Save Operation Settings
|
||||||
pipelineOptions.pipelineNamePrompt=Masukkan nama pipeline di sini
|
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||||
pipelineOptions.selectOperation=Pilih Operasi
|
pipelineOptions.selectOperation=Select Operation
|
||||||
pipelineOptions.addOperationButton=Tambah operasi
|
pipelineOptions.addOperationButton=Add operation
|
||||||
pipelineOptions.pipelineHeader=Pipeline:
|
pipelineOptions.pipelineHeader=Pipeline:
|
||||||
pipelineOptions.saveButton=Unduh
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Validasi
|
pipelineOptions.validateButton=Validate
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade ke Pro
|
|
||||||
enterpriseEdition.warning=Fitur ini hanya tersedia untuk pengguna Pro.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro mendukung berkas konfigurasi YAML dan fitur SSO lainnya.
|
|
||||||
enterpriseEdition.ssoAdvert=Mencari lebih banyak fitur manajemen pengguna? Lihat Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Apakah Anda ingin membuat Stirling PDF lebih baik?
|
|
||||||
analytics.paragraph1=Stirling PDF memiliki analitik yang dapat diaktifkan untuk membantu kami meningkatkan produk. Kami tidak melacak informasi pribadi atau konten berkas.
|
|
||||||
analytics.paragraph2=Silakan pertimbangkan untuk mengaktifkan analitik agar Stirling PDF dapat berkembang dan untuk memungkinkan kami memahami pengguna kami dengan lebih baik.
|
|
||||||
analytics.enable=Aktifkan analitik
|
|
||||||
analytics.disable=Nonaktifkan analitik
|
|
||||||
analytics.settings=Anda dapat mengubah pengaturan untuk analitik di berkas config/settings.yml
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
#############
|
#############
|
||||||
navbar.favorite=Favorit
|
navbar.favorite=Favorites
|
||||||
navbar.darkmode=Mode Gelap
|
navbar.darkmode=Mode Gelap
|
||||||
navbar.language=Bahasa
|
navbar.language=Languages
|
||||||
navbar.settings=Pengaturan
|
navbar.settings=Pengaturan
|
||||||
navbar.allTools=Alat
|
navbar.allTools=Tools
|
||||||
navbar.multiTool=Alat Multi
|
navbar.multiTool=Multi Tools
|
||||||
navbar.sections.organize=Atur
|
navbar.sections.organize=Organize
|
||||||
navbar.sections.convertTo=Konversi ke PDF
|
navbar.sections.convertTo=Convert to PDF
|
||||||
navbar.sections.convertFrom=Konversi dari PDF
|
navbar.sections.convertFrom=Convert from PDF
|
||||||
navbar.sections.security=Tanda Tangan & Keamanan
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Langkah Lanjut
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=Melihat & Mengedit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Populer
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
#############
|
#############
|
||||||
settings.title=Pengaturan
|
settings.title=Pengaturan
|
||||||
settings.update=Pembaruan tersedia
|
settings.update=Pembaruan tersedia
|
||||||
settings.updateAvailable={0} adalah versi yang terpasang saat ini. Versi baru ({1}) tersedia.
|
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
|
||||||
settings.appVersion=Versi Aplikasi:
|
settings.appVersion=Versi Aplikasi:
|
||||||
settings.downloadOption.title=Pilih opsi unduhan (Untuk unduhan berkas tunggal non zip):
|
settings.downloadOption.title=Pilih opsi unduhan (Untuk unduhan berkas tunggal non zip):
|
||||||
settings.downloadOption.1=Buka di jendela yang sama
|
settings.downloadOption.1=Buka di jendela yang sama
|
||||||
@@ -163,13 +143,13 @@ settings.downloadOption.3=Unduh berkas
|
|||||||
settings.zipThreshold=Berkas zip ketika jumlah berkas yang diunduh melebihi
|
settings.zipThreshold=Berkas zip ketika jumlah berkas yang diunduh melebihi
|
||||||
settings.signOut=Keluar
|
settings.signOut=Keluar
|
||||||
settings.accountSettings=Pengaturan Akun
|
settings.accountSettings=Pengaturan Akun
|
||||||
settings.bored.help=Mengaktifkan permainan telur paskah
|
settings.bored.help=Enables easter egg game
|
||||||
settings.cacheInputs.name=Simpan input formulir
|
settings.cacheInputs.name=Save form inputs
|
||||||
settings.cacheInputs.help=Aktifkan untuk menyimpan input yang pernah digunakan untuk menjalankan di masa depan
|
settings.cacheInputs.help=Enable to store previously used inputs for future runs
|
||||||
|
|
||||||
changeCreds.title=Ubah Kredensial
|
changeCreds.title=Ubah Kredensial
|
||||||
changeCreds.header=Perbarui Detail Akun Anda
|
changeCreds.header=Perbarui Detail Akun Anda
|
||||||
changeCreds.changePassword=Anda menggunakan kredensial login default. Silakan masukkan kata sandi baru
|
changeCreds.changePassword=You are using default login credentials. Please enter a new password
|
||||||
changeCreds.newUsername=Nama Pengguna Baru
|
changeCreds.newUsername=Nama Pengguna Baru
|
||||||
changeCreds.oldPassword=Kata Sandi Saat Ini
|
changeCreds.oldPassword=Kata Sandi Saat Ini
|
||||||
changeCreds.newPassword=Kata Sandi Baru
|
changeCreds.newPassword=Kata Sandi Baru
|
||||||
@@ -204,48 +184,46 @@ adminUserSettings.header=Pengaturan Kontrol Admin
|
|||||||
adminUserSettings.admin=Admin
|
adminUserSettings.admin=Admin
|
||||||
adminUserSettings.user=Pengguna
|
adminUserSettings.user=Pengguna
|
||||||
adminUserSettings.addUser=Tambahkan Pengguna Baru
|
adminUserSettings.addUser=Tambahkan Pengguna Baru
|
||||||
adminUserSettings.deleteUser=Hapus Pengguna
|
adminUserSettings.deleteUser=Delete User
|
||||||
adminUserSettings.confirmDeleteUser=Haruskah pengguna dihapus?
|
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||||
adminUserSettings.confirmChangeUserStatus=Haruskah pengguna dinonaktifkan/diaktifkan?
|
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
||||||
adminUserSettings.usernameInfo=Nama pengguna hanya boleh mengandung huruf, angka, dan karakter khusus berikut @._+- atau harus berupa alamat email yang valid.
|
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||||
adminUserSettings.roles=Peran
|
adminUserSettings.roles=Peran
|
||||||
adminUserSettings.role=Peran
|
adminUserSettings.role=Peran
|
||||||
adminUserSettings.actions=Tindakan
|
adminUserSettings.actions=Tindakan
|
||||||
adminUserSettings.apiUser=Pengguna API Terbatas
|
adminUserSettings.apiUser=Pengguna API Terbatas
|
||||||
adminUserSettings.extraApiUser=Additional Limited API User
|
adminUserSettings.extraApiUser=Additional Limited API User
|
||||||
adminUserSettings.webOnlyUser=Pengguna Khusus Web
|
adminUserSettings.webOnlyUser=Pengguna Khusus Web
|
||||||
adminUserSettings.demoUser=Pengguna Demo (Tanpa pengaturan kustom)
|
adminUserSettings.demoUser=Demo User (No custom settings)
|
||||||
adminUserSettings.internalApiUser=Pengguna API Internal
|
adminUserSettings.internalApiUser=Internal API User
|
||||||
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
|
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
|
||||||
adminUserSettings.submit=Simpan Pengguna
|
adminUserSettings.submit=Simpan Pengguna
|
||||||
adminUserSettings.changeUserRole=Ubah Peran Pengguna
|
adminUserSettings.changeUserRole=Ubah Peran Pengguna
|
||||||
adminUserSettings.authenticated=Terautentikasi
|
adminUserSettings.authenticated=Authenticated
|
||||||
adminUserSettings.editOwnProfil=Edit profil sendiri
|
adminUserSettings.editOwnProfil=Edit own profile
|
||||||
adminUserSettings.enabledUser=Pengguna diaktifkan
|
adminUserSettings.enabledUser=enabled user
|
||||||
adminUserSettings.disabledUser=Pengguna dinonaktifkan
|
adminUserSettings.disabledUser=disabled user
|
||||||
adminUserSettings.activeUsers=Pengguna Aktif:
|
adminUserSettings.activeUsers=Active Users:
|
||||||
adminUserSettings.disabledUsers=Pengguna Dinonaktifkan:
|
adminUserSettings.disabledUsers=Disabled Users:
|
||||||
adminUserSettings.totalUsers=Total Pengguna:
|
adminUserSettings.totalUsers=Total Users:
|
||||||
adminUserSettings.lastRequest=Permintaan Terakhir
|
adminUserSettings.lastRequest=Last Request
|
||||||
|
|
||||||
|
|
||||||
database.title=Impor/Ekspor Database
|
database.title=Database Import/Export
|
||||||
database.header=Impor/Ekspor Database
|
database.header=Database Import/Export
|
||||||
database.fileName=Nama Berkas
|
database.fileName=File Name
|
||||||
database.creationDate=Tanggal Pembuatan
|
database.creationDate=Creation Date
|
||||||
database.fileSize=Ukuran Berkas
|
database.fileSize=File Size
|
||||||
database.deleteBackupFile=Hapus Berkas Cadangan
|
database.deleteBackupFile=Delete Backup File
|
||||||
database.importBackupFile=Impor Berkas Cadangan
|
database.importBackupFile=Import Backup File
|
||||||
database.downloadBackupFile=Unduh Berkas Cadangan
|
database.downloadBackupFile=Download Backup File
|
||||||
database.info_1=Ketika mengimpor data, sangat penting untuk memastikan struktur yang benar. Jika Anda tidak yakin dengan apa yang Anda lakukan, cari nasihat dan dukungan dari seorang profesional. Kesalahan dalam struktur dapat menyebabkan malfungsi aplikasi, bahkan hingga tidak dapat menjalankan aplikasi sama sekali.
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
database.info_2=Nama berkas tidak menjadi masalah saat mengunggah. Nama berkas akan diubah setelahnya mengikuti format backup_user_yyyyMMddHHmm.sql, memastikan konsistensi dalam penamaan.
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
database.submit=Impor Cadangan
|
database.submit=Import Backup
|
||||||
database.importIntoDatabaseSuccessed=Impor ke database berhasil
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
database.fileNotFound=Berkas tidak Ditemukan
|
database.fileNotFound=File not Found
|
||||||
database.fileNullOrEmpty=Berkas tidak boleh null atau kosong
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Impor Berkas Gagal
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Sesi Anda telah kedaluwarsa. Silakan muat ulang halaman dan coba lagi.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@@ -315,7 +293,7 @@ removePassword.tags=aman,Dekripsi,keamanan,buka kata sandi,hapus kata sandi
|
|||||||
|
|
||||||
home.compressPdfs.title=Kompres
|
home.compressPdfs.title=Kompres
|
||||||
home.compressPdfs.desc=Kompres PDF untuk mengurangi ukuran berkas.
|
home.compressPdfs.desc=Kompres PDF untuk mengurangi ukuran berkas.
|
||||||
compressPdfs.tags=remas, kecil, mini
|
compressPdfs.tags=squish, kecil, kecil
|
||||||
|
|
||||||
|
|
||||||
home.changeMetadata.title=Ubah Metadata
|
home.changeMetadata.title=Ubah Metadata
|
||||||
@@ -492,41 +470,36 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
|
|||||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF ke Buku
|
home.PDFToBook.title=PDF to Book
|
||||||
home.PDFToBook.desc=Mengonversi PDF ke format Buku/Komik menggunakan calibre
|
home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
|
||||||
PDFToBook.tags=Buku,Komik,Calibre,Konversi,manga,amazon,kindle
|
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.BookToPDF.title=Buku ke PDF
|
home.BookToPDF.title=Book to PDF
|
||||||
home.BookToPDF.desc=Mengonversi format Buku/Komik ke PDF menggunakan calibre
|
home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
|
||||||
BookToPDF.tags=Buku,Komik,Calibre,Konversi,manga,amazon,kindle
|
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Hapus Gambar
|
home.removeImagePdf.title=Remove image
|
||||||
home.removeImagePdf.desc=Hapus gambar dari PDF untuk mengurangi ukuran file
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Hapus Gambar,Operasi Halaman,Backend,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Pisahkan PDF berdasarkan Bab
|
|
||||||
home.splitPdfByChapters.desc=Memisahkan PDF menjadi beberapa file berdasarkan struktur babnya.
|
|
||||||
splitPdfByChapters.tags=pemisahan,bab,bookmark,atur
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Ganti-Inversi-Warna
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Ganti-Inversi Warna PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Ganti dan Inversi Warna
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Ganti warna untuk teks dan latar belakang dalam PDF dan inversi seluruh warna PDF untuk mengurangi ukuran file
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Ganti Warna,Operasi Halaman,Backend,server side
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Opsi Ganti atau Inversi warna
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Default(Warna kontras tinggi default)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Kustom(Warna yang disesuaikan)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Full-Inversi(Inversi semua warna)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Opsi warna kontras tinggi
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=teks putih di latar belakang hitam
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=teks hitam di latar belakang putih
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=teks kuning di latar belakang hitam
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=teks hijau di latar belakang hitam
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Pilih warna teks
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Pilih warna latar belakang
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Ganti
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -545,17 +518,15 @@ login.locked=Akun Anda telah dikunci.
|
|||||||
login.signinTitle=Silakan masuk
|
login.signinTitle=Silakan masuk
|
||||||
login.ssoSignIn=Masuk melalui Single Sign - on
|
login.ssoSignIn=Masuk melalui Single Sign - on
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
|
login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
|
||||||
login.oauth2AdminBlockedUser=Registrasi atau login pengguna yang tidak terdaftar saat ini diblokir. Silakan hubungi administrator.
|
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
||||||
login.oauth2RequestNotFound=Permintaan otorisasi tidak ditemukan
|
login.oauth2RequestNotFound=Authorization request not found
|
||||||
login.oauth2InvalidUserInfoResponse=Respons Info Pengguna Tidak Valid
|
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
||||||
login.oauth2invalidRequest=Permintaan Tidak Valid
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Akses Ditolak
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Respons Token Tidak Valid
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Token ID Tidak Valid
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=Pengguna dinonaktifkan, login saat ini diblokir dengan nama pengguna ini. Silakan hubungi administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=Anda sudah login ke
|
|
||||||
login.alreadyLoggedIn2=perangkat. Silakan keluar dari perangkat dan coba lagi.
|
|
||||||
login.toManySessions=Anda memiliki terlalu banyak sesi aktif
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redaksional Otomatis
|
autoRedact.title=Redaksional Otomatis
|
||||||
@@ -619,37 +590,37 @@ HTMLToPDF.header=HTML Ke PDF
|
|||||||
HTMLToPDF.help=Menerima berkas HTML dan ZIP yang berisi html / css / gambar, dll yang diperlukan
|
HTMLToPDF.help=Menerima berkas HTML dan ZIP yang berisi html / css / gambar, dll yang diperlukan
|
||||||
HTMLToPDF.submit=Konversi
|
HTMLToPDF.submit=Konversi
|
||||||
HTMLToPDF.credit=Menggunakan WeasyPrint
|
HTMLToPDF.credit=Menggunakan WeasyPrint
|
||||||
HTMLToPDF.zoom=Tingkat perbersan untuk menampilkan situs web.
|
HTMLToPDF.zoom=Zoom level for displaying the website.
|
||||||
HTMLToPDF.pageWidth=Lebar halaman dalam sentimeter. (Kosong untuk default)
|
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
|
||||||
HTMLToPDF.pageHeight=Tinggi halaman dalam sentimeter. (Kosong untuk default)
|
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
|
||||||
HTMLToPDF.marginTop=Margin atas halaman dalam milimeter. (Kosong untuk default)
|
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
|
||||||
HTMLToPDF.marginBottom=Margin bawah halaman dalam milimeter. (Kosong untuk default)
|
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
|
||||||
HTMLToPDF.marginLeft=Margin kiri halaman dalam milimeter. (Kosong untuk default)
|
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
|
||||||
HTMLToPDF.marginRight=Margin kanan halaman dalam milimeter. (Kosong untuk default)
|
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
|
||||||
HTMLToPDF.printBackground=Render latar belakang situs web.
|
HTMLToPDF.printBackground=Render the background of websites.
|
||||||
HTMLToPDF.defaultHeader=Aktifkan Header Default (Nama dan nomor halaman)
|
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
|
||||||
HTMLToPDF.cssMediaType=Ubah jenis media CSS halaman.
|
HTMLToPDF.cssMediaType=Change the CSS media type of the page.
|
||||||
HTMLToPDF.none=Tidak ada
|
HTMLToPDF.none=None
|
||||||
HTMLToPDF.print=Cetak
|
HTMLToPDF.print=Print
|
||||||
HTMLToPDF.screen=Layar
|
HTMLToPDF.screen=Screen
|
||||||
|
|
||||||
|
|
||||||
#AddStampRequest
|
#AddStampRequest
|
||||||
AddStampRequest.header=Stampel PDF
|
AddStampRequest.header=Stamp PDF
|
||||||
AddStampRequest.title=Stampel PDF
|
AddStampRequest.title=Stamp PDF
|
||||||
AddStampRequest.stampType=Jenis Stampel
|
AddStampRequest.stampType=Stamp Type
|
||||||
AddStampRequest.stampText=Teks Stampel
|
AddStampRequest.stampText=Stamp Text
|
||||||
AddStampRequest.stampImage=Gambar Stampel
|
AddStampRequest.stampImage=Stamp Image
|
||||||
AddStampRequest.alphabet=Alfabet
|
AddStampRequest.alphabet=Alphabet
|
||||||
AddStampRequest.fontSize=Ukuran Font/Gambar
|
AddStampRequest.fontSize=Font/Image Size
|
||||||
AddStampRequest.rotation=Rotasi
|
AddStampRequest.rotation=Rotation
|
||||||
AddStampRequest.opacity=Transparansi
|
AddStampRequest.opacity=Opacity
|
||||||
AddStampRequest.position=Posisi
|
AddStampRequest.position=Position
|
||||||
AddStampRequest.overrideX=Timpa Koordinat X
|
AddStampRequest.overrideX=Override X Coordinate
|
||||||
AddStampRequest.overrideY=Timpa Koordinat Y
|
AddStampRequest.overrideY=Override Y Coordinate
|
||||||
AddStampRequest.customMargin=Margin Kustom
|
AddStampRequest.customMargin=Custom Margin
|
||||||
AddStampRequest.customColor=Warna Teks Kustom
|
AddStampRequest.customColor=Custom Text Color
|
||||||
AddStampRequest.submit=Kirim
|
AddStampRequest.submit=Submit
|
||||||
|
|
||||||
|
|
||||||
#sanitizePDF
|
#sanitizePDF
|
||||||
@@ -739,7 +710,7 @@ scalePages.submit=Kirim
|
|||||||
certSign.title=Penandatanganan Sertifikat
|
certSign.title=Penandatanganan Sertifikat
|
||||||
certSign.header=Menandatangani PDF dengan sertifikat Anda (Sedang dalam proses)
|
certSign.header=Menandatangani PDF dengan sertifikat Anda (Sedang dalam proses)
|
||||||
certSign.selectPDF=Pilih Berkas PDF untuk Penandatanganan:
|
certSign.selectPDF=Pilih Berkas PDF untuk Penandatanganan:
|
||||||
certSign.jksNote=Catatan: Jika tipe sertifikat Anda tidak terdaftar di bawah, silakan konversi ke file Java Keystore (.jks) menggunakan alat baris perintah keytool. Kemudian, pilih opsi file .jks di bawah.
|
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
|
||||||
certSign.selectKey=Pilih Berkas Kunci Pribadi Anda (format PKCS # 8, bisa .pem atau .der):
|
certSign.selectKey=Pilih Berkas Kunci Pribadi Anda (format PKCS # 8, bisa .pem atau .der):
|
||||||
certSign.selectCert=Pilih Berkas Sertifikat Anda (format X.509, bisa .pem atau .der):
|
certSign.selectCert=Pilih Berkas Sertifikat Anda (format X.509, bisa .pem atau .der):
|
||||||
certSign.selectP12=Pilih Berkas Keystore PKCS #12 Anda (.p12 atau .pfx) (Opsional, Jika disediakan, berkas tersebut harus berisi kunci pribadi dan sertifikat Anda):
|
certSign.selectP12=Pilih Berkas Keystore PKCS #12 Anda (.p12 atau .pfx) (Opsional, Jika disediakan, berkas tersebut harus berisi kunci pribadi dan sertifikat Anda):
|
||||||
@@ -754,15 +725,15 @@ certSign.submit=Tanda tangani PDF
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Hapus Tanda Tangan Sertifikat
|
removeCertSign.title=Remove Certificate Signature
|
||||||
removeCertSign.header=Hapus sertifikat digital dari PDF
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
removeCertSign.selectPDF=Pilih file PDF:
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
removeCertSign.submit=Hapus Tanda Tangan
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Hapus yang Kosong
|
removeBlanks.title=Hapus Halaman Kosong
|
||||||
removeBlanks.header=Hapus Halaman Kosong
|
removeBlanks.header=Remove Blank Pages
|
||||||
removeBlanks.threshold=Ambang Batas Keputihan Piksel:
|
removeBlanks.threshold=Ambang Batas Keputihan Piksel:
|
||||||
removeBlanks.thresholdDesc=Ambang batas untuk menentukan seberapa putih piksel putih yang harus diklasifikasikan sebagai 'Putih'. 0=Hitam, 255 putih murni.
|
removeBlanks.thresholdDesc=Ambang batas untuk menentukan seberapa putih piksel putih yang harus diklasifikasikan sebagai 'Putih'. 0=Hitam, 255 putih murni.
|
||||||
removeBlanks.whitePercent=Persen Putih (%):
|
removeBlanks.whitePercent=Persen Putih (%):
|
||||||
@@ -779,27 +750,24 @@ removeAnnotations.submit=Hapus
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Bandingkan
|
compare.title=Bandingkan
|
||||||
compare.header=Bandingkan PDF
|
compare.header=Bandingkan PDF
|
||||||
compare.highlightColor.1=Warna Sorotan 1:
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
compare.highlightColor.2=Warna Sorotan 2:
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokumen 1
|
compare.document.1=Dokumen 1
|
||||||
compare.document.2=Dokumen 2
|
compare.document.2=Dokumen 2
|
||||||
compare.submit=Bandingkan
|
compare.submit=Bandingkan
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Buku dan Komik ke PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
BookToPDF.header=Buku ke PDF
|
BookToPDF.header=Book to PDF
|
||||||
BookToPDF.credit=Menggunakan Calibre
|
BookToPDF.credit=Uses Calibre
|
||||||
BookToPDF.submit=Konversi
|
BookToPDF.submit=Convert
|
||||||
|
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDF ke Buku
|
PDFToBook.title=PDF to Book
|
||||||
PDFToBook.header=PDF ke Buku
|
PDFToBook.header=PDF to Book
|
||||||
PDFToBook.selectText.1=Format
|
PDFToBook.selectText.1=Format
|
||||||
PDFToBook.credit=Menggunakan Calibre
|
PDFToBook.credit=Uses Calibre
|
||||||
PDFToBook.submit=Konversi
|
PDFToBook.submit=Convert
|
||||||
|
|
||||||
#sign
|
#sign
|
||||||
sign.title=Tanda
|
sign.title=Tanda
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Gambar Tanda Tangan
|
|||||||
sign.text=Masukan Teks
|
sign.text=Masukan Teks
|
||||||
sign.clear=Hapus
|
sign.clear=Hapus
|
||||||
sign.add=Tambah
|
sign.add=Tambah
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -840,7 +803,7 @@ ScannerImageSplit.selectText.7=Area Kontur Minimum:
|
|||||||
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
|
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
|
||||||
ScannerImageSplit.selectText.9=Ukuran Batas:
|
ScannerImageSplit.selectText.9=Ukuran Batas:
|
||||||
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
|
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
|
||||||
ScannerImageSplit.info=Python tidak terinstal. Ini diperlukan untuk menjalankan.
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -914,16 +877,16 @@ pdfOrganiser.title=Pengaturan Halaman
|
|||||||
pdfOrganiser.header=Pengaturan Halaman PDF
|
pdfOrganiser.header=Pengaturan Halaman PDF
|
||||||
pdfOrganiser.submit=Susun ulang halaman
|
pdfOrganiser.submit=Susun ulang halaman
|
||||||
pdfOrganiser.mode=Mode
|
pdfOrganiser.mode=Mode
|
||||||
pdfOrganiser.mode.1=Urutan Halaman Kustom
|
pdfOrganiser.mode.1=Custom Page Order
|
||||||
pdfOrganiser.mode.2=Urutan Terbalik
|
pdfOrganiser.mode.2=Reverse Order
|
||||||
pdfOrganiser.mode.3=Sortir Duplex
|
pdfOrganiser.mode.3=Duplex Sort
|
||||||
pdfOrganiser.mode.4=Sortir Buku
|
pdfOrganiser.mode.4=Booklet Sort
|
||||||
pdfOrganiser.mode.5=Sortir Buku Jahitan Samping
|
pdfOrganiser.mode.5=Side Stitch Booklet Sort
|
||||||
pdfOrganiser.mode.6=Pemisahan Genap-Ganjil
|
pdfOrganiser.mode.6=Odd-Even Split
|
||||||
pdfOrganiser.mode.7=Hapus Pertama
|
pdfOrganiser.mode.7=Remove First
|
||||||
pdfOrganiser.mode.8=Hapus Terakhir
|
pdfOrganiser.mode.8=Remove Last
|
||||||
pdfOrganiser.mode.9=Hapus Pertama dan Terakhir
|
pdfOrganiser.mode.9=Remove First and Last
|
||||||
pdfOrganiser.mode.10=Penggabungan Genap-Ganjil
|
pdfOrganiser.mode.10=Odd-Even Merge
|
||||||
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
|
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
|
||||||
|
|
||||||
|
|
||||||
@@ -992,7 +955,7 @@ pdfToImage.color=Warna
|
|||||||
pdfToImage.grey=Skala abu-abu
|
pdfToImage.grey=Skala abu-abu
|
||||||
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
|
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
|
||||||
pdfToImage.submit=Konversi
|
pdfToImage.submit=Konversi
|
||||||
pdfToImage.info=Python tidak terinstal. Diperlukan untuk konversi WebP.
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1070,7 +1033,7 @@ changeMetadata.author=Penulis:
|
|||||||
changeMetadata.creationDate=Tanggal Dibuat (yyyy/MM/dd HH:mm:ss):
|
changeMetadata.creationDate=Tanggal Dibuat (yyyy/MM/dd HH:mm:ss):
|
||||||
changeMetadata.creator=Pencipta:
|
changeMetadata.creator=Pencipta:
|
||||||
changeMetadata.keywords=Kata kunci:
|
changeMetadata.keywords=Kata kunci:
|
||||||
changeMetadata.modDate=Tangal Diperbarui (yyyy/MM/dd HH:mm:ss):
|
changeMetadata.modDate=Tangal Diupdate (yyyy/MM/dd HH:mm:ss):
|
||||||
changeMetadata.producer=Produser:
|
changeMetadata.producer=Produser:
|
||||||
changeMetadata.subject=Subjek:
|
changeMetadata.subject=Subjek:
|
||||||
changeMetadata.trapped=Terperangkap:
|
changeMetadata.trapped=Terperangkap:
|
||||||
@@ -1084,13 +1047,13 @@ pdfToPDFA.title=PDF Ke PDF/A
|
|||||||
pdfToPDFA.header=PDF ke PDF/A
|
pdfToPDFA.header=PDF ke PDF/A
|
||||||
pdfToPDFA.credit=Layanan ini menggunakan ghostscript untuk konversi PDF/A.
|
pdfToPDFA.credit=Layanan ini menggunakan ghostscript untuk konversi PDF/A.
|
||||||
pdfToPDFA.submit=Konversi
|
pdfToPDFA.submit=Konversi
|
||||||
pdfToPDFA.tip=Saat ini tidak dapat digunakan untuk beberapa input sekaligus
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Format keluaran
|
pdfToPDFA.outputFormat=Output format
|
||||||
pdfToPDFA.pdfWithDigitalSignature=PDF ini mengandung tanda tangan digital. Ini akan dihapus pada langkah berikutnya.
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
PDFToWord.title=PDF ke Word
|
PDFToWord.title=PDF Ke Word
|
||||||
PDFToWord.header=PDF ke Word
|
PDFToWord.header=PDF ke Word
|
||||||
PDFToWord.selectText.1=Hasil format berkas
|
PDFToWord.selectText.1=Hasil format berkas
|
||||||
PDFToWord.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
PDFToWord.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
||||||
@@ -1106,7 +1069,7 @@ PDFToPresentation.submit=Konversi
|
|||||||
|
|
||||||
|
|
||||||
#PDFToText
|
#PDFToText
|
||||||
PDFToText.title=PDF ke RTF (Text)
|
PDFToText.title=PDF Ke RTF (Text)
|
||||||
PDFToText.header=PDF ke RTF (Text)
|
PDFToText.header=PDF ke RTF (Text)
|
||||||
PDFToText.selectText.1=Hasil format berkas
|
PDFToText.selectText.1=Hasil format berkas
|
||||||
PDFToText.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
PDFToText.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
||||||
@@ -1114,20 +1077,20 @@ PDFToText.submit=Konversi
|
|||||||
|
|
||||||
|
|
||||||
#PDFToHTML
|
#PDFToHTML
|
||||||
PDFToHTML.title=PDF ke HTML
|
PDFToHTML.title=PDF Ke HTML
|
||||||
PDFToHTML.header=PDF ke HTML
|
PDFToHTML.header=PDF ke HTML
|
||||||
PDFToHTML.credit=Layanan ini menggunakan pdftohtml untuk konversi berkas.
|
PDFToHTML.credit=Layanan ini menggunakan pdftohtml untuk konversi berkas.
|
||||||
PDFToHTML.submit=Konversi
|
PDFToHTML.submit=Konversi
|
||||||
|
|
||||||
|
|
||||||
#PDFToXML
|
#PDFToXML
|
||||||
PDFToXML.title=PDF ke XML
|
PDFToXML.title=PDF Ke XML
|
||||||
PDFToXML.header=PDF ke XML
|
PDFToXML.header=PDF ke XML
|
||||||
PDFToXML.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
PDFToXML.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
|
||||||
PDFToXML.submit=Konversi
|
PDFToXML.submit=Konversi
|
||||||
|
|
||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF ke CSV
|
PDFToCSV.title=PDF Ke CSV
|
||||||
PDFToCSV.header=PDF ke CSV
|
PDFToCSV.header=PDF ke CSV
|
||||||
PDFToCSV.prompt=Pilih halaman untuk mengambil tabel
|
PDFToCSV.prompt=Pilih halaman untuk mengambil tabel
|
||||||
PDFToCSV.submit=Ektraksi
|
PDFToCSV.submit=Ektraksi
|
||||||
@@ -1168,65 +1131,51 @@ split-by-sections.vertical.label=Pembagian Vertikal
|
|||||||
split-by-sections.horizontal.placeholder=Input angka untuk pembagian horizontal
|
split-by-sections.horizontal.placeholder=Input angka untuk pembagian horizontal
|
||||||
split-by-sections.vertical.placeholder=Input angka untuk pembagian vertikal
|
split-by-sections.vertical.placeholder=Input angka untuk pembagian vertikal
|
||||||
split-by-sections.submit=Pisahkan PDF
|
split-by-sections.submit=Pisahkan PDF
|
||||||
split-by-sections.merge=Gabung Menjadi Berkas PDF Tunggal
|
split-by-sections.merge=Merge Into One PDF
|
||||||
|
|
||||||
|
|
||||||
#printFile
|
#printFile
|
||||||
printFile.title=Cetak File
|
printFile.title=Print File
|
||||||
printFile.header=Cetak File ke Printer
|
printFile.header=Print File to Printer
|
||||||
printFile.selectText.1=Pilih File untuk Dicetak
|
printFile.selectText.1=Select File to Print
|
||||||
printFile.selectText.2=Masukkan Nama Printer
|
printFile.selectText.2=Enter Printer Name
|
||||||
printFile.submit=Cetak
|
printFile.submit=Print
|
||||||
|
|
||||||
|
|
||||||
#licenses
|
#licenses
|
||||||
licenses.nav=Lisensi
|
licenses.nav=Licenses
|
||||||
licenses.title=Lisensi Pihak Ketiga
|
licenses.title=3rd Party Licenses
|
||||||
licenses.header=Lisensi Pihak Ketiga
|
licenses.header=3rd Party Licenses
|
||||||
licenses.module=Modul
|
licenses.module=Module
|
||||||
licenses.version=Versi
|
licenses.version=Version
|
||||||
licenses.license=Lisensi
|
licenses.license=License
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survei
|
survey.nav=Survey
|
||||||
survey.title=Survei Stirling-PDF
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF tidak memiliki pelacakan, jadi kami ingin mendengar dari pengguna kami untuk meningkatkan Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF telah berubah sejak survei terakhir! Untuk mengetahui lebih lanjut, silakan periksa posting blog kami di sini:
|
survey.please=Please consider taking our survey!
|
||||||
survey.changes2=Dengan perubahan ini, kami mendapatkan dukungan bisnis yang dibayar dan pendanaan
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.please=Silakan pertimbangkan untuk mengikuti survei kami!
|
survey.button=Take Survey
|
||||||
survey.disabled=(Popup survei akan dinonaktifkan dalam pembaruan berikutnya tetapi tersedia di bagian bawah halaman)
|
survey.dontShowAgain=Don't show again
|
||||||
survey.button=Ikuti Survei
|
|
||||||
survey.dontShowAgain=Jangan tampilkan lagi
|
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
error.sorry=Maaf atas masalah ini!
|
error.sorry=Sorry for the issue!
|
||||||
error.needHelp=Butuh bantuan / Menemukan masalah?
|
error.needHelp=Need help / Found an issue?
|
||||||
error.contactTip=Jika Anda masih mengalami kesulitan, jangan ragu untuk menghubungi kami untuk bantuan. Anda dapat mengirim tiket di halaman GitHub kami atau menghubungi kami melalui Discord:
|
error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
|
||||||
error.404.head=404 - Halaman Tidak Ditemukan | Ups, kami tersandung dalam kode!
|
error.404.head=404 - Page Not Found | Oops, we tripped in the code!
|
||||||
error.404.1=Kami tidak dapat menemukan halaman yang Anda cari.
|
error.404.1=We can't seem to find the page you're looking for.
|
||||||
error.404.2=Terjadi kesalahan
|
error.404.2=Something went wrong
|
||||||
error.github=Kirim tiket di GitHub
|
error.github=Submit a ticket on GitHub
|
||||||
error.showStack=Tampilkan Stack Trace
|
error.showStack=Show Stack Trace
|
||||||
error.copyStack=Salin Stack Trace
|
error.copyStack=Copy Stack Trace
|
||||||
error.githubSubmit=GitHub - Kirim tiket
|
error.githubSubmit=GitHub - Submit a ticket
|
||||||
error.discordSubmit=Discord - Kirim pos dukungan
|
error.discordSubmit=Discord - Submit Support post
|
||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Hapus gambar
|
removeImage.title=Remove image
|
||||||
removeImage.header=Hapus gambar
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Hapus gambar
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Hapus gambar
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Pecah PDF berdasarkan Bab
|
|
||||||
splitByChapters.header=Pecah PDF berdasarkan Bab
|
|
||||||
splitByChapters.bookmarkLevel=Tingkatan Markah
|
|
||||||
splitByChapters.includeMetadata=Termasuk Metadata
|
|
||||||
splitByChapters.allowDuplicates=Izinkan Duplikat
|
|
||||||
splitByChapters.desc.1=Alat ini membagi file PDF menjadi beberapa PDF berdasarkan struktur babnya.
|
|
||||||
splitByChapters.desc.2=Tingkatan Markah: Pilih tingkatan markah yang digunakan untuk membagi (0 untuk tingkat atas, 1 untuk tingkat kedua, dll.).
|
|
||||||
splitByChapters.desc.3=Termasuk Metadata: Jika dicentang, metadata asli PDF akan disertakan dalam setiap PDF yang dibagi.
|
|
||||||
splitByChapters.desc.4=Izinkan Duplikat: Jika dicentang, mengizinkan beberapa markah pada halaman yang sama untuk membuat PDF terpisah.
|
|
||||||
splitByChapters.submit=Pecah PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donazione
|
|||||||
color=Colore
|
color=Colore
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
page=Page
|
||||||
page=Pagina
|
pages=Pages
|
||||||
pages=Pagine
|
|
||||||
loading=Caricamento...
|
|
||||||
addToDoc=Aggiungi al documento
|
|
||||||
|
|
||||||
legal.privacy=Informativa sulla privacy
|
legal.privacy=Informativa sulla privacy
|
||||||
legal.terms=Termini e Condizioni
|
legal.terms=Termini e Condizioni
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Convalidare
|
pipelineOptions.validateButton=Convalidare
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Aggiorna alla versione Pro
|
|
||||||
enterpriseEdition.warning=Questa funzionalità è disponibile solo per gli utenti Pro.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supporta i file di configurazione YAML e altre funzionalità SSO.
|
|
||||||
enterpriseEdition.ssoAdvert=Cerchi altre funzionalità di gestione degli utenti? Dai un'occhiata a Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Vuoi migliorare Stirling PDF?
|
|
||||||
analytics.paragraph1=Stirling PDF ha opt-in analytics per aiutarci a migliorare il prodotto. Non tracciamo alcuna informazione personale o contenuto di file.
|
|
||||||
analytics.paragraph2=Si prega di prendere in considerazione l'attivazione dell'analytics per aiutare Stirling-PDF a crescere e consentirci di comprendere meglio i nostri utenti.
|
|
||||||
analytics.enable=Abilita analytics
|
|
||||||
analytics.disable=Disabilita analytics
|
|
||||||
analytics.settings=È possibile modificare le impostazioni per analitycs nel file config/settings.yml
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Converti da PDF
|
|||||||
navbar.sections.security=Firma & Sicurezza
|
navbar.sections.security=Firma & Sicurezza
|
||||||
navbar.sections.advance=Avanzate
|
navbar.sections.advance=Avanzate
|
||||||
navbar.sections.edit=Visualizza & Modifica
|
navbar.sections.edit=Visualizza & Modifica
|
||||||
navbar.sections.popular=Popolare
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File non trovato
|
|||||||
database.fileNullOrEmpty=Il file non deve essere nullo o vuoto
|
database.fileNullOrEmpty=Il file non deve essere nullo o vuoto
|
||||||
database.failedImportFile=Importazione file non riuscita
|
database.failedImportFile=Importazione file non riuscita
|
||||||
|
|
||||||
session.expired=La tua sessione è scaduta. Aggiorna la pagina e riprova.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,29 +482,24 @@ home.removeImagePdf.title=Rimuovi immagine
|
|||||||
home.removeImagePdf.desc=Rimuovi le immagini dal PDF per ridurre la dimensione del file
|
home.removeImagePdf.desc=Rimuovi le immagini dal PDF per ridurre la dimensione del file
|
||||||
removeImagePdf.tags=Rimuovi immagine,operazioni sulla pagina,back-end,lato server
|
removeImagePdf.tags=Rimuovi immagine,operazioni sulla pagina,back-end,lato server
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Dividi PDF per capitoli
|
|
||||||
home.splitPdfByChapters.desc=Dividi un PDF in più file in base alla struttura dei capitoli.
|
|
||||||
splitPdfByChapters.tags=dividi, capitoli, segnalibri, organizza
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Sostituisci-Inverti-Colore
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Sostituisci-Inverti colore PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Sostituisci e inverti il colore
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Sostituisci il colore del testo e dello sfondo nel PDF e inverti il colore completo del PDF per ridurre le dimensioni del file
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Sostituisci colore, Operazioni di pagina, Back-end, lato server
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Sostituisci o inverti le opzioni del colore
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Predefinito (colori ad alto contrasto predefiniti)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Personalizzato (colori personalizzati)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Inversione completa (inverte tutti i colori)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Opzioni di colore ad alto contrasto
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=testo bianco su sfondo nero
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Testo nero su sfondo bianco
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Testo giallo su sfondo nero
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Testo verde su sfondo nero
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Scegli il colore del testo
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Scegli il colore di sfondo
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Sostituisci
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Accesso negato
|
|||||||
login.oauth2InvalidTokenResponse=Risposta token non valida
|
login.oauth2InvalidTokenResponse=Risposta token non valida
|
||||||
login.oauth2InvalidIdToken=Id Token non valido
|
login.oauth2InvalidIdToken=Id Token non valido
|
||||||
login.userIsDisabled=L'utente è disattivato, l'accesso è attualmente bloccato con questo nome utente. Si prega di contattare l'amministratore.
|
login.userIsDisabled=L'utente è disattivato, l'accesso è attualmente bloccato con questo nome utente. Si prega di contattare l'amministratore.
|
||||||
login.alreadyLoggedIn=Hai già effettuato l'accesso a
|
|
||||||
login.alreadyLoggedIn2=dispositivi. Esci dai dispositivi e riprova.
|
|
||||||
login.toManySessions=Hai troppe sessioni attive
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redazione automatica
|
autoRedact.title=Redazione automatica
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Evidenzia colore 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Compara
|
compare.submit=Compara
|
||||||
compare.complex.message=Uno o entrambi i documenti forniti sono file di grandi dimensioni, l'accuratezza del confronto potrebbe risultare ridotta
|
|
||||||
compare.large.file.message=Uno o entrambi i documenti forniti sono troppo grandi per essere elaborati
|
|
||||||
compare.no.text.message=Uno o entrambi i PDF selezionati non hanno contenuto di testo. Si prega di scegliere PDF con testo per il confronto.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Libri e fumetti in PDF
|
BookToPDF.title=Libri e fumetti in PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Disegna Firma
|
|||||||
sign.text=Testo
|
sign.text=Testo
|
||||||
sign.clear=Cancella
|
sign.clear=Cancella
|
||||||
sign.add=Aggiungi
|
sign.add=Aggiungi
|
||||||
sign.saved=Firme salvate
|
|
||||||
sign.save=Firma salvata
|
|
||||||
sign.personalSigs=Firme personali
|
|
||||||
sign.sharedSigs=Firme condivise
|
|
||||||
sign.noSavedSigs=Nessuna firma salvata trovata
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licenza
|
|||||||
survey.nav=Sondaggio
|
survey.nav=Sondaggio
|
||||||
survey.title=Sondaggio Stirling-PDF
|
survey.title=Sondaggio Stirling-PDF
|
||||||
survey.description=Stirling-PDF non fa tracciamento, quindi vogliamo sentire i nostri utenti per migliorare Stirling-PDF!
|
survey.description=Stirling-PDF non fa tracciamento, quindi vogliamo sentire i nostri utenti per migliorare Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF è cambiato dall'ultimo sondaggio! Per saperne di più, consulta il nostro blog qui:
|
|
||||||
survey.changes2=Con questi cambiamenti stiamo ricevendo supporto aziendale e finanziamenti retribuiti
|
|
||||||
survey.please=Ti invitiamo a prendere in considerazione la possibilità di partecipare al nostro sondaggio!
|
survey.please=Ti invitiamo a prendere in considerazione la possibilità di partecipare al nostro sondaggio!
|
||||||
survey.disabled=(Il popup del sondaggio verrà disabilitato nei prossimi aggiornamenti ma sarà disponibile a piè di pagina)
|
survey.disabled=(Il popup del sondaggio verrà disabilitato nei prossimi aggiornamenti ma sarà disponibile a piè di pagina)
|
||||||
survey.button=Partecipa al sondaggio
|
survey.button=Partecipa al sondaggio
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Rimuovere immagine
|
|||||||
removeImage.header=Rimuovi immagine
|
removeImage.header=Rimuovi immagine
|
||||||
removeImage.removeImage=Rimuovi immagine
|
removeImage.removeImage=Rimuovi immagine
|
||||||
removeImage.submit=Rimuovi immagine
|
removeImage.submit=Rimuovi immagine
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Dividere PDF per capitoli
|
|
||||||
splitByChapters.header=Dividi PDF per capitoli
|
|
||||||
splitByChapters.bookmarkLevel=Livello segnalibro
|
|
||||||
splitByChapters.includeMetadata=Includi Metadati
|
|
||||||
splitByChapters.allowDuplicates=Consenti duplicati
|
|
||||||
splitByChapters.desc.1=Questo strumento divide un file PDF in più PDF in base alla struttura dei capitoli.
|
|
||||||
splitByChapters.desc.2=Livello segnalibro: seleziona il livello dei segnalibri da utilizzare per la suddivisione (0 per il livello superiore, 1 per il secondo livello, ecc.).
|
|
||||||
splitByChapters.desc.3=Includi metadati: se selezionato, i metadati del PDF originale verranno inclusi in ogni PDF diviso.
|
|
||||||
splitByChapters.desc.4=Consenti duplicati: se selezionata, consente più segnalibri sulla stessa pagina per creare PDF separati.
|
|
||||||
splitByChapters.submit=Dividi PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=寄付する
|
|||||||
color=色
|
color=色
|
||||||
sponsor=スポンサー
|
sponsor=スポンサー
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=プライバシーポリシー
|
legal.privacy=プライバシーポリシー
|
||||||
legal.terms=利用規約
|
legal.terms=利用規約
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=パイプライン:
|
|||||||
pipelineOptions.saveButton=ダウンロード
|
pipelineOptions.saveButton=ダウンロード
|
||||||
pipelineOptions.validateButton=検証
|
pipelineOptions.validateButton=検証
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=PDFから変換
|
|||||||
navbar.sections.security=署名とセキュリティ
|
navbar.sections.security=署名とセキュリティ
|
||||||
navbar.sections.advance=アドバンスド
|
navbar.sections.advance=アドバンスド
|
||||||
navbar.sections.edit=閲覧と編集
|
navbar.sections.edit=閲覧と編集
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=ファイルが見つかりません
|
|||||||
database.fileNullOrEmpty=ファイルは null または空であってはなりません
|
database.fileNullOrEmpty=ファイルは null または空であってはなりません
|
||||||
database.failedImportFile=ファイルのインポートに失敗
|
database.failedImportFile=ファイルのインポートに失敗
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=画像の削除
|
|||||||
home.removeImagePdf.desc=PDFから画像を削除してファイルサイズを小さくします
|
home.removeImagePdf.desc=PDFから画像を削除してファイルサイズを小さくします
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=アクセス拒否
|
|||||||
login.oauth2InvalidTokenResponse=無効なトークン応答
|
login.oauth2InvalidTokenResponse=無効なトークン応答
|
||||||
login.oauth2InvalidIdToken=無効なIDトークン
|
login.oauth2InvalidIdToken=無効なIDトークン
|
||||||
login.userIsDisabled=ユーザーは非アクティブ化されており、現在このユーザー名でのログインはブロックされています。管理者に連絡してください。
|
login.userIsDisabled=ユーザーは非アクティブ化されており、現在このユーザー名でのログインはブロックされています。管理者に連絡してください。
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自動塗りつぶし
|
autoRedact.title=自動塗りつぶし
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=ハイライトカラー 2:
|
|||||||
compare.document.1=ドキュメント 1
|
compare.document.1=ドキュメント 1
|
||||||
compare.document.2=ドキュメント 2
|
compare.document.2=ドキュメント 2
|
||||||
compare.submit=比較
|
compare.submit=比較
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=書籍やコミックをPDFに変換
|
BookToPDF.title=書籍やコミックをPDFに変換
|
||||||
@@ -809,11 +777,6 @@ sign.draw=署名を書く
|
|||||||
sign.text=テキスト入力
|
sign.text=テキスト入力
|
||||||
sign.clear=クリア
|
sign.clear=クリア
|
||||||
sign.add=追加
|
sign.add=追加
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=ライセンス
|
|||||||
survey.nav=アンケート
|
survey.nav=アンケート
|
||||||
survey.title=Stirling-PDFのアンケート
|
survey.title=Stirling-PDFのアンケート
|
||||||
survey.description=Stirling-PDFには追跡機能がないため、Stirling-PDFをより良くするために皆様の意見を聞かせてください!
|
survey.description=Stirling-PDFには追跡機能がないため、Stirling-PDFをより良くするために皆様の意見を聞かせてください!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=アンケートにご協力ください!
|
survey.please=アンケートにご協力ください!
|
||||||
survey.disabled=(アンケートのポップアップは、次の更新では無効になりますが、ページの下部に表示されます。)
|
survey.disabled=(アンケートのポップアップは、次の更新では無効になりますが、ページの下部に表示されます。)
|
||||||
survey.button=アンケートに答える
|
survey.button=アンケートに答える
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=画像の削除
|
|||||||
removeImage.header=画像の削除
|
removeImage.header=画像の削除
|
||||||
removeImage.removeImage=画像の削除
|
removeImage.removeImage=画像の削除
|
||||||
removeImage.submit=画像を削除
|
removeImage.submit=画像を削除
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=기부하기
|
|||||||
color=색상
|
color=색상
|
||||||
sponsor=스폰서
|
sponsor=스폰서
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=파이프라인:
|
|||||||
pipelineOptions.saveButton=다운로드
|
pipelineOptions.saveButton=다운로드
|
||||||
pipelineOptions.validateButton=확인
|
pipelineOptions.validateButton=확인
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=자동 검열
|
autoRedact.title=자동 검열
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=문서 1
|
compare.document.1=문서 1
|
||||||
compare.document.2=문서 2
|
compare.document.2=문서 2
|
||||||
compare.submit=비교
|
compare.submit=비교
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=책과 만화를 PDF로
|
BookToPDF.title=책과 만화를 PDF로
|
||||||
@@ -809,11 +777,6 @@ sign.draw=서명 그리기
|
|||||||
sign.text=텍스트 입력
|
sign.text=텍스트 입력
|
||||||
sign.clear=초기화
|
sign.clear=초기화
|
||||||
sign.add=추가
|
sign.add=추가
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=라이센스
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Doneer
|
|||||||
color=Kleur
|
color=Kleur
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pijplijn:
|
|||||||
pipelineOptions.saveButton=Downloaden
|
pipelineOptions.saveButton=Downloaden
|
||||||
pipelineOptions.validateButton=Valideren
|
pipelineOptions.validateButton=Valideren
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Converteren van PDF
|
|||||||
navbar.sections.security=Ondertekenen & beveiliging
|
navbar.sections.security=Ondertekenen & beveiliging
|
||||||
navbar.sections.advance=Geavanceerd
|
navbar.sections.advance=Geavanceerd
|
||||||
navbar.sections.edit=Bekijken & wijzigen
|
navbar.sections.edit=Bekijken & wijzigen
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Toegang geweigerd
|
|||||||
login.oauth2InvalidTokenResponse=Ongeldige tokenreactie
|
login.oauth2InvalidTokenResponse=Ongeldige tokenreactie
|
||||||
login.oauth2InvalidIdToken=Ongeldige ID token
|
login.oauth2InvalidIdToken=Ongeldige ID token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisch censureren
|
autoRedact.title=Automatisch censureren
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Vergelijken
|
compare.submit=Vergelijken
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Boeken en strips naar PDF
|
BookToPDF.title=Boeken en strips naar PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Handtekening tekenen
|
|||||||
sign.text=Tekstinvoer
|
sign.text=Tekstinvoer
|
||||||
sign.clear=Wissen
|
sign.clear=Wissen
|
||||||
sign.add=Toevoegen
|
sign.add=Toevoegen
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licentie
|
|||||||
survey.nav=Enquête
|
survey.nav=Enquête
|
||||||
survey.title=Stirling-PDF Enquête
|
survey.title=Stirling-PDF Enquête
|
||||||
survey.description=Stirling-PDF heeft geen tracking, dus we willen van onze gebruikers horen om Stirling-PDF te verbeteren.
|
survey.description=Stirling-PDF heeft geen tracking, dus we willen van onze gebruikers horen om Stirling-PDF te verbeteren.
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Overweeg alstublieft om onze enquête in te vullen!
|
survey.please=Overweeg alstublieft om onze enquête in te vullen!
|
||||||
survey.disabled=(Enquête popup wordt in een toekomstige update weggehaald, maar is beschikbaar aan de onderkant van de pagina.)
|
survey.disabled=(Enquête popup wordt in een toekomstige update weggehaald, maar is beschikbaar aan de onderkant van de pagina.)
|
||||||
survey.button=Vul enquête in.
|
survey.button=Vul enquête in.
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Doner
|
|||||||
color=Farge
|
color=Farge
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Last ned
|
pipelineOptions.saveButton=Last ned
|
||||||
pipelineOptions.validateButton=Valider
|
pipelineOptions.validateButton=Valider
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Konverter fra PDF
|
|||||||
navbar.sections.security=Signer & Sikkerhet
|
navbar.sections.security=Signer & Sikkerhet
|
||||||
navbar.sections.advance=Avansert
|
navbar.sections.advance=Avansert
|
||||||
navbar.sections.edit=Vis & Rediger
|
navbar.sections.edit=Vis & Rediger
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=Fil ikke funnet
|
|||||||
database.fileNullOrEmpty=Fil må ikke være tom eller null
|
database.fileNullOrEmpty=Fil må ikke være tom eller null
|
||||||
database.failedImportFile=Import av fil mislyktes
|
database.failedImportFile=Import av fil mislyktes
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Tilgang nektet
|
|||||||
login.oauth2InvalidTokenResponse=Ugyldig tokenrespons
|
login.oauth2InvalidTokenResponse=Ugyldig tokenrespons
|
||||||
login.oauth2InvalidIdToken=Ugyldig Id Token
|
login.oauth2InvalidIdToken=Ugyldig Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisk Sensurering
|
autoRedact.title=Automatisk Sensurering
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Uthevingsfarge 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Sammenlign
|
compare.submit=Sammenlign
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Bøker og Tegneserier til PDF
|
BookToPDF.title=Bøker og Tegneserier til PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Tegn signatur
|
|||||||
sign.text=Tekstinput
|
sign.text=Tekstinput
|
||||||
sign.clear=Slett
|
sign.clear=Slett
|
||||||
sign.add=Legg til
|
sign.add=Legg til
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Lisens
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
###########
|
###########
|
||||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||||
language.direction=ltr
|
language.direction=ltr
|
||||||
addPageNumbers.fontSize=Rozmiar Czcionki
|
addPageNumbers.fontSize=Font Size
|
||||||
addPageNumbers.fontName=Nazwa Czcionki
|
addPageNumbers.fontName=Font Name
|
||||||
pdfPrompt=Wybierz PDF
|
pdfPrompt=Wybierz PDF
|
||||||
multiPdfPrompt=Wybierz PDF (2+)
|
multiPdfPrompt=Wybierz PDF (2+)
|
||||||
multiPdfDropPrompt=Wybierz (lub przeciągnij i puść) wszystkie dokumenty PDF
|
multiPdfDropPrompt=Wybierz (lub przeciągnij i puść) wszystkie dokumenty PDF
|
||||||
@@ -56,12 +56,12 @@ userNotFoundMessage=Brak użytkownika.
|
|||||||
incorrectPasswordMessage=Nieprawidłowe hasło.
|
incorrectPasswordMessage=Nieprawidłowe hasło.
|
||||||
usernameExistsMessage=Taki uzytkownik już istnieje.
|
usernameExistsMessage=Taki uzytkownik już istnieje.
|
||||||
invalidUsernameMessage=Niewłaściwa nazwa użytkownika - musi zawierać litery, cyfry i @._+- LUB być adresem email.
|
invalidUsernameMessage=Niewłaściwa nazwa użytkownika - musi zawierać litery, cyfry i @._+- LUB być adresem email.
|
||||||
invalidPasswordMessage=Hasło nie może być puste i nie może zawierać spacji na początku ani na końcu.
|
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
||||||
confirmPasswordErrorMessage=Wpisz poprawnie hasło w OBA pola.
|
confirmPasswordErrorMessage=Wpisz poprawnie hasło w OBA pola.
|
||||||
deleteCurrentUserMessage=Nie można usunąć zalogowanego użytkownika
|
deleteCurrentUserMessage=Nie można usunąć zalogowanego użytkownika
|
||||||
deleteUsernameExistsMessage=Nie można usunąć zalogowanego użytkownika
|
deleteUsernameExistsMessage=Nie można usunąć zalogowanego użytkownika
|
||||||
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
|
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
|
||||||
disabledCurrentUserMessage=Nie można wyłączyć bieżącego użytkownika
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
|
downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
|
||||||
userAlreadyExistsOAuthMessage=Takie konto użytkownika istnieje - stworzone za pomocą OAuth2.
|
userAlreadyExistsOAuthMessage=Takie konto użytkownika istnieje - stworzone za pomocą OAuth2.
|
||||||
userAlreadyExistsWebMessage=Takie konto użytkownika istnieje - stworzone za pomocą przeglądarki.
|
userAlreadyExistsWebMessage=Takie konto użytkownika istnieje - stworzone za pomocą przeglądarki.
|
||||||
@@ -76,17 +76,14 @@ donate=Podaruj
|
|||||||
color=kolor
|
color=kolor
|
||||||
sponsor=sponsor
|
sponsor=sponsor
|
||||||
info=informacje
|
info=informacje
|
||||||
pro=Pro
|
page=Page
|
||||||
page=Strona
|
pages=Pages
|
||||||
pages=Strony
|
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Polityka Prywatności
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Zasady i Postanowienia
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=Dostępność
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Polityka plików cookie
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=Impresja
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Automatyzacja
|
|||||||
pipelineOptions.saveButton=Pobierz
|
pipelineOptions.saveButton=Pobierz
|
||||||
pipelineOptions.validateButton=Waliduj
|
pipelineOptions.validateButton=Waliduj
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Uaktualnij do wersji Pro
|
|
||||||
enterpriseEdition.warning=Ta funkcja jest dostępna tylko dla użytkowników Pro.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro obsługuje pliki konfiguracyjne YAML i inne funkcje SSO.
|
|
||||||
enterpriseEdition.ssoAdvert=Szukasz więcej funkcji zarządzania użytkownikami? Sprawdź Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Czy chcesz ulepszyć Stirling PDF?
|
|
||||||
analytics.paragraph1=Stirling PDF ma opcję analizy, która pomaga nam udoskonalać produkt. Nie śledzimy żadnych danych osobowych ani zawartości plików.
|
|
||||||
analytics.paragraph2=Rozważ włączenie funkcji analitycznych, które pomogą w rozwoju Stirling-PDF i pozwolą nam lepiej zrozumieć naszych użytkowników.
|
|
||||||
analytics.enable=Włącz analitykę
|
|
||||||
analytics.disable=Wyłącz analitykę
|
|
||||||
analytics.settings=Możesz zmienić ustawienia analityki w pliku config/settings.yml
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -140,14 +121,13 @@ navbar.darkmode=Tryb nocny
|
|||||||
navbar.language=Języki
|
navbar.language=Języki
|
||||||
navbar.settings=Ustawienia
|
navbar.settings=Ustawienia
|
||||||
navbar.allTools=Narzędzia
|
navbar.allTools=Narzędzia
|
||||||
navbar.multiTool=Narzędzie Wielofunkcyjne
|
navbar.multiTool=Multi Tools
|
||||||
navbar.sections.organize=Organizuj
|
navbar.sections.organize=Organizuj
|
||||||
navbar.sections.convertTo=Przetwórz na PDF
|
navbar.sections.convertTo=Przetwórz na PDF
|
||||||
navbar.sections.convertFrom=Przetwórz z PDF
|
navbar.sections.convertFrom=Przetwórz z PDF
|
||||||
navbar.sections.security=Podpis i bezpieczeństwo
|
navbar.sections.security=Podpis i bezpieczeństwo
|
||||||
navbar.sections.advance=Zaawansowane
|
navbar.sections.advance=Zaawansowane
|
||||||
navbar.sections.edit=Podgląd i edycja
|
navbar.sections.edit=Podgląd i edycja
|
||||||
navbar.sections.popular=Popularne
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -220,13 +200,13 @@ adminUserSettings.forceChange=Wymuś zmianę hasło po zalogowaniu
|
|||||||
adminUserSettings.submit=Zapisz użytkownika
|
adminUserSettings.submit=Zapisz użytkownika
|
||||||
adminUserSettings.changeUserRole=Zmień rolę użytkownika
|
adminUserSettings.changeUserRole=Zmień rolę użytkownika
|
||||||
adminUserSettings.authenticated=Zalogowany
|
adminUserSettings.authenticated=Zalogowany
|
||||||
adminUserSettings.editOwnProfil=Edytuj własny profil
|
adminUserSettings.editOwnProfil=Edit own profile
|
||||||
adminUserSettings.enabledUser=włączony użytkownik
|
adminUserSettings.enabledUser=enabled user
|
||||||
adminUserSettings.disabledUser=wyłączony użytkownik
|
adminUserSettings.disabledUser=disabled user
|
||||||
adminUserSettings.activeUsers=Aktywni Użytkownicy:
|
adminUserSettings.activeUsers=Active Users:
|
||||||
adminUserSettings.disabledUsers=Wyłączeni Użytkownicy:
|
adminUserSettings.disabledUsers=Disabled Users:
|
||||||
adminUserSettings.totalUsers=Łączna Liczba Użytkowników:
|
adminUserSettings.totalUsers=Total Users:
|
||||||
adminUserSettings.lastRequest=Ostatnie Zgłoszenie
|
adminUserSettings.lastRequest=Last Request
|
||||||
|
|
||||||
|
|
||||||
database.title=Import/Eksport bazy danych
|
database.title=Import/Eksport bazy danych
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=Plik nie znaleziony
|
|||||||
database.fileNullOrEmpty=Plik nie może być pusty
|
database.fileNullOrEmpty=Plik nie może być pusty
|
||||||
database.failedImportFile=Nie udało się zaimportować pliku
|
database.failedImportFile=Nie udało się zaimportować pliku
|
||||||
|
|
||||||
session.expired=Twoja sesja wygasła. Odśwież stronę i spróbuj ponownie.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -258,207 +236,207 @@ home.viewPdf.title=Podejrzyj PDF
|
|||||||
home.viewPdf.desc=Wyświetl, adnotuj, dodaj tekst lub obrazy
|
home.viewPdf.desc=Wyświetl, adnotuj, dodaj tekst lub obrazy
|
||||||
viewPdf.tags=wyświetl,czytaj,adnotuj,tekst,obraz
|
viewPdf.tags=wyświetl,czytaj,adnotuj,tekst,obraz
|
||||||
|
|
||||||
home.multiTool.title=Wielofunkcyjne Narzędzie PDF
|
home.multiTool.title=Multi narzędzie PDF
|
||||||
home.multiTool.desc=Łącz, dziel, obracaj, zmieniaj kolejność i usuwaj strony
|
home.multiTool.desc=Łącz, dziel, obracaj, zmieniaj kolejność i usuwaj strony
|
||||||
multiTool.tags=Wielofunkcyjne narzędzie, obsługa wielu operacji, interfejs użytkownika, przeciąganie kliknięć, front-end, strona klienta
|
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
|
||||||
|
|
||||||
home.merge.title=Połącz
|
home.merge.title=Połącz
|
||||||
home.merge.desc=Łatwe łączenie wielu dokumentów PDF w jeden.
|
home.merge.desc=Łatwe łączenie wielu dokumentów PDF w jeden.
|
||||||
merge.tags=scalanie, operacje na stronach, back-end, po stronie serwera
|
merge.tags=merge,Page operations,Back end,server side
|
||||||
|
|
||||||
home.split.title=Podziel
|
home.split.title=Podziel
|
||||||
home.split.desc=Podziel dokument PDF na wiele dokumentów
|
home.split.desc=Podziel dokument PDF na wiele dokumentów
|
||||||
split.tags=Operacje na stronach, dzielenie, wiele stron, cięcie, po stronie serwera
|
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||||
|
|
||||||
home.rotate.title=Obróć
|
home.rotate.title=Obróć
|
||||||
home.rotate.desc=Łatwo obracaj dokumenty PDF.
|
home.rotate.desc=Łatwo obracaj dokumenty PDF.
|
||||||
rotate.tags=strona serwera
|
rotate.tags=server side
|
||||||
|
|
||||||
|
|
||||||
home.imageToPdf.title=Obraz na PDF
|
home.imageToPdf.title=Obraz na PDF
|
||||||
home.imageToPdf.desc=Konwertuj obraz (PNG, JPEG, GIF) do dokumentu PDF.
|
home.imageToPdf.desc=Konwertuj obraz (PNG, JPEG, GIF) do dokumentu PDF.
|
||||||
imageToPdf.tags=konwersja,img,jpg,obraz,zdjęcie
|
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||||
|
|
||||||
home.pdfToImage.title=PDF na Obraz
|
home.pdfToImage.title=PDF na Obraz
|
||||||
home.pdfToImage.desc=Konwertuj plik PDF na obraz (PNG, JPEG, GIF).
|
home.pdfToImage.desc=Konwertuj plik PDF na obraz (PNG, JPEG, GIF).
|
||||||
pdfToImage.tags=konwersja,img,jpg,obraz,zdjęcie
|
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||||
|
|
||||||
home.pdfOrganiser.title=Uporządkuj
|
home.pdfOrganiser.title=Uporządkuj
|
||||||
home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności
|
home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności
|
||||||
pdfOrganiser.tags=duplex,parzyste,nieparzyste,sortuj,przenieś
|
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||||
|
|
||||||
|
|
||||||
home.addImage.title=Dodaj obraz
|
home.addImage.title=Dodaj obraz
|
||||||
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF
|
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF
|
||||||
addImage.tags=img,jpg,obraz,zdjęcie
|
addImage.tags=img,jpg,picture,photo
|
||||||
|
|
||||||
home.watermark.title=Dodaj znak wodny
|
home.watermark.title=Dodaj znak wodny
|
||||||
home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF.
|
home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF.
|
||||||
watermark.tags=Tekst,powtarzanie,etykieta,własne,prawa autorskie,znak wodny,img,jpg,obraz,zdjęcie
|
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||||
|
|
||||||
home.permissions.title=Zmień uprawnienia
|
home.permissions.title=Zmień uprawnienia
|
||||||
home.permissions.desc=Zmień uprawnienia dokumentu PDF
|
home.permissions.desc=Zmień uprawnienia dokumentu PDF
|
||||||
permissions.tags=odczyt,zapis,edycja,drukowanie
|
permissions.tags=read,write,edit,print
|
||||||
|
|
||||||
|
|
||||||
home.removePages.title=Usuń
|
home.removePages.title=Usuń
|
||||||
home.removePages.desc=Usuń niechciane strony z dokumentu PDF.
|
home.removePages.desc=Usuń niechciane strony z dokumentu PDF.
|
||||||
removePages.tags=Usuń strony,usuwaj strony
|
removePages.tags=Remove pages,delete pages
|
||||||
|
|
||||||
home.addPassword.title=Dodaj hasło
|
home.addPassword.title=Dodaj hasło
|
||||||
home.addPassword.desc=Zaszyfruj dokument PDF za pomocą hasła.
|
home.addPassword.desc=Zaszyfruj dokument PDF za pomocą hasła.
|
||||||
addPassword.tags=bezpieczeństwo,ochrona
|
addPassword.tags=secure,security
|
||||||
|
|
||||||
home.removePassword.title=Usuń hasło
|
home.removePassword.title=Usuń hasło
|
||||||
home.removePassword.desc=Usuń ochronę hasłem z dokumentu PDF.
|
home.removePassword.desc=Usuń ochronę hasłem z dokumentu PDF.
|
||||||
removePassword.tags=zabezpieczenie,odszyfrowanie,bezpieczeństwo,odhasłowanie,usunięcie hasła
|
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||||
|
|
||||||
home.compressPdfs.title=Kompresuj
|
home.compressPdfs.title=Kompresuj
|
||||||
home.compressPdfs.desc=Kompresuj dokumenty PDF, aby zmniejszyć ich rozmiar.
|
home.compressPdfs.desc=Kompresuj dokumenty PDF, aby zmniejszyć ich rozmiar.
|
||||||
compressPdfs.tags=zgniatać,mały,malutki
|
compressPdfs.tags=squish,small,tiny
|
||||||
|
|
||||||
|
|
||||||
home.changeMetadata.title=Zmień metadane
|
home.changeMetadata.title=Zmień metadane
|
||||||
home.changeMetadata.desc=Zmień/Usuń/Dodaj metadane w dokumencie PDF
|
home.changeMetadata.desc=Zmień/Usuń/Dodaj metadane w dokumencie PDF
|
||||||
changeMetadata.tags=Tytuł,autor,data,utworzenie,czas,wydawca,producent,statystyki
|
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
|
||||||
|
|
||||||
home.fileToPDF.title=Konwertuj plik do PDF
|
home.fileToPDF.title=Konwertuj plik do PDF
|
||||||
home.fileToPDF.desc=Konwertuj dowolny plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
home.fileToPDF.desc=Konwertuj dowolny plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
||||||
fileToPDF.tags=transformacja,format,dokument,obraz,slajd,tekst,konwersja,office,dokumenty,word,excel,powerpoint
|
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||||
|
|
||||||
home.ocr.title=OCR / Zamiana na tekst
|
home.ocr.title=OCR / Zamiana na tekst
|
||||||
home.ocr.desc=OCR skanuje i wykrywa tekst z obrazów w dokumencie PDF i zamienia go na tekst.
|
home.ocr.desc=OCR skanuje i wykrywa tekst z obrazów w dokumencie PDF i zamienia go na tekst.
|
||||||
ocr.tags=rozpoznawanie, tekst, obraz, skanowanie, odczyt, identyfikacja, wykrywanie, edytowalność
|
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||||
|
|
||||||
|
|
||||||
home.extractImages.title=Wyodrębnij obrazy
|
home.extractImages.title=Wyodrębnij obrazy
|
||||||
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
|
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
|
||||||
extractImages.tags=obraz, zdjęcie, zapisz, archiwum, zip, przechwyć, złap
|
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||||
|
|
||||||
home.pdfToPDFA.title=PDF na PDF/A
|
home.pdfToPDFA.title=PDF na PDF/A
|
||||||
home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
|
home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
|
||||||
pdfToPDFA.tags=archiwum, długoterminowe, standardowe, konwersja, przechowywanie, konserwacja
|
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||||
|
|
||||||
home.PDFToWord.title=PDF na Word
|
home.PDFToWord.title=PDF na Word
|
||||||
home.PDFToWord.desc=Konwertuj dokument PDF na formaty Word (DOC, DOCX i ODT)
|
home.PDFToWord.desc=Konwertuj dokument PDF na formaty Word (DOC, DOCX i ODT)
|
||||||
PDFToWord.tags=doc,docx,odt,word, przekształcenie, transformacja, konwersja, office, microsoft, plik doc
|
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||||
|
|
||||||
home.PDFToPresentation.title=PDF na Prezentację
|
home.PDFToPresentation.title=PDF na Prezentację
|
||||||
home.PDFToPresentation.desc=Konwertuj dokument PDF na formaty prezentacji (PPT, PPTX i ODP)
|
home.PDFToPresentation.desc=Konwertuj dokument PDF na formaty prezentacji (PPT, PPTX i ODP)
|
||||||
PDFToPresentation.tags=slajdy, pokaz, office, microsoft
|
PDFToPresentation.tags=slides,show,office,microsoft
|
||||||
|
|
||||||
home.PDFToText.title=PDF na Tekst/RTF
|
home.PDFToText.title=PDF na Tekst/RTF
|
||||||
home.PDFToText.desc=Konwertuj dokument PDF na tekst lub format RTF
|
home.PDFToText.desc=Konwertuj dokument PDF na tekst lub format RTF
|
||||||
PDFToText.tags=format tekstu sformatowanego,rtf format
|
PDFToText.tags=richformat,richtextformat,rich text format
|
||||||
|
|
||||||
home.PDFToHTML.title=PDF na HTML
|
home.PDFToHTML.title=PDF na HTML
|
||||||
home.PDFToHTML.desc=Konwertuj dokument PDF na format HTML
|
home.PDFToHTML.desc=Konwertuj dokument PDF na format HTML
|
||||||
PDFToHTML.tags=zawartość internetowa, przyjazne dla przeglądarek
|
PDFToHTML.tags=web content,browser friendly
|
||||||
|
|
||||||
|
|
||||||
home.PDFToXML.title=PDF na XML
|
home.PDFToXML.title=PDF na XML
|
||||||
home.PDFToXML.desc=Konwertuj dokument PDF na format XML
|
home.PDFToXML.desc=Konwertuj dokument PDF na format XML
|
||||||
PDFToXML.tags=ekstrakcja danych, zawartość strukturalna, współdziałanie, transformacja, konwertowanie
|
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||||
|
|
||||||
home.ScannerImageSplit.title=Wykryj/Podziel zeskanowane zdjęcia
|
home.ScannerImageSplit.title=Wykryj/Podziel zeskanowane zdjęcia
|
||||||
home.ScannerImageSplit.desc=Podziel na wiele zdjęć z jednego zdjęcia/PDF
|
home.ScannerImageSplit.desc=Podziel na wiele zdjęć z jednego zdjęcia/PDF
|
||||||
ScannerImageSplit.tags=oddzielne, automatyczne wykrywanie, skanowanie, wiele zdjęć, porządkowanie
|
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||||
|
|
||||||
home.sign.title=Podpis
|
home.sign.title=Podpis
|
||||||
home.sign.desc=Dodaje podpis do dokumentu PDF za pomocą rysunku, tekstu lub obrazu
|
home.sign.desc=Dodaje podpis do dokumentu PDF za pomocą rysunku, tekstu lub obrazu
|
||||||
sign.tags=autoryzacja, inicjały, podpis odręczny, podpis tekstowy, podpis graficzny
|
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||||
|
|
||||||
home.flatten.title=Spłaszcz
|
home.flatten.title=Spłaszcz
|
||||||
home.flatten.desc=Usuń wszystkie interaktywne elementy i formularze z dokumentu PDF
|
home.flatten.desc=Usuń wszystkie interaktywne elementy i formularze z dokumentu PDF
|
||||||
flatten.tags=statyczny, dezaktywacja, nieinteraktywny, opływowy, streamline
|
flatten.tags=static,deactivate,non-interactive,streamline
|
||||||
|
|
||||||
home.repair.title=Napraw
|
home.repair.title=Napraw
|
||||||
home.repair.desc=Spróbuj naprawić uszkodzony dokument PDF
|
home.repair.desc=Spróbuj naprawić uszkodzony dokument PDF
|
||||||
repair.tags=naprawianie, naprawa, przywracanie, poprawianie, odzyskiwanie
|
repair.tags=fix,restore,correction,recover
|
||||||
|
|
||||||
home.removeBlanks.title=Usuń puste strony
|
home.removeBlanks.title=Usuń puste strony
|
||||||
home.removeBlanks.desc=Wykrywa i usuwa puste strony z dokumentu PDF
|
home.removeBlanks.desc=Wykrywa i usuwa puste strony z dokumentu PDF
|
||||||
removeBlanks.tags=czyszczenie, usprawnianie, brak treści, organizowanie
|
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||||
|
|
||||||
home.removeAnnotations.title=Usuń notatki/przypisy
|
home.removeAnnotations.title=Usuń notatki/przypisy
|
||||||
home.removeAnnotations.desc=Usuwa wszystkie notatki i przypisy z dokumentu PDF
|
home.removeAnnotations.desc=Usuwa wszystkie notatki i przypisy z dokumentu PDF
|
||||||
removeAnnotations.tags=komentarze, podświetlanie, notatki, znaczniki, usuwanie
|
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
||||||
|
|
||||||
home.compare.title=Porównaj
|
home.compare.title=Porównaj
|
||||||
home.compare.desc=Porównuje i pokazuje różnice między dwoma dokumentami PDF
|
home.compare.desc=Porównuje i pokazuje różnice między dwoma dokumentami PDF
|
||||||
compare.tags=rozróżnienie, kontrast, zmiany, analiza
|
compare.tags=differentiate,contrast,changes,analysis
|
||||||
|
|
||||||
home.certSign.title=Podpisz certyfikatem
|
home.certSign.title=Podpisz certyfikatem
|
||||||
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
||||||
certSign.tags=uwierzytelnianie, PEM, P12, oficjalny, szyfrowanie
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
home.removeCertSign.title=Usuń podpis certyfikatem
|
home.removeCertSign.title=Usuń podpis certyfikatem
|
||||||
home.removeCertSign.desc=Usuń podpis certyfikatem z dokumentu PDF
|
home.removeCertSign.desc=Usuń podpis certyfikatem z dokumentu PDF
|
||||||
removeCertSign.tags=uwierzytelnianie, PEM, P12, oficjalny, odszyfrowywanie
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Układ wielu stron
|
home.pageLayout.title=Układ wielu stron
|
||||||
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
||||||
pageLayout.tags=scalanie, kompozycja, pojedynczy widok, organizowanie, porządkowanie
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
|
|
||||||
home.scalePages.title=Dopasuj rozmiar stron
|
home.scalePages.title=Dopasuj rozmiar stron
|
||||||
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
||||||
scalePages.tags=zmiana rozmiaru, modyfikacja, rozmiar, dostosowanie
|
scalePages.tags=resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Automatyzacja
|
home.pipeline.title=Automatyzacja
|
||||||
home.pipeline.desc=Wykonaj wiele akcji na dokumentach PDF, tworząc automatyzację
|
home.pipeline.desc=Wykonaj wiele akcji na dokumentach PDF, tworząc automatyzację
|
||||||
pipeline.tags=automatyzacja, sekwencja, skrypt, przetwarzanie wsadowe
|
pipeline.tags=automate,sequence,scripted,batch-process
|
||||||
|
|
||||||
home.add-page-numbers.title=Dodaj numery stron
|
home.add-page-numbers.title=Dodaj numery stron
|
||||||
home.add-page-numbers.desc=Dodaj numery strony w dokumencie PDF w podanej lokalizacji
|
home.add-page-numbers.desc=Dodaj numery strony w dokumencie PDF w podanej lokalizacji
|
||||||
add-page-numbers.tags=stronicowanie, etykieta, organizowanie, indeks, index
|
add-page-numbers.tags=paginate,label,organize,index
|
||||||
|
|
||||||
home.auto-rename.title=Automatycznie zmień nazwę PDF
|
home.auto-rename.title=Automatycznie zmień nazwę PDF
|
||||||
home.auto-rename.desc=Automatycznie zmień nazwę PDF bazując na nagłówku
|
home.auto-rename.desc=Automatycznie zmień nazwę PDF bazując na nagłówku
|
||||||
auto-rename.tags=automatyczne wykrywanie, oparte na nagłówkach, organizowanie, ponowne etykietowanie
|
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||||
|
|
||||||
home.adjust-contrast.title=Zmień kolor/nasycenie/jasność
|
home.adjust-contrast.title=Zmień kolor/nasycenie/jasność
|
||||||
home.adjust-contrast.desc=Zmień kolor/nasycenie/jasność w dokumencie PDF
|
home.adjust-contrast.desc=Zmień kolor/nasycenie/jasność w dokumencie PDF
|
||||||
adjust-contrast.tags=Korekcja kolorów, dostrajanie, modyfikacja, ulepszanie
|
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||||
|
|
||||||
home.crop.title=Przytnij PDF
|
home.crop.title=Przytnij PDF
|
||||||
home.crop.desc=Przytnij dokument PDF w celu zmniejszenia rozmiaru
|
home.crop.desc=Przytnij dokument PDF w celu zmniejszenia rozmiaru
|
||||||
crop.tags=przycinanie, zmniejszanie, edycja, kształtowanie
|
crop.tags=trim,shrink,edit,shape
|
||||||
|
|
||||||
home.autoSplitPDF.title=Automatycznie podziel strony
|
home.autoSplitPDF.title=Automatycznie podziel strony
|
||||||
home.autoSplitPDF.desc=Automatycznie podziel dokument na strony
|
home.autoSplitPDF.desc=Automatycznie podziel dokument na strony
|
||||||
autoSplitPDF.tags=Oparty na QR, rozdzielanie, skanowanie, organizowanie
|
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||||
|
|
||||||
home.sanitizePdf.title=Dezynfekcja
|
home.sanitizePdf.title=Dezynfekcja
|
||||||
home.sanitizePdf.desc=Usuń skrypt i inne elementy z dokumentu PDF
|
home.sanitizePdf.desc=Usuń skrypt i inne elementy z dokumentu PDF
|
||||||
sanitizePdf.tags=czyszczenie, ochrona, bezpieczeństwo, usuwanie zagrożeń
|
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||||
|
|
||||||
home.URLToPDF.title=Strona WWW do PDFa
|
home.URLToPDF.title=Strona WWW do PDFa
|
||||||
home.URLToPDF.desc=Zapisuje podany adres WWW do PDFa
|
home.URLToPDF.desc=Zapisuje podany adres WWW do PDFa
|
||||||
URLToPDF.tags=przechwytywanie stron internetowych, zapisywanie strony, strona internetowa do dokumentu, archiwizacja
|
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||||
|
|
||||||
home.HTMLToPDF.title=HTML do PDF
|
home.HTMLToPDF.title=HTML do PDF
|
||||||
home.HTMLToPDF.desc=Zapisuje podany plik HTML/ZIP do PDF
|
home.HTMLToPDF.desc=Zapisuje podany plik HTML/ZIP do PDF
|
||||||
HTMLToPDF.tags=znaczniki, treść internetowa, transformacja, konwertowanie
|
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||||
|
|
||||||
|
|
||||||
home.MarkdownToPDF.title=Markdown do PDF
|
home.MarkdownToPDF.title=Markdown do PDF
|
||||||
home.MarkdownToPDF.desc=Zapisuje dokument Markdown do PDF
|
home.MarkdownToPDF.desc=Zapisuje dokument Markdown do PDF
|
||||||
MarkdownToPDF.tags=znaczniki, treść internetowa, transformacja, konwertowanie
|
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||||
|
|
||||||
|
|
||||||
home.getPdfInfo.title=Pobierz informacje o pliku PDF
|
home.getPdfInfo.title=Pobierz informacje o pliku PDF
|
||||||
home.getPdfInfo.desc=Pobiera wszelkie informacje o pliku PDF
|
home.getPdfInfo.desc=Pobiera wszelkie informacje o pliku PDF
|
||||||
getPdfInfo.tags=informacje, dane, statystyka, statystyki
|
getPdfInfo.tags=infomation,data,stats,statistics
|
||||||
|
|
||||||
|
|
||||||
home.extractPage.title=Wyciągnij stronę z PDF
|
home.extractPage.title=Wyciągnij stronę z PDF
|
||||||
home.extractPage.desc=Wyciąga stronę z dokumentu PDF
|
home.extractPage.desc=Wyciąga stronę z dokumentu PDF
|
||||||
extractPage.tags=wydobycie,separacja,wyciaganie
|
extractPage.tags=extract
|
||||||
|
|
||||||
|
|
||||||
home.PdfToSinglePage.title=PDF do jednej strony
|
home.PdfToSinglePage.title=PDF do jednej strony
|
||||||
home.PdfToSinglePage.desc=Łączy wszystkie strony PDFa w jedną wielką stronę PDF
|
home.PdfToSinglePage.desc=Łączy wszystkie strony PDFa w jedną wielką stronę PDF
|
||||||
PdfToSinglePage.tags=pojedyncza strona
|
PdfToSinglePage.tags=single page
|
||||||
|
|
||||||
|
|
||||||
home.showJS.title=Pokaż kod JavaScript
|
home.showJS.title=Pokaż kod JavaScript
|
||||||
@@ -467,66 +445,61 @@ showJS.tags=JS
|
|||||||
|
|
||||||
home.autoRedact.title=Zaciemnij
|
home.autoRedact.title=Zaciemnij
|
||||||
home.autoRedact.desc=Zaciemnia dokument PDF bazując na podanej wartości
|
home.autoRedact.desc=Zaciemnia dokument PDF bazując na podanej wartości
|
||||||
autoRedact.tags=Redagowanie, ukrywanie, zaciemnianie, zaczernianie, zaznaczanie, ukrywanie
|
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF do CSV
|
home.tableExtraxt.title=PDF do CSV
|
||||||
home.tableExtraxt.desc=Konwertuje tabele z PDF do pliku CSV
|
home.tableExtraxt.desc=Konwertuje tabele z PDF do pliku CSV
|
||||||
tableExtraxt.tags=CSV, ekstrakcja tabeli, ekstrakcja, konwersja, wydobywanie
|
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||||
|
|
||||||
|
|
||||||
home.autoSizeSplitPDF.title=Podziel (Rozmiar/Ilość stron)
|
home.autoSizeSplitPDF.title=Podziel (Rozmiar/Ilość stron)
|
||||||
home.autoSizeSplitPDF.desc=Rozdziela dokument PDF na wiele dokumentów bazując na podanym rozmiarze, ilości stron bądź ilości dokumentów
|
home.autoSizeSplitPDF.desc=Rozdziela dokument PDF na wiele dokumentów bazując na podanym rozmiarze, ilości stron bądź ilości dokumentów
|
||||||
autoSizeSplitPDF.tags=pdf, dzielenie, dokument, organizacja
|
autoSizeSplitPDF.tags=pdf,split,document,organization
|
||||||
|
|
||||||
|
|
||||||
home.overlay-pdfs.title=Nałóż PDFa
|
home.overlay-pdfs.title=Nałóż PDFa
|
||||||
home.overlay-pdfs.desc=Nakłada dokumenty PDF na siebie
|
home.overlay-pdfs.desc=Nakłada dokumenty PDF na siebie
|
||||||
overlay-pdfs.tags=Nakładka
|
overlay-pdfs.tags=Overlay
|
||||||
|
|
||||||
home.split-by-sections.title=Podziel PDF na sekcje
|
home.split-by-sections.title=Podziel PDF na sekcje
|
||||||
home.split-by-sections.desc=Podziel strony PDF w mniejsze sekcje
|
home.split-by-sections.desc=Podziel strony PDF w mniejsze sekcje
|
||||||
split-by-sections.tags=Podział sekcji, dzielenie, dostosowywanie
|
split-by-sections.tags=Section Split, Divide, Customize
|
||||||
|
|
||||||
home.AddStampRequest.title=Dodaj pieczęć
|
home.AddStampRequest.title=Dodaj pieczęć
|
||||||
home.AddStampRequest.desc=Dodaj pieczęć tekstową/obrazową w wyznaczonej lokalizacji dokumentu
|
home.AddStampRequest.desc=Dodaj pieczęć tekstową/obrazową w wyznaczonej lokalizacji dokumentu
|
||||||
AddStampRequest.tags=Stempel, dodawanie obrazu, wyśrodkowanie obrazu, znak wodny, PDF, osadzanie, dostosowywanie
|
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF do eBooka
|
home.PDFToBook.title=PDF do eBooka
|
||||||
home.PDFToBook.desc=Zapisuje dokument PDF w formacie eBooka za pomocą Calibre
|
home.PDFToBook.desc=Zapisuje dokument PDF w formacie eBooka za pomocą Calibre
|
||||||
PDFToBook.tags=Książka,komiks,Calibre, konwertowanie, manga, amazon, kindle
|
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.BookToPDF.title=eBook do PDF
|
home.BookToPDF.title=eBook do PDF
|
||||||
home.BookToPDF.desc=Zapisuje ebooka do PDF za pomocą Calibre
|
home.BookToPDF.desc=Zapisuje ebooka do PDF za pomocą Calibre
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||||
|
|
||||||
home.removeImagePdf.title=Usuń obraz
|
home.removeImagePdf.title=Remove image
|
||||||
home.removeImagePdf.desc=Usuń obraz z pliku PDF, aby zmniejszyć rozmiar pliku
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Usuń obraz, operacje na stronie, back-end, strona serwera
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Podziel PDF według rozdziałów
|
|
||||||
home.splitPdfByChapters.desc=Podział pliku PDF na wiele plików na podstawie struktury rozdziałów.
|
|
||||||
splitPdfByChapters.tags=podział, rozdziały, zakładki, porządkowanie, organizacja
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Zamień-Odwróć-Kolor
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Zamień-Odwróć kolor PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Zastąp i Odwróć Kolor
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Zastąp kolor tekstu i tła w pliku PDF i odwróć pełen kolor pliku PDF, aby zmniejszyć rozmiar pliku
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Zastąp kolor, operacje na stronach, back-end, strona serwera
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Zastąp lub Odwróć opcje kolorów
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Domyślnie (domyślne kolory o wysokim kontraście)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Niestandardowe (kolory niestandardowe)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Całkowita-Odwrotność (Odwrócenie wszystkich kolorów)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Wysoki kontrast opcji kolorystycznych
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=biały tekst na czarnym tle
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Czarny tekst na białym tle
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Żółty tekst na czarnym tle
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Zielony tekst na czarnym tle
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Wybierz Kolor tekstu
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Wybierz Kolor tła
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Zamień
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -545,17 +518,15 @@ login.locked=Konto jest zablokowane
|
|||||||
login.signinTitle=Zaloguj się
|
login.signinTitle=Zaloguj się
|
||||||
login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
|
login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
|
||||||
login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
|
login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
|
||||||
login.oauth2AdminBlockedUser=Rejestracja lub logowanie niezarejestrowanych użytkowników jest obecnie zablokowane. Prosimy o kontakt z administratorem.
|
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
||||||
login.oauth2RequestNotFound=Błąd logowania OAuth2
|
login.oauth2RequestNotFound=Błąd logowania OAuth2
|
||||||
login.oauth2InvalidUserInfoResponse=Niewłaściwe dane logowania
|
login.oauth2InvalidUserInfoResponse=Niewłaściwe dane logowania
|
||||||
login.oauth2invalidRequest=Nieprawidłowe żądanie
|
login.oauth2invalidRequest=Nieprawidłowe żądanie
|
||||||
login.oauth2AccessDenied=Brak dostępu
|
login.oauth2AccessDenied=Brak dostępu
|
||||||
login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token
|
login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token
|
||||||
login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu
|
login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu
|
||||||
login.userIsDisabled=Użytkownik jest nieaktywny, logowanie przy użyciu tej nazwy użytkownika jest obecnie zablokowane. Prosimy o kontakt z administratorem.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=Jesteś już zalogowany na
|
|
||||||
login.alreadyLoggedIn2=urządzeniach. Wyloguj się z tych urządzeń i spróbuj ponownie.
|
|
||||||
login.toManySessions=Masz zbyt wiele aktywnych sesji
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatyczne zaciemnienie
|
autoRedact.title=Automatyczne zaciemnienie
|
||||||
@@ -779,14 +750,11 @@ removeAnnotations.submit=Usuń
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Porównaj
|
compare.title=Porównaj
|
||||||
compare.header=Porównaj PDF(y)
|
compare.header=Porównaj PDF(y)
|
||||||
compare.highlightColor.1=Kolor Podświetlenia 1:
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
compare.highlightColor.2=Kolor Podświetlenia 2:
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porównaj
|
compare.submit=Porównaj
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=eBooki do PDF
|
BookToPDF.title=eBooki do PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Narysuj podpis
|
|||||||
sign.text=Wprowadź tekst
|
sign.text=Wprowadź tekst
|
||||||
sign.clear=Wyczyść
|
sign.clear=Wyczyść
|
||||||
sign.add=Dodaj
|
sign.add=Dodaj
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -840,7 +803,7 @@ ScannerImageSplit.selectText.7=Minimalny obszar konturu:
|
|||||||
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
|
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
|
||||||
ScannerImageSplit.selectText.9=Rozmiar obramowania:
|
ScannerImageSplit.selectText.9=Rozmiar obramowania:
|
||||||
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
|
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
|
||||||
ScannerImageSplit.info=Python nie został zainstalowany. Jest on wymagany do uruchomienia.
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -867,7 +830,7 @@ ocr.submit=Przetwarzaj PDF za pomocą OCR
|
|||||||
extractImages.title=Wyodrębnij obrazy
|
extractImages.title=Wyodrębnij obrazy
|
||||||
extractImages.header=Wyodrębnij obrazy
|
extractImages.header=Wyodrębnij obrazy
|
||||||
extractImages.selectText=Wybierz format obrazu, na który chcesz przekonwertować wyodrębniony obraz.
|
extractImages.selectText=Wybierz format obrazu, na który chcesz przekonwertować wyodrębniony obraz.
|
||||||
extractImages.allowDuplicates=Zapisz zduplikowane obrazy
|
extractImages.allowDuplicates=Save duplicate images
|
||||||
extractImages.submit=Wyodrębnij
|
extractImages.submit=Wyodrębnij
|
||||||
|
|
||||||
|
|
||||||
@@ -928,8 +891,8 @@ pdfOrganiser.placeholder=(przykład 1,3,2 lub 4-8,2,10-12 lub 2n-1)
|
|||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=Narzędzie Wielofunkcyjne PDF
|
multiTool.title=Multi narzędzie PDF
|
||||||
multiTool.header=Narzędzie Wielofunkcyjne PDF
|
multiTool.header=Multi narzędzie PDF
|
||||||
multiTool.uploadPrompts=Nazwa pliku
|
multiTool.uploadPrompts=Nazwa pliku
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
@@ -992,7 +955,7 @@ pdfToImage.color=Kolor
|
|||||||
pdfToImage.grey=Odcień szarości
|
pdfToImage.grey=Odcień szarości
|
||||||
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
|
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
|
||||||
pdfToImage.submit=Konwertuj
|
pdfToImage.submit=Konwertuj
|
||||||
pdfToImage.info=Python nie został zainstalowany. Jest wymagany do konwersji WebP.
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1029,7 +992,7 @@ watermark.selectText.6=Odstęp w pionie (odstęp między każdym znakiem wodnym
|
|||||||
watermark.selectText.7=Nieprzezroczystość (0% - 100%):
|
watermark.selectText.7=Nieprzezroczystość (0% - 100%):
|
||||||
watermark.selectText.8=Typ znaku wodnego:
|
watermark.selectText.8=Typ znaku wodnego:
|
||||||
watermark.selectText.9=Obraz znaku wodnego:
|
watermark.selectText.9=Obraz znaku wodnego:
|
||||||
watermark.selectText.10=Konwertuj PDF do PDF-Image
|
watermark.selectText.10=Convert PDF to PDF-Image
|
||||||
watermark.submit=Dodaj znak wodny
|
watermark.submit=Dodaj znak wodny
|
||||||
watermark.type.1=Tekst
|
watermark.type.1=Tekst
|
||||||
watermark.type.2=Obraz
|
watermark.type.2=Obraz
|
||||||
@@ -1129,7 +1092,7 @@ PDFToXML.submit=Konwertuj
|
|||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF na CSV
|
PDFToCSV.title=PDF na CSV
|
||||||
PDFToCSV.header=PDF na CSV
|
PDFToCSV.header=PDF na CSV
|
||||||
PDFToCSV.prompt=Wybierz stronę do wyodrębnienia tabeli
|
PDFToCSV.prompt=Choose page to extract table
|
||||||
PDFToCSV.submit=Zatwierdź
|
PDFToCSV.submit=Zatwierdź
|
||||||
|
|
||||||
#split-by-size-or-count
|
#split-by-size-or-count
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licencja
|
|||||||
survey.nav=Ankieta
|
survey.nav=Ankieta
|
||||||
survey.title=Ankieta Stirling-PDF
|
survey.title=Ankieta Stirling-PDF
|
||||||
survey.description=Stirling-PDF nie śledzi swoich użytkowników, więc chciałby poznać opinie swoich użytkowników!
|
survey.description=Stirling-PDF nie śledzi swoich użytkowników, więc chciałby poznać opinie swoich użytkowników!
|
||||||
survey.changes=Stirling-PDF zmieniło się od czasu ostatniej ankiety! Aby dowiedzieć się więcej, sprawdź nasz wpis na blogu tutaj:
|
|
||||||
survey.changes2=Dzięki tym zmianom otrzymujemy płatne wsparcie biznesowe i finansowanie
|
|
||||||
survey.please=Wypełnij proszę ankietę dla nas!
|
survey.please=Wypełnij proszę ankietę dla nas!
|
||||||
survey.disabled=(Blokada wyskakującego okienka z ankieta zostanie dodane w następnych aktualizacjach, ale będzie dostępna na dole strony)
|
survey.disabled=(Blokada wyskakującego okienka z ankieta zostanie dodane w następnych aktualizacjach, ale będzie dostępna na dole strony)
|
||||||
survey.button=Wypełnij ankietę
|
survey.button=Wypełnij ankietę
|
||||||
@@ -1214,19 +1175,7 @@ error.discordSubmit=Discord - wyślij posta z prośbą o pomoc
|
|||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Usuń obraz
|
removeImage.title=Remove image
|
||||||
removeImage.header=Usuń obraz
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Usuń obraz
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Usuń obraz
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Podziel PDF według Rozdziałów
|
|
||||||
splitByChapters.header=Podziel PDF według Rozdziałów
|
|
||||||
splitByChapters.bookmarkLevel=Poziom Zakładek
|
|
||||||
splitByChapters.includeMetadata=Dołącz Metadane
|
|
||||||
splitByChapters.allowDuplicates=Zezwalaj na Duplikaty
|
|
||||||
splitByChapters.desc.1=Narzędzie to dzieli plik PDF na wiele plików PDF w oparciu o strukturę rozdziałów.
|
|
||||||
splitByChapters.desc.2=Poziom Zakładek: Wybierz poziom zakładek, który ma zostać użyty do podziału (0 dla najwyższego poziomu, 1 dla drugiego poziomu itd.).
|
|
||||||
splitByChapters.desc.3=Dołącz Metadane: Jeśli opcja ta jest zaznaczona, metadane oryginalnego pliku PDF zostaną uwzględnione w każdym rozdzielonych plików PDF.
|
|
||||||
splitByChapters.desc.4=Zezwól na Duplikaty: Jeśli ta opcja jest zaznaczona, pozwala na tworzenie oddzielnych plików PDF przez wiele zakładek na tej samej stronie.
|
|
||||||
splitByChapters.submit=Podziel PDF
|
|
||||||
|
|||||||
@@ -3,42 +3,42 @@
|
|||||||
###########
|
###########
|
||||||
# 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=Tamanho da Fonte
|
addPageNumbers.fontSize=Tamanho da fonte
|
||||||
addPageNumbers.fontName=Nome da Fonte
|
addPageNumbers.fontName=Nome da fonte
|
||||||
pdfPrompt=Selecione PDF(s)
|
pdfPrompt=Selecione PDF(s)
|
||||||
multiPdfPrompt=Selecione PDFs (2+)
|
multiPdfPrompt=Selecione PDFs (2+)
|
||||||
multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs desejados
|
multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs necessários
|
||||||
imgPrompt=Selecione a(s) Imagem(ns)
|
imgPrompt=Selecione a(s) imagem(ns)
|
||||||
genericSubmit=Enviar
|
genericSubmit=Enviar
|
||||||
processTimeWarning=Aviso: esse processo pode levar até um minuto, dependendo do tamanho do arquivo
|
processTimeWarning=Aviso: esse processo pode levar até um minuto, dependendo do tamanho do arquivo
|
||||||
pageOrderPrompt=Ordem de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula ou Funções como 2n+1):
|
pageOrderPrompt=Ordem de página personalizada (digite uma lista de números de página separada por vírgula):
|
||||||
pageSelectionPrompt=Seleção de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula 1,5,6 ou Funções como 2n+1) :
|
pageSelectionPrompt=Seleção de página personalizada (digite uma lista de números de página separada por vírgula 1,5,6 ou Funções como 2n+1) :
|
||||||
goToPage=Ir
|
goToPage=Ir
|
||||||
true=Verdadeiro
|
true=Verdadeiro
|
||||||
false=Falso
|
false=Falso
|
||||||
unknown=Desconhecido
|
unknown=Desconhecido
|
||||||
save=Salvar
|
save=Salvar
|
||||||
saveToBrowser=Salvar no Navegador
|
saveToBrowser=Salvar no navegador
|
||||||
close=Fechar
|
close=Fechar
|
||||||
filesSelected=Arquivos Selecionados
|
filesSelected=arquivos selecionados
|
||||||
noFavourites=Nenhum Favorito Adicionado
|
noFavourites=Nenhum favorito adicionado
|
||||||
downloadComplete=Download Completo
|
downloadComplete=Download Completo
|
||||||
bored=Entediado Esperando?
|
bored=Entediado esperando?
|
||||||
alphabet=Alfabeto
|
alphabet=Alfabeto
|
||||||
downloadPdf=Baixar PDF
|
downloadPdf=Baixar PDF
|
||||||
text=Texto
|
text=Texto
|
||||||
font=Fonte
|
font=Fonte
|
||||||
selectFillter=-- Selecione --
|
selectFillter=-- Selecione --
|
||||||
pageNum=Número da Página
|
pageNum=Número da página
|
||||||
sizes.small=Pequeno
|
sizes.small=Pequeno
|
||||||
sizes.medium=Médio
|
sizes.medium=Médio
|
||||||
sizes.large=Grande
|
sizes.large=Grande
|
||||||
sizes.x-large=Extra grande
|
sizes.x-large=Extra grande
|
||||||
error.pdfPassword=O documento PDF está protegido por senha e a senha não foi fornecida ou está incorreta
|
error.pdfPassword=O documento PDF está protegido por senha e a senha não foi fornecida ou está incorreta
|
||||||
delete=Apagar
|
delete=apagar
|
||||||
username=Usuário
|
username=Usuário
|
||||||
password=Senha
|
password=Senha
|
||||||
welcome=Bem-vindo
|
welcome=Bem vindo
|
||||||
property=Propriedade
|
property=Propriedade
|
||||||
black=Preto
|
black=Preto
|
||||||
white=Branco
|
white=Branco
|
||||||
@@ -46,7 +46,7 @@ red=Vermelho
|
|||||||
green=Verde
|
green=Verde
|
||||||
blue=Azul
|
blue=Azul
|
||||||
custom=Personalizado...
|
custom=Personalizado...
|
||||||
WorkInProgess=Trabalho em progresso, Talvez não funcione ou apresente erros, Por favor, reporte qualquer problema!
|
WorkInProgess=Em progesso, Talvez não funcione ou apresente erros, Por favor, reporte qualquer problema!
|
||||||
poweredBy=Distribuído por
|
poweredBy=Distribuído por
|
||||||
yes=Sim
|
yes=Sim
|
||||||
no=Não
|
no=Não
|
||||||
@@ -55,32 +55,29 @@ notAuthenticatedMessage=Usuário não autenticado.
|
|||||||
userNotFoundMessage=Usuário não encontrado.
|
userNotFoundMessage=Usuário não encontrado.
|
||||||
incorrectPasswordMessage=A senha atual está incorreta.
|
incorrectPasswordMessage=A senha atual está incorreta.
|
||||||
usernameExistsMessage=Novo Usuário já existe.
|
usernameExistsMessage=Novo Usuário já existe.
|
||||||
invalidUsernameMessage=Usuário inválido, nome de usuário só pode incluir letras, números e os seguintes caracteres especiais @._+- ou deve ser um e-mail válido.
|
invalidUsernameMessage=Usuário inválido, nome de usuário só pode incluir letras, números e os seguintes caracteres especiais @._+- ou deve ser um email válido.
|
||||||
invalidPasswordMessage=A senha não deve estar vazia e não deve conter espaços no início ou no final.
|
invalidPasswordMessage=A senha não deve estar vazia e não deve conter espaços no início ou no final.
|
||||||
confirmPasswordErrorMessage=Nova Senha e Confirmar Nova Senha devem ser iguais.
|
confirmPasswordErrorMessage=Nova Senha e Confirmar Nova Senha devem ser iguais.
|
||||||
deleteCurrentUserMessage=Não é possível apagar usuário conectado no momento.
|
deleteCurrentUserMessage=Não é possível apagar o usuário da sessão atual.
|
||||||
deleteUsernameExistsMessage=O usuário não existe e não pode ser apagado.
|
deleteUsernameExistsMessage=O usuário não existe e não pode ser apagado.
|
||||||
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário conectado no momento.
|
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual
|
||||||
disabledCurrentUserMessage=O usuário atual não pode ser desativado.
|
disabledCurrentUserMessage=O usuário atual não pode ser desativado
|
||||||
downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do usuário atual. Portanto, o usuário atual não será mostrado.
|
downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do usuário atual. Portanto, o usuário atual não será mostrado.
|
||||||
userAlreadyExistsOAuthMessage=O usuário já existe como um usuário OAuth2.
|
userAlreadyExistsOAuthMessage=O usuário já existe como um usuário OAuth2.
|
||||||
userAlreadyExistsWebMessage=O usuário já existe como um usuário Web.
|
userAlreadyExistsWebMessage=O usuário já existe como um usuário web.
|
||||||
error=Erro
|
error=Erro
|
||||||
oops=Ops!
|
oops=Ops!
|
||||||
help=Ajuda
|
help=Ajuda
|
||||||
goHomepage=Ir para a Página Inicial
|
goHomepage=Ir para a Página Inicial
|
||||||
joinDiscord=Junte-se ao nosso servidor Discord
|
joinDiscord=Junte-se ao nosso servidor Discord
|
||||||
seeDockerHub=Visite o Docker Hub
|
seeDockerHub=Visite o Docker Hub
|
||||||
visitGithub=Visite o repositório no GitHub
|
visitGithub=Visite o repositŕio no GitHub
|
||||||
donate=Doar
|
donate=Doar
|
||||||
color=Cor
|
color=Cor
|
||||||
sponsor=Patrocinador
|
sponsor=Patrocine
|
||||||
info=Informações
|
info=Informações
|
||||||
pro=Pro
|
page=Page
|
||||||
page=Página
|
pages=Pages
|
||||||
pages=Páginas
|
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Política de Privacidade
|
legal.privacy=Política de Privacidade
|
||||||
legal.terms=Termos e Condições
|
legal.terms=Termos e Condições
|
||||||
@@ -92,7 +89,7 @@ legal.impressum=Informações legais
|
|||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=Menu do Pipeline (Beta)
|
pipeline.header=Menu do Pipeline (Beta)
|
||||||
pipeline.uploadButton=Upload Personalizado
|
pipeline.uploadButton=Upload personalizado
|
||||||
pipeline.configureButton=Configurar
|
pipeline.configureButton=Configurar
|
||||||
pipeline.defaultOption=Personalizado
|
pipeline.defaultOption=Personalizado
|
||||||
pipeline.submitButton=Enviar
|
pipeline.submitButton=Enviar
|
||||||
@@ -105,32 +102,16 @@ pipeline.deletePrompt=Tem certeza de que deseja excluir o pipeline
|
|||||||
######################
|
######################
|
||||||
pipelineOptions.header=Configuração do Pipeline
|
pipelineOptions.header=Configuração do Pipeline
|
||||||
pipelineOptions.pipelineNameLabel=Nome do Pipeline
|
pipelineOptions.pipelineNameLabel=Nome do Pipeline
|
||||||
pipelineOptions.saveSettings=Salvar Configurações da Operação
|
pipelineOptions.saveSettings=Salvar configurações da operação
|
||||||
pipelineOptions.pipelineNamePrompt=Insira o nome do pipeline aqui
|
pipelineOptions.pipelineNamePrompt=Insira o nome do pipeline aqui
|
||||||
pipelineOptions.selectOperation=Selecione uma Operação
|
pipelineOptions.selectOperation=Selecione uma operação
|
||||||
pipelineOptions.addOperationButton=Adicione uma Operação
|
pipelineOptions.addOperationButton=Adicione uma operação
|
||||||
pipelineOptions.pipelineHeader=Pipeline:
|
pipelineOptions.pipelineHeader=Pipeline:
|
||||||
pipelineOptions.saveButton=Baixar
|
pipelineOptions.saveButton=Baixar
|
||||||
pipelineOptions.validateButton=Validar
|
pipelineOptions.validateButton=Validar
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Atualize para versão Pro
|
|
||||||
enterpriseEdition.warning=Esse recurso só está disponivel para usuários da versão Pro.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro suporta arquivos de configuração YAML e outros recursos SSO.
|
|
||||||
enterpriseEdition.ssoAdvert=Procurando por mais recursos de controle de usuários? Veja Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Você quer melhorar Stirling PDF?
|
|
||||||
analytics.paragraph1=Stirling PDF possui coleta de dados opcional para ajudar a melhorar o produto. Nós não rastreamos nenhuma informação pessoal ou conteúdo dos arquivos.
|
|
||||||
analytics.paragraph2=Por favor considere habilitar coleta de dados para ajudar Stirling-PDF a crescer e nos ajudar a entender nossos usuários melhor.
|
|
||||||
analytics.enable=Habilitar coleta de dados
|
|
||||||
analytics.disable=Desabilitar coleta de dados
|
|
||||||
analytics.settings=Você pode alterar as configurações de coleta de dados no arquivo config/settings.yml
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Converter de PDF
|
|||||||
navbar.sections.security=Assinatura & Segurança
|
navbar.sections.security=Assinatura & Segurança
|
||||||
navbar.sections.advance=Avançado
|
navbar.sections.advance=Avançado
|
||||||
navbar.sections.edit=Visualizar & editar
|
navbar.sections.edit=Visualizar & editar
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -164,61 +144,61 @@ settings.zipThreshold=Compactar arquivos quando o número de arquivos baixados e
|
|||||||
settings.signOut=Sair
|
settings.signOut=Sair
|
||||||
settings.accountSettings=Configurações de conta
|
settings.accountSettings=Configurações de conta
|
||||||
settings.bored.help=Habilitar jogos secretos
|
settings.bored.help=Habilitar jogos secretos
|
||||||
settings.cacheInputs.name=Salvar entradas do formulário
|
settings.cacheInputs.name=Salvar entradas de formulário
|
||||||
settings.cacheInputs.help=Habilitar para armazenar entradas usadas anteriormente para execuções futuras
|
settings.cacheInputs.help=Habilitar para armazenar entradas usadas anteriormente para execuções futuras
|
||||||
|
|
||||||
changeCreds.title=Alterar Credenciais
|
changeCreds.title=Alterar credenciais
|
||||||
changeCreds.header=Atualizar Detalhes da Conta
|
changeCreds.header=Atualizar detalhes da sua conta
|
||||||
changeCreds.changePassword=Você está usando as credenciais padrões. Por favor, insira uma nova senha
|
changeCreds.changePassword=Você está usando as credenciais padrões. Por favor, insira uma nova senha
|
||||||
changeCreds.newUsername=Novo Usuário
|
changeCreds.newUsername=Novo usuário
|
||||||
changeCreds.oldPassword=Senha Atual
|
changeCreds.oldPassword=Senha atual
|
||||||
changeCreds.newPassword=Senha Nova
|
changeCreds.newPassword=Nova senha
|
||||||
changeCreds.confirmNewPassword=Confirme a Nova Senha
|
changeCreds.confirmNewPassword=Confirmar nova senha
|
||||||
changeCreds.submit=Enviar Alterações
|
changeCreds.submit=Enviar alterações
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
account.title=Configurações de Conta
|
account.title=Configurações de conta
|
||||||
account.accountSettings=Configurações de Conta
|
account.accountSettings=Configurações de conta
|
||||||
account.adminSettings=Configurações de Administrador – Visualizar e Adicionar Usuários
|
account.adminSettings=Configurações de Administrador – visualizar e adicionar usuários
|
||||||
account.userControlSettings=Configurações de Controle de Usuário
|
account.userControlSettings=Configurações de controle de usuário
|
||||||
account.changeUsername=Alterar Usuário
|
account.changeUsername=Alterar usuário
|
||||||
account.newUsername=Novo Usuário
|
account.newUsername=Novo usuário
|
||||||
account.password=Senha de Confirmação
|
account.password=Senha de confirmação
|
||||||
account.oldPassword=Senha Antiga
|
account.oldPassword=Senha antiga
|
||||||
account.newPassword=Senha Nova
|
account.newPassword=Senha nova
|
||||||
account.changePassword=Alterar a Senha
|
account.changePassword=Alterar a senha
|
||||||
account.confirmNewPassword=Confirme a Nova Senha
|
account.confirmNewPassword=Confirme a nova senha
|
||||||
account.signOut=Sair
|
account.signOut=Sair
|
||||||
account.yourApiKey=Sua chave de API
|
account.yourApiKey=Sua chave de API
|
||||||
account.syncTitle=Sincronize as configurações do navegador com a conta
|
account.syncTitle=Sincronize as configurações do navegador com a conta
|
||||||
account.settingsCompare=Comparação de Configurações:
|
account.settingsCompare=Comparação de configurações:
|
||||||
account.property=Propriedade
|
account.property=Propriedade
|
||||||
account.webBrowserSettings=Configuração do navegador Web
|
account.webBrowserSettings=Configuração do navegador Web
|
||||||
account.syncToBrowser=Sincronizar Conta -> Navegador
|
account.syncToBrowser=Sincronizar conta -> Navegador
|
||||||
account.syncToAccount=Sincronizar Conta <- Navegador
|
account.syncToAccount=Sincronizar conta <- navegador
|
||||||
|
|
||||||
|
|
||||||
adminUserSettings.title=Configurações de controle de usuário
|
adminUserSettings.title=Configurações de controle de usuário
|
||||||
adminUserSettings.header=Configurações de controle do usuário administrador
|
adminUserSettings.header=Configurações de controle de usuário administrador
|
||||||
adminUserSettings.admin=Administrador
|
adminUserSettings.admin=Administrador
|
||||||
adminUserSettings.user=Usuário
|
adminUserSettings.user=Usuário
|
||||||
adminUserSettings.addUser=Adicionar novo usuário
|
adminUserSettings.addUser=Adicionar novo usuário
|
||||||
adminUserSettings.deleteUser=Apagar usuário
|
adminUserSettings.deleteUser=Apagar usuário
|
||||||
adminUserSettings.confirmDeleteUser=O usuário deve ser apagado?
|
adminUserSettings.confirmDeleteUser=O usuário deve ser apagado?
|
||||||
adminUserSettings.confirmChangeUserStatus=O usuário deve ser desabilitado/habilitado?
|
adminUserSettings.confirmChangeUserStatus=O usuário deve ser desabilitado/habilitado?
|
||||||
adminUserSettings.usernameInfo=Nome de usuário só pode incluir letras, números e os seguintes caracteres especiais @._+- ou deve ser um e-mail válido.
|
adminUserSettings.usernameInfo=Nome de usuário só pode incluir letras, números e os seguintes caracteres especiais @._+- ou deve ser um email válido.
|
||||||
adminUserSettings.roles=Funções
|
adminUserSettings.roles=Funções
|
||||||
adminUserSettings.role=Função
|
adminUserSettings.role=Função
|
||||||
adminUserSettings.actions=Ações
|
adminUserSettings.actions=Ações
|
||||||
adminUserSettings.apiUser=Usuário de API limitado
|
adminUserSettings.apiUser=Usuário de API limitado
|
||||||
adminUserSettings.extraApiUser=Usuário de API limitado adicional
|
adminUserSettings.extraApiUser=Usuário de API limitado adicional
|
||||||
adminUserSettings.webOnlyUser=Usuário web apenas
|
adminUserSettings.webOnlyUser=Usuário apenas web
|
||||||
adminUserSettings.demoUser=Usuário demo (Sem configurações personalizadas)
|
adminUserSettings.demoUser=Usuário demo (Sem configurações personalizadas)
|
||||||
adminUserSettings.internalApiUser=Usuário interno de API
|
adminUserSettings.internalApiUser=Usuário interno de API
|
||||||
adminUserSettings.forceChange=Forçar usuário a trocar a senha ao iniciar sessão
|
adminUserSettings.forceChange=Forçar usuário a trocar a senha ao iniciar sessão
|
||||||
adminUserSettings.submit=Salvar Usuário
|
adminUserSettings.submit=Salvar usuário
|
||||||
adminUserSettings.changeUserRole=Alterar Função do Usuário
|
adminUserSettings.changeUserRole=Alterar Função de Usuário
|
||||||
adminUserSettings.authenticated=Autenticado
|
adminUserSettings.authenticated=Autenticado
|
||||||
adminUserSettings.editOwnProfil=Editar próprio perfil
|
adminUserSettings.editOwnProfil=Editar próprio perfil
|
||||||
adminUserSettings.enabledUser=usuário habilitado
|
adminUserSettings.enabledUser=usuário habilitado
|
||||||
@@ -237,16 +217,14 @@ database.fileSize=Tamanho do arquivo
|
|||||||
database.deleteBackupFile=Apagar arquivo de backup
|
database.deleteBackupFile=Apagar arquivo de backup
|
||||||
database.importBackupFile=Importar arquivo de backup
|
database.importBackupFile=Importar arquivo de backup
|
||||||
database.downloadBackupFile=Baixar arquivo de backup
|
database.downloadBackupFile=Baixar arquivo de backup
|
||||||
database.info_1=Ao importar dados, é crucial garantir a estrutura correta. Se você não tem certeza do que está fazendo procure auxílio de um profissional. Um erro na estrutura pode ocasionar em mau funcionamento da aplicação, incluindo a impossibilidade da aplicação ser executada.
|
database.info_1=Ao importar dados, é crucial garantir a estrutura correta. Se você não tem certeza do que está fazendo procure auxílio de um profissional. Um erro na estrutura pode ocasionar em mau funcionamento da aplicação, incluindo a possibilidade de perda total da aplicação.
|
||||||
database.info_2=O nome do arquivo não importa ao enviar. Ele será renomeado em seguida para seguir o formato backup_user_yyyyMMddHHmm.sql, garantindo uma convenção de nomes coerente.
|
database.info_2=O nome do arquivo não importa ao enviar. Ele será renomeado em seguida para seguir o formato backup_user_yyyyMMddHHmm.sql, garantindo uma convenção de nomes coerente.
|
||||||
database.submit=Importar Backup
|
database.submit=Importar Backup
|
||||||
database.importIntoDatabaseSuccessed=Importação para o banco de dados bem sucedida
|
database.importIntoDatabaseSuccessed=Importação para o banco de dados bem sucedida
|
||||||
database.fileNotFound=Arquivo não encontrado
|
database.fileNotFound=Arquivo não encontrado
|
||||||
database.fileNullOrEmpty=O arquivo não pode estar nulo ou vazio
|
database.fileNullOrEmpty=O arquivo não estar nulo ou vazio
|
||||||
database.failedImportFile=Falha ao importar arquivo
|
database.failedImportFile=Falha ao importar arquivo
|
||||||
|
|
||||||
session.expired=Sua sessão expirou. Por gentileza atualize a página e tente novamente.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -259,11 +237,11 @@ home.viewPdf.desc=Visualizar, anotar, adicionar texto ou imagens
|
|||||||
viewPdf.tags=visualizar,ler,anotar,texto,imagem
|
viewPdf.tags=visualizar,ler,anotar,texto,imagem
|
||||||
|
|
||||||
home.multiTool.title=Multiferramenta de PDF
|
home.multiTool.title=Multiferramenta de PDF
|
||||||
home.multiTool.desc=Mesclar, girar, reorganizar, dividir e remover páginas
|
home.multiTool.desc=Mesclar, girar, reorganizar e remover páginas
|
||||||
multiTool.tags=Multiferramenta, múltiplas operações, Interface do Usuário, Clique e arraste, front-end, lado do cliente, interativo, intratável, movimento, excluir, migrar, dividir
|
multiTool.tags=Multiferramenta,Múltiplas operações,Interface do Usuário,Clique e arraste,front-end,lado do cliente,interativo,intratável,movimento
|
||||||
|
|
||||||
home.merge.title=Mesclar
|
home.merge.title=Mesclar
|
||||||
home.merge.desc=Mescle facilmente vários PDFs em um só.
|
home.merge.desc=Mesclar facilmente vários PDFs em um só.
|
||||||
merge.tags=mesclar,Operações de Página,Back-end,lado do servidor
|
merge.tags=mesclar,Operações de Página,Back-end,lado do servidor
|
||||||
|
|
||||||
home.split.title=Dividir
|
home.split.title=Dividir
|
||||||
@@ -271,7 +249,7 @@ home.split.desc=Dividir PDFs em vários documentos
|
|||||||
split.tags=Operações de Página,dividir,Múltiplas Páginas,cortar,lado do servidor
|
split.tags=Operações de Página,dividir,Múltiplas Páginas,cortar,lado do servidor
|
||||||
|
|
||||||
home.rotate.title=Girar
|
home.rotate.title=Girar
|
||||||
home.rotate.desc=Gire facilmente seus PDFs.
|
home.rotate.desc=Girar facilmente seus PDFs.
|
||||||
rotate.tags=Lado do servidor
|
rotate.tags=Lado do servidor
|
||||||
|
|
||||||
|
|
||||||
@@ -289,11 +267,11 @@ pdfOrganiser.tags=duplex,par,ímpar,ordenar,mover
|
|||||||
|
|
||||||
|
|
||||||
home.addImage.title=Adicionar Imagem
|
home.addImage.title=Adicionar Imagem
|
||||||
home.addImage.desc=Adicionar uma imagem em um local definido no PDF
|
home.addImage.desc=Adicionar uma imagem em um local definido no PDF (Em desenvolvimento)
|
||||||
addImage.tags=img,jpg,imagem,foto
|
addImage.tags=img,jpg,imagem,foto
|
||||||
|
|
||||||
home.watermark.title=Adicionar Marca d'água
|
home.watermark.title="Adicionar Marca d'água"
|
||||||
home.watermark.desc=Adicionar uma marca d'água personalizada ao seu documento PDF.
|
home.watermark.desc="Adicionar uma marca d'água personalizada ao seu documento PDF."
|
||||||
watermark.tags=Texto,repetindo,rótulo,próprio,direitos autorais,marca registrada,img,jpg,imagem,foto
|
watermark.tags=Texto,repetindo,rótulo,próprio,direitos autorais,marca registrada,img,jpg,imagem,foto
|
||||||
|
|
||||||
home.permissions.title=Alterar Permissões
|
home.permissions.title=Alterar Permissões
|
||||||
@@ -305,13 +283,13 @@ home.removePages.title=Remover
|
|||||||
home.removePages.desc=Excluir as páginas indesejadas do seu documento PDF.
|
home.removePages.desc=Excluir as páginas indesejadas do seu documento PDF.
|
||||||
removePages.tags=Remover páginas,excluir páginas
|
removePages.tags=Remover páginas,excluir páginas
|
||||||
|
|
||||||
home.addPassword.title=Adicionar Senha
|
home.addPassword.title=Adicionar senha
|
||||||
home.addPassword.desc=Criptografar seu documento PDF com uma senha.
|
home.addPassword.desc=Criptografar seu documento PDF com uma senha.
|
||||||
addPassword.tags=seguro,segurança
|
addPassword.tags=seguro,segurança
|
||||||
|
|
||||||
home.removePassword.title=Remover Senha
|
home.removePassword.title=Remover Senha
|
||||||
home.removePassword.desc=Remover a proteção por senha do seu documento PDF.
|
home.removePassword.desc=Remover a proteção por senha do seu documento PDF.
|
||||||
removePassword.tags=seguro, descriptografar, segurança, remover senha
|
removePassword.tags=seguro, Descriptografar, segurança, remover senha
|
||||||
|
|
||||||
home.compressPdfs.title=Comprimir
|
home.compressPdfs.title=Comprimir
|
||||||
home.compressPdfs.desc=Comprimir PDFs para reduzir o tamanho do arquivo.
|
home.compressPdfs.desc=Comprimir PDFs para reduzir o tamanho do arquivo.
|
||||||
@@ -341,7 +319,7 @@ pdfToPDFA.tags=arquivo,longo prazo,padrão,conversão,armazenamento,preservaçã
|
|||||||
|
|
||||||
home.PDFToWord.title=PDF para Word
|
home.PDFToWord.title=PDF para Word
|
||||||
home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT)
|
home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT)
|
||||||
PDFToWord.tags=doc,docx,odt,word,transformação,formato,conversão,escritório,microsoft,doc
|
PDFToWord.tags=doc,docx,odt,word,transformação,formato,conversão,escritório,microsoft,arquivo doc
|
||||||
|
|
||||||
home.PDFToPresentation.title=PDF para Apresentação
|
home.PDFToPresentation.title=PDF para Apresentação
|
||||||
home.PDFToPresentation.desc=Converter PDF para formatos de apresentação (PPT, PPTX e ODP)
|
home.PDFToPresentation.desc=Converter PDF para formatos de apresentação (PPT, PPTX e ODP)
|
||||||
@@ -357,12 +335,12 @@ PDFToHTML.tags=conteúdo web,compatível com navegador
|
|||||||
|
|
||||||
|
|
||||||
home.PDFToXML.title=PDF para XML
|
home.PDFToXML.title=PDF para XML
|
||||||
home.PDFToXML.desc=Converter PDF para formato XML
|
home.PDFToXML.desc=Converter PDF para o formato XML
|
||||||
PDFToXML.tags=extração-de-dados,conteúdo-estruturado,interoperabilidade,transformação,converter
|
PDFToXML.tags=extração-de-dados,conteúdo-estruturado,interoperabilidade,transformação,converter
|
||||||
|
|
||||||
home.ScannerImageSplit.title=Detectar/Dividir Fotos Digitalizadas
|
home.ScannerImageSplit.title=Detectar/Dividir Fotos Digitalizadas
|
||||||
home.ScannerImageSplit.desc=Divide várias fotos de dentro de uma imagem/PDF
|
home.ScannerImageSplit.desc=Divide várias fotos de dentro de uma imagem/PDF digitalizado
|
||||||
ScannerImageSplit.tags=separar,detecção-automática,digitalizações,fotos-múltiplas,organizar
|
ScannerImageSplit.tags=separar,detecção-automática,digitalizações,foto-múltipla,organizar
|
||||||
|
|
||||||
home.sign.title=Assinar
|
home.sign.title=Assinar
|
||||||
home.sign.desc=Adicionar assinatura ao PDF por desenho, texto ou imagem
|
home.sign.desc=Adicionar assinatura ao PDF por desenho, texto ou imagem
|
||||||
@@ -380,7 +358,7 @@ home.removeBlanks.title=Remover Páginas em Branco
|
|||||||
home.removeBlanks.desc=Detectar e remover páginas em branco de um documento
|
home.removeBlanks.desc=Detectar e remover páginas em branco de um documento
|
||||||
removeBlanks.tags=limpeza,otimização,sem-conteúdo,organizar
|
removeBlanks.tags=limpeza,otimização,sem-conteúdo,organizar
|
||||||
|
|
||||||
home.removeAnnotations.title=Remover Anotações
|
home.removeAnnotations.title=Remover anotações
|
||||||
home.removeAnnotations.desc=Remove todos os comentários/anotações de um PDF
|
home.removeAnnotations.desc=Remove todos os comentários/anotações de um PDF
|
||||||
removeAnnotations.tags=comentários,destaque,notas,marcação,remover
|
removeAnnotations.tags=comentários,destaque,notas,marcação,remover
|
||||||
|
|
||||||
@@ -428,7 +406,7 @@ home.autoSplitPDF.title=Divisão Automática de Páginas
|
|||||||
home.autoSplitPDF.desc=Dividir automaticamente um PDF digitalizado com separador de páginas físicas QR Code
|
home.autoSplitPDF.desc=Dividir automaticamente um PDF digitalizado com separador de páginas físicas QR Code
|
||||||
autoSplitPDF.tags=baseado-em-QR,separar,segmento-de-digitalização,organizar
|
autoSplitPDF.tags=baseado-em-QR,separar,segmento-de-digitalização,organizar
|
||||||
|
|
||||||
home.sanitizePdf.title=Higienizar
|
home.sanitizePdf.title=Sanitizar
|
||||||
home.sanitizePdf.desc=Remover scripts e outros elementos de arquivos PDF
|
home.sanitizePdf.desc=Remover scripts e outros elementos de arquivos PDF
|
||||||
sanitizePdf.tags=limpar,seguro,protegido,remover-ameaças
|
sanitizePdf.tags=limpar,seguro,protegido,remover-ameaças
|
||||||
|
|
||||||
@@ -470,7 +448,7 @@ home.autoRedact.desc=Ocultação automática (escurecimento) de texto em um PDF
|
|||||||
autoRedact.tags=Redigir,ocultar,escurecer,preto,marcador,oculto
|
autoRedact.tags=Redigir,ocultar,escurecer,preto,marcador,oculto
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF para CSV
|
home.tableExtraxt.title=PDF para CSV
|
||||||
home.tableExtraxt.desc=Extrai tabelas de um PDF convertendo para CSV
|
home.tableExtraxt.desc=Extrai tabelas de um PDF convertendo-o para CSV
|
||||||
tableExtraxt.tags=CSV,extração de tabela,extrair,converter
|
tableExtraxt.tags=CSV,extração de tabela,extrair,converter
|
||||||
|
|
||||||
|
|
||||||
@@ -483,13 +461,13 @@ home.overlay-pdfs.title=Sobrepor PDFs
|
|||||||
home.overlay-pdfs.desc=Sobrepõe PDFs sobre outro PDF
|
home.overlay-pdfs.desc=Sobrepõe PDFs sobre outro PDF
|
||||||
overlay-pdfs.tags=Sobreposição
|
overlay-pdfs.tags=Sobreposição
|
||||||
|
|
||||||
home.split-by-sections.title=Dividir PDF por Seções
|
home.split-by-sections.title=Dividir PDF por seções
|
||||||
home.split-by-sections.desc=Divida cada página de um PDF em seções horizontais e verticais menores
|
home.split-by-sections.desc=Divida cada página de um PDF em seções horizontais e verticais menores
|
||||||
split-by-sections.tags=Seção Dividir, Dividir, Personalizar
|
split-by-sections.tags=Seção Dividir, Dividir, Personalizar
|
||||||
|
|
||||||
home.AddStampRequest.title=Adicionar Carimbo ao PDF
|
home.AddStampRequest.title=Adicionar carimbo ao PDF
|
||||||
home.AddStampRequest.desc=Adicione texto ou carimbos de imagem em locais definidos
|
home.AddStampRequest.desc=Adicione texto ou carimbos de imagem em locais definidos
|
||||||
AddStampRequest.tags=Carimbo,Adicionar imagem,centralizar imagem,Marca d'água,PDF,Incorporar,Personalizar
|
AddStampRequest.tags="Carimbo,Adicionar imagem,centralizar imagem,Marca d'água,PDF,Incorporar,Personalizar"
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF para Livro
|
home.PDFToBook.title=PDF para Livro
|
||||||
@@ -497,36 +475,31 @@ home.PDFToBook.desc=Converte PDF para formatos de livro/quadrinhos usando Calibr
|
|||||||
PDFToBook.tags=Livro,Quadrinhos,Calibre,Converter,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
|
PDFToBook.tags=Livro,Quadrinhos,Calibre,Converter,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
|
||||||
|
|
||||||
home.BookToPDF.title=Livro para PDF
|
home.BookToPDF.title=Livro para PDF
|
||||||
home.BookToPDF.desc=Converte formatos de livros/quadrinhos para PDF usando Calibre
|
home.BookToPDF.desc=Converte formatos de livros/quadrinhos em PDF usando Calibre
|
||||||
BookToPDF.tags=Livro,Quadrinhos,Calibre,Converter,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
|
BookToPDF.tags=Livro,Quadrinhos,Calibre,Converter,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
|
||||||
|
|
||||||
home.removeImagePdf.title=Remover Imagem
|
home.removeImagePdf.title=Remover imagem
|
||||||
home.removeImagePdf.desc=Remova a imagem do PDF para reduzir o tamanho do arquivo
|
home.removeImagePdf.desc=Remova a imagem do PDF para reduzir o tamanho do arquivo
|
||||||
removeImagePdf.tags=Remover imagem,operações de página,back-end,lado do servidor
|
removeImagePdf.tags=Remover imagem,operações de página,back-end,lado do servidor
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Divide PDF por Capítulos
|
|
||||||
home.splitPdfByChapters.desc=Divide um PDF em vários arquivos baseado na sua estrutura de capítulos.
|
|
||||||
splitPdfByChapters.tags=dividir,capítulos,favoritos,organizar
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Substituir-Inverter-Cor
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Substitui-Inverter Cor PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Substitui e Inverte Cor
|
home.replaceColorPdf.title=Replace and Invert Color
|
||||||
home.replaceColorPdf.desc=Substitui cor de um texto e plano de fundo de um PDF e inverte a toda cor do PDF para reduzir o tamanho
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Substitui Cor, Operações na Página, back end, lado do servidor
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Substituir ou inverter cor Opções
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
replace-color.selectText.2=Padrão(Padrão cores de alto constraste)
|
replace-color.selectText.2=Default(Default high contrast colors)
|
||||||
replace-color.selectText.3=Customizado(Cores customizadas)
|
replace-color.selectText.3=Custom(Customized colors)
|
||||||
replace-color.selectText.4=Inversão Completa(Inverte todas cores)
|
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||||
replace-color.selectText.5=Opções de cores de alto contraste
|
replace-color.selectText.5=High contrast color options
|
||||||
replace-color.selectText.6=Texto branco em um plano de fundo preto
|
replace-color.selectText.6=white text on black background
|
||||||
replace-color.selectText.7=Texto preto em um plano de fundo branco
|
replace-color.selectText.7=Black text on white background
|
||||||
replace-color.selectText.8=Texto amarelo em um plano de fundo preto
|
replace-color.selectText.8=Yellow text on black background
|
||||||
replace-color.selectText.9=Texto verde em um plano de fundo preto
|
replace-color.selectText.9=Green text on black background
|
||||||
replace-color.selectText.10=Escolha cor do texto
|
replace-color.selectText.10=Choose text Color
|
||||||
replace-color.selectText.11=Escolha cor do plano de fundo
|
replace-color.selectText.11=Choose background Color
|
||||||
replace-color.submit=Substituir
|
replace-color.submit=Replace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -543,23 +516,21 @@ login.rememberme=Lembrar de mim
|
|||||||
login.invalid=Usuário ou senha inválidos.
|
login.invalid=Usuário ou senha inválidos.
|
||||||
login.locked=Sua conta foi bloqueada.
|
login.locked=Sua conta foi bloqueada.
|
||||||
login.signinTitle=Por favor, inicie a sessão
|
login.signinTitle=Por favor, inicie a sessão
|
||||||
login.ssoSignIn=Iniciar sessão através de login único (SSO)
|
login.ssoSignIn=Iniciar sessão através de início de sessão único
|
||||||
login.oauth2AutoCreateDisabled=Auto-Criar Usuário OAUTH2 Desativado
|
login.oauth2AutoCreateDisabled=Auto-Criar Usuário OAUTH2 Desativado
|
||||||
login.oauth2AdminBlockedUser=O registro ou login de usuários não registrados está atualmente bloqueado. Entre em contato com o administrador.
|
login.oauth2AdminBlockedUser=O registro ou login de usuários não registrados está atualmente bloqueado. Entre em contato com o administrador.
|
||||||
login.oauth2RequestNotFound=Solicitação de autorização não encontrada
|
login.oauth2RequestNotFound=Solicitação de autorização não encontrada
|
||||||
login.oauth2InvalidUserInfoResponse=Resposta de informação de usuário inválida
|
login.oauth2InvalidUserInfoResponse=Resposta de informação de usuário inválida
|
||||||
login.oauth2invalidRequest=Requisição Inválida
|
login.oauth2invalidRequest=Requisição inválida
|
||||||
login.oauth2AccessDenied=Acesso Negado
|
login.oauth2AccessDenied=Acesso negado
|
||||||
login.oauth2InvalidTokenResponse=Resposta de Token Inválida
|
login.oauth2InvalidTokenResponse=Resposta de token inválida
|
||||||
login.oauth2InvalidIdToken=Id de Token Inválido
|
login.oauth2InvalidIdToken=Id de token inválido
|
||||||
login.userIsDisabled=O usuário está desativado, o login está atualmente bloqueado com este nome de usuário. Entre em contato com o administrador.
|
login.userIsDisabled=O usuário está desativado, o login está atualmente bloqueado com este nome de usuário. Entre em contato com o administrador.
|
||||||
login.alreadyLoggedIn=Você já está conectado
|
|
||||||
login.alreadyLoggedIn2=aparelhos. Por favor saia dos aparelhos e tente novamente.
|
|
||||||
login.toManySessions=Você tem muitas sessões ativas
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redação Automática de Dados
|
autoRedact.title=Redigir automaticamente
|
||||||
autoRedact.header=Redação Automática de Dados
|
autoRedact.header=Redigir automaticamente
|
||||||
autoRedact.colorLabel=Cor
|
autoRedact.colorLabel=Cor
|
||||||
autoRedact.textsToRedactLabel=Texto para redigir (separado por linha)
|
autoRedact.textsToRedactLabel=Texto para redigir (separado por linha)
|
||||||
autoRedact.textsToRedactPlaceholder=por exemplo: \nConfidencial \nSecreto
|
autoRedact.textsToRedactPlaceholder=por exemplo: \nConfidencial \nSecreto
|
||||||
@@ -645,22 +616,22 @@ AddStampRequest.fontSize=Tamanho da fonte/imagem
|
|||||||
AddStampRequest.rotation=Rotação
|
AddStampRequest.rotation=Rotação
|
||||||
AddStampRequest.opacity=Opacidade
|
AddStampRequest.opacity=Opacidade
|
||||||
AddStampRequest.position=Posição
|
AddStampRequest.position=Posição
|
||||||
AddStampRequest.overrideX=Substituir Coordenada X
|
AddStampRequest.overrideX=Substituir coordenada X
|
||||||
AddStampRequest.overrideY=Substituir Coordenada Y
|
AddStampRequest.overrideY=Substituir coordenada Y
|
||||||
AddStampRequest.customMargin=Margem personalizada
|
AddStampRequest.customMargin=Margem personalizada
|
||||||
AddStampRequest.customColor=Cor de texto personalizada
|
AddStampRequest.customColor=Cor de texto personalizada
|
||||||
AddStampRequest.submit=Enviar
|
AddStampRequest.submit=Enviar
|
||||||
|
|
||||||
|
|
||||||
#sanitizePDF
|
#sanitizePDF
|
||||||
sanitizePDF.title=Higienizar PDF
|
sanitizePDF.title=Sanitizar PDF
|
||||||
sanitizePDF.header=Higienizar um arquivo PDF
|
sanitizePDF.header=Sanitizar um arquivo PDF
|
||||||
sanitizePDF.selectText.1=Remover ações de JavaScript
|
sanitizePDF.selectText.1=Remover ações de JavaScript
|
||||||
sanitizePDF.selectText.2=Remover arquivos embutidos
|
sanitizePDF.selectText.2=Remover arquivos embutidos
|
||||||
sanitizePDF.selectText.3=Remover metadados
|
sanitizePDF.selectText.3=Remover metadados
|
||||||
sanitizePDF.selectText.4=Remover links
|
sanitizePDF.selectText.4=Remover links
|
||||||
sanitizePDF.selectText.5=Remover fontes
|
sanitizePDF.selectText.5=Remover fontes
|
||||||
sanitizePDF.submit=Higienizar PDF
|
sanitizePDF.submit=Sanitizar PDF
|
||||||
|
|
||||||
|
|
||||||
#addPageNumbers
|
#addPageNumbers
|
||||||
@@ -740,9 +711,9 @@ certSign.title=Assinatura com Certificado
|
|||||||
certSign.header=Assine um PDF com o seu certificado (Em desenvolvimento)
|
certSign.header=Assine um PDF com o seu certificado (Em desenvolvimento)
|
||||||
certSign.selectPDF=Selecione um arquivo PDF para assinatura:
|
certSign.selectPDF=Selecione um arquivo PDF para assinatura:
|
||||||
certSign.jksNote=Nota: Se o seu tipo de certificado não estiver listado abaixo, converta-o em um arquivo Java Keystore (.jks) usando a ferramenta de linha de comando keytool. Em seguida, escolha a opção de arquivo .jks abaixo.
|
certSign.jksNote=Nota: Se o seu tipo de certificado não estiver listado abaixo, converta-o em um arquivo Java Keystore (.jks) usando a ferramenta de linha de comando keytool. Em seguida, escolha a opção de arquivo .jks abaixo.
|
||||||
certSign.selectKey=Selecione o seu arquivo de chave privada (formato PKCS#8, pode ser .pem ou .der):
|
certSign.selectKey="Selecione o seu arquivo de chave privada (formato PKCS#8, pode ser .pem ou .der):"
|
||||||
certSign.selectCert=Selecione o seu arquivo de certificado (formato X.509, pode ser .pem ou .der):
|
certSign.selectCert=Selecione o seu arquivo de certificado (formato X.509, pode ser .pem ou .der):
|
||||||
certSign.selectP12=Selecione o seu arquivo de armazenamento de chave PKCS#12 (.p12 ou .pfx) (opcional, se fornecido, deve conter a sua chave privada e certificado):
|
certSign.selectP12="Selecione o seu arquivo de armazenamento de chave PKCS#12 (.p12 ou .pfx) (opcional, se fornecido, deve conter a sua chave privada e certificado):"
|
||||||
certSign.selectJKS=Selecione seu arquivo Java Keystore (.jks ou .keystore):
|
certSign.selectJKS=Selecione seu arquivo Java Keystore (.jks ou .keystore):
|
||||||
certSign.certType=Tipo de Certificado
|
certSign.certType=Tipo de Certificado
|
||||||
certSign.password=Digite a senha do seu armazenamento de chave ou chave privada (se aplicável):
|
certSign.password=Digite a senha do seu armazenamento de chave ou chave privada (se aplicável):
|
||||||
@@ -754,7 +725,7 @@ certSign.submit=Assinar PDF
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Remover Assinatura do Certificado
|
removeCertSign.title=Remover assinatura com Certificado
|
||||||
removeCertSign.header=Remover o certificado digital do PDF
|
removeCertSign.header=Remover o certificado digital do PDF
|
||||||
removeCertSign.selectPDF=Selecione um arquivo PDF:
|
removeCertSign.selectPDF=Selecione um arquivo PDF:
|
||||||
removeCertSign.submit=Remover assinatura
|
removeCertSign.submit=Remover assinatura
|
||||||
@@ -766,13 +737,13 @@ removeBlanks.header=Remover páginas em branco
|
|||||||
removeBlanks.threshold=Limite de brancura de pixel:
|
removeBlanks.threshold=Limite de brancura de pixel:
|
||||||
removeBlanks.thresholdDesc=Limite para determinar o quão branco um pixel branco deve ser para ser classificado como 'Branco'. 0 = Preto, 255 branco puro.
|
removeBlanks.thresholdDesc=Limite para determinar o quão branco um pixel branco deve ser para ser classificado como 'Branco'. 0 = Preto, 255 branco puro.
|
||||||
removeBlanks.whitePercent=Porcentagem de Branco (%):
|
removeBlanks.whitePercent=Porcentagem de Branco (%):
|
||||||
removeBlanks.whitePercentDesc=Porcentagem da página que devem ter pixels “brancos” para serem removidas
|
removeBlanks.whitePercentDesc=Porcentagem de páginas que devem ter pixels “brancos” para serem removidas
|
||||||
removeBlanks.submit=Remover páginas em branco
|
removeBlanks.submit=Remover páginas em branco
|
||||||
|
|
||||||
|
|
||||||
#removeAnnotations
|
#removeAnnotations
|
||||||
removeAnnotations.title=Remover Anotações
|
removeAnnotations.title=Remover anotações
|
||||||
removeAnnotations.header=Remover Anotações
|
removeAnnotations.header=Remover anotações
|
||||||
removeAnnotations.submit=Remover
|
removeAnnotations.submit=Remover
|
||||||
|
|
||||||
|
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Cor de destaque 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Livros e Quadrinhos para PDF
|
BookToPDF.title=Livros e Quadrinhos para PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Desenhar Assinatura
|
|||||||
sign.text=Inserir texto
|
sign.text=Inserir texto
|
||||||
sign.clear=Limpar
|
sign.clear=Limpar
|
||||||
sign.add=Adicionar
|
sign.add=Adicionar
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -846,26 +809,26 @@ ScannerImageSplit.info=Python não está instalado. É necessário para executar
|
|||||||
#OCR
|
#OCR
|
||||||
ocr.title=OCR / Limpeza de Digitalização
|
ocr.title=OCR / Limpeza de Digitalização
|
||||||
ocr.header=OCR / Limpeza de Digitalização (Reconhecimento Óptico de Caracteres)
|
ocr.header=OCR / Limpeza de Digitalização (Reconhecimento Óptico de Caracteres)
|
||||||
ocr.selectText.1=Selecione os idiomas a serem detectados no PDF (os listados são os atualmente instalados):
|
ocr.selectText.1=Selecione os idiomas a serem detectados no PDF (os listados são os atualmente detectados):
|
||||||
ocr.selectText.2=Criar um arquivo de texto contendo o texto OCR junto do PDF com OCR
|
ocr.selectText.2=Criar um arquivo de texto contendo o texto OCR ao lado do PDF com OCR
|
||||||
ocr.selectText.3=Páginas corretamente digitalizadas em um ângulo inclinado, gire-as de volta à posição original
|
ocr.selectText.3=Páginas corretamente digitalizadas em um ângulo inclinado, gire-as de volta à posição original
|
||||||
ocr.selectText.4=Limpar a página para reduzir a probabilidade de o OCR encontrar texto no ruído de fundo (sem alteração na saída)
|
ocr.selectText.4=Limpar a página para reduzir a probabilidade de o OCR encontrar texto no ruído de fundo (sem alteração na saída)
|
||||||
ocr.selectText.5=Limpar a página para reduzir a probabilidade de o OCR encontrar texto no ruído de fundo, mantendo a limpeza na saída.
|
ocr.selectText.5=Limpar a página para reduzir a probabilidade de o OCR encontrar texto no ruído de fundo, mantendo a limpeza na saída.
|
||||||
ocr.selectText.6=Ignorar páginas com texto interativo, processar por OCR apenas as páginas com imagens
|
ocr.selectText.6=Ignorar páginas com texto interativo, processar apenas as páginas de OCR que são imagens
|
||||||
ocr.selectText.7=Forçar OCR, executar OCR em todas as páginas, removendo todos os elementos de texto originais
|
ocr.selectText.7=Forçar OCR, executar OCR em todas as páginas, removendo todos os elementos de texto originais
|
||||||
ocr.selectText.8=Normal (gerará um erro se o PDF já contiver texto)
|
ocr.selectText.8=Normal (gerará um erro se o PDF já contiver texto)
|
||||||
ocr.selectText.9=Configurações Adicionais
|
ocr.selectText.9=Configurações adicionais
|
||||||
ocr.selectText.10=Modo OCR
|
ocr.selectText.10=Modo OCR
|
||||||
ocr.selectText.11=Remover imagens após o OCR (remove TODAS as imagens, útil apenas como parte do processo de conversão)
|
ocr.selectText.11=Remover imagens após o OCR (remove TODAS as imagens, útil apenas como parte do processo de conversão)
|
||||||
ocr.selectText.12=Tipo de Renderização (avançado)
|
ocr.selectText.12=Tipo de renderização (avançado)
|
||||||
ocr.help=Por favor, leia a documentação sobre como usar isso para outros idiomas e/ou fora do ambiente Docker
|
ocr.help=Por favor, leia a documentação sobre como usar isso para outros idiomas e/ou fora do ambiente Docker
|
||||||
ocr.credit=Este serviço usa OCRmyPDF e Tesseract para OCR.
|
ocr.credit=Este serviço usa OCRmyPDF e Tesseract para OCR.
|
||||||
ocr.submit=Processar PDF com OCR
|
ocr.submit=Processar PDF com OCR
|
||||||
|
|
||||||
|
|
||||||
#extractImages
|
#extractImages
|
||||||
extractImages.title=Extrair Imagens
|
extractImages.title=Extrair imagens
|
||||||
extractImages.header=Extrair Imagens
|
extractImages.header=Extrair imagens
|
||||||
extractImages.selectText=Selecione o formato de imagem para converter as imagens extraídas
|
extractImages.selectText=Selecione o formato de imagem para converter as imagens extraídas
|
||||||
extractImages.allowDuplicates=Salvar imagens duplicadas
|
extractImages.allowDuplicates=Salvar imagens duplicadas
|
||||||
extractImages.submit=Extrair
|
extractImages.submit=Extrair
|
||||||
@@ -893,7 +856,7 @@ compress.submit=Comprimir
|
|||||||
|
|
||||||
|
|
||||||
#Add image
|
#Add image
|
||||||
addImage.title=Adicionar Imagem
|
addImage.title=Adicionar imagem
|
||||||
addImage.header=Adicionar imagem ao PDF
|
addImage.header=Adicionar imagem ao PDF
|
||||||
addImage.everyPage=Para cada página?
|
addImage.everyPage=Para cada página?
|
||||||
addImage.upload=Enviar imagem
|
addImage.upload=Enviar imagem
|
||||||
@@ -902,7 +865,7 @@ addImage.submit=Adicionar imagem
|
|||||||
|
|
||||||
#merge
|
#merge
|
||||||
merge.title=Mesclar
|
merge.title=Mesclar
|
||||||
merge.header=Mesclar vários PDFs (2+)
|
merge.header=Mesclar Vários PDFs (2+)
|
||||||
merge.sortByName=Classificar por nome
|
merge.sortByName=Classificar por nome
|
||||||
merge.sortByDate=Classificar por data
|
merge.sortByDate=Classificar por data
|
||||||
merge.removeCertSign=Remover a assinatura digital do arquivo mesclado?
|
merge.removeCertSign=Remover a assinatura digital do arquivo mesclado?
|
||||||
@@ -916,7 +879,7 @@ pdfOrganiser.submit=Reorganizar páginas
|
|||||||
pdfOrganiser.mode=Modo
|
pdfOrganiser.mode=Modo
|
||||||
pdfOrganiser.mode.1=Ordem de página personalizada
|
pdfOrganiser.mode.1=Ordem de página personalizada
|
||||||
pdfOrganiser.mode.2=Ordem inversa
|
pdfOrganiser.mode.2=Ordem inversa
|
||||||
pdfOrganiser.mode.3=Classificação duplex
|
pdfOrganiser.mode.3=Classificação Duplex
|
||||||
pdfOrganiser.mode.4=Classificação de livreto
|
pdfOrganiser.mode.4=Classificação de livreto
|
||||||
pdfOrganiser.mode.5=Classificação de livreto com ponto lateral
|
pdfOrganiser.mode.5=Classificação de livreto com ponto lateral
|
||||||
pdfOrganiser.mode.6=Divisão ímpar-par
|
pdfOrganiser.mode.6=Divisão ímpar-par
|
||||||
@@ -981,7 +944,7 @@ imageToPDF.selectText.5=Converter em PDFs separados
|
|||||||
|
|
||||||
|
|
||||||
#pdfToImage
|
#pdfToImage
|
||||||
pdfToImage.title=PDF para Imagem
|
pdfToImage.title=PDF para imagem
|
||||||
pdfToImage.header=Converter PDF para imagem
|
pdfToImage.header=Converter PDF para imagem
|
||||||
pdfToImage.selectText=Formato de imagem
|
pdfToImage.selectText=Formato de imagem
|
||||||
pdfToImage.singleOrMultiple=Tipo de resultado de imagem
|
pdfToImage.singleOrMultiple=Tipo de resultado de imagem
|
||||||
@@ -990,7 +953,7 @@ pdfToImage.multi=Várias imagens, uma imagem por página
|
|||||||
pdfToImage.colorType=Tipo de cor
|
pdfToImage.colorType=Tipo de cor
|
||||||
pdfToImage.color=Colorida
|
pdfToImage.color=Colorida
|
||||||
pdfToImage.grey=Escala de Cinza
|
pdfToImage.grey=Escala de Cinza
|
||||||
pdfToImage.blackwhite=Preto e Branco (pode perder informações!)
|
pdfToImage.blackwhite=Preto e Branco (pode perder de dados!)
|
||||||
pdfToImage.submit=Converter
|
pdfToImage.submit=Converter
|
||||||
pdfToImage.info=Python não está instalado. Necessário para conversão WebP.
|
pdfToImage.info=Python não está instalado. Necessário para conversão WebP.
|
||||||
|
|
||||||
@@ -1001,7 +964,7 @@ addPassword.header=Adicionar Senha (Criptografar)
|
|||||||
addPassword.selectText.1=Selecione o PDF para Criptografar
|
addPassword.selectText.1=Selecione o PDF para Criptografar
|
||||||
addPassword.selectText.2=Senha
|
addPassword.selectText.2=Senha
|
||||||
addPassword.selectText.3=Tamanho da Chave de Criptografia
|
addPassword.selectText.3=Tamanho da Chave de Criptografia
|
||||||
addPassword.selectText.4=Valores mais altos são mais seguros, mas valores mais baixos são melhores para compatibilidade.
|
addPassword.selectText.4=Valores mais altos são mais seguros, mas valores mais baixos são mais compatíveis.
|
||||||
addPassword.selectText.5=Permissões a serem definidas (recomendado para uso junto com a senha do proprietário)
|
addPassword.selectText.5=Permissões a serem definidas (recomendado para uso junto com a senha do proprietário)
|
||||||
addPassword.selectText.6=Impedir a montagem do documento
|
addPassword.selectText.6=Impedir a montagem do documento
|
||||||
addPassword.selectText.7=Impedir a extração de conteúdo
|
addPassword.selectText.7=Impedir a extração de conteúdo
|
||||||
@@ -1018,26 +981,26 @@ addPassword.submit=Criptografar
|
|||||||
|
|
||||||
|
|
||||||
#watermark
|
#watermark
|
||||||
watermark.title=Adicionar marca d'água
|
watermark.title="Adicionar marca d'água"
|
||||||
watermark.header=Adicionar marca d'água
|
watermark.header="Adicionar marca d'água"
|
||||||
watermark.selectText.1=Selecione PDF para adicionar a marca d'água:
|
watermark.selectText.1="Selecione PDF para adicionar a marca d'água:"
|
||||||
watermark.selectText.2=Texto da marca d'água:
|
watermark.selectText.2="Texto da marca d'água:"
|
||||||
watermark.selectText.3=Tamanho da fonte:
|
watermark.selectText.3=Tamanho da fonte:
|
||||||
watermark.selectText.4=Rotação (0-360):
|
watermark.selectText.4=Rotação (0-360):
|
||||||
watermark.selectText.5=widthSpacer (Espaço entre cada marca d'água horizontalmente):
|
watermark.selectText.5="widthSpacer (Espaço entre cada marca d'água horizontalmente):"
|
||||||
watermark.selectText.6=heightSpacer (Espaço entre cada marca d'água verticalmente):
|
watermark.selectText.6="heightSpacer (Espaço entre cada marca d'água verticalmente):"
|
||||||
watermark.selectText.7=Opacidade (0% - 100%):
|
watermark.selectText.7=Opacidade (0% - 100%):
|
||||||
watermark.selectText.8=Tipo de marca d'água:
|
watermark.selectText.8="Tipo de marca d'água:"
|
||||||
watermark.selectText.9=Imagem da marca d'água:
|
watermark.selectText.9="Imagem da marca d'água:"
|
||||||
watermark.selectText.10=Converter PDF em imagem PDF
|
watermark.selectText.10=Converter PDF em imagem PDF
|
||||||
watermark.submit=Adicionar marca d'água
|
watermark.submit="Adicionar marca d'água"
|
||||||
watermark.type.1=Texto
|
watermark.type.1=Texto
|
||||||
watermark.type.2=Imagem
|
watermark.type.2=Imagem
|
||||||
|
|
||||||
|
|
||||||
#Change permissions
|
#Change permissions
|
||||||
permissions.title=Alterar Permissões
|
permissions.title=Alterar permissões
|
||||||
permissions.header=Alterar Permissões
|
permissions.header=Alterar permissões
|
||||||
permissions.warning=Aviso: para que essas permissões sejam imutáveis, é recomendável defini-las com uma senha através da página Adicionar Senha
|
permissions.warning=Aviso: para que essas permissões sejam imutáveis, é recomendável defini-las com uma senha através da página Adicionar Senha
|
||||||
permissions.selectText.1=Selecione o PDF para alterar as permissões
|
permissions.selectText.1=Selecione o PDF para alterar as permissões
|
||||||
permissions.selectText.2=Permissões para definir
|
permissions.selectText.2=Permissões para definir
|
||||||
@@ -1053,7 +1016,7 @@ permissions.submit=Alterar
|
|||||||
|
|
||||||
|
|
||||||
#remove password
|
#remove password
|
||||||
removePassword.title=Remover Senha
|
removePassword.title=Remover senha
|
||||||
removePassword.header=Remover senha (descriptografar)
|
removePassword.header=Remover senha (descriptografar)
|
||||||
removePassword.selectText.1=Selecione o PDF para descriptografar
|
removePassword.selectText.1=Selecione o PDF para descriptografar
|
||||||
removePassword.selectText.2=Senha
|
removePassword.selectText.2=Senha
|
||||||
@@ -1061,7 +1024,7 @@ removePassword.submit=Remover
|
|||||||
|
|
||||||
|
|
||||||
#changeMetadata
|
#changeMetadata
|
||||||
changeMetadata.title=Alterar Metadados
|
changeMetadata.title=Alterar metadados
|
||||||
changeMetadata.header=Alterar metadados
|
changeMetadata.header=Alterar metadados
|
||||||
changeMetadata.selectText.1=Edite as variáveis que deseja alterar
|
changeMetadata.selectText.1=Edite as variáveis que deseja alterar
|
||||||
changeMetadata.selectText.2=Excluir todos os metadados
|
changeMetadata.selectText.2=Excluir todos os metadados
|
||||||
@@ -1145,7 +1108,7 @@ split-by-size-or-count.submit=Enviar
|
|||||||
|
|
||||||
|
|
||||||
#overlay-pdfs
|
#overlay-pdfs
|
||||||
overlay-pdfs.header=Sobrepor Arquivos PDF
|
overlay-pdfs.header=Sobrepor arquivos PDF
|
||||||
overlay-pdfs.baseFile.label=Selecione o arquivo PDF base
|
overlay-pdfs.baseFile.label=Selecione o arquivo PDF base
|
||||||
overlay-pdfs.overlayFiles.label=Selecione os arquivos PDF para sobreposição
|
overlay-pdfs.overlayFiles.label=Selecione os arquivos PDF para sobreposição
|
||||||
overlay-pdfs.mode.label=Selecione o modo de sobreposição
|
overlay-pdfs.mode.label=Selecione o modo de sobreposição
|
||||||
@@ -1163,7 +1126,7 @@ overlay-pdfs.submit=Enviar
|
|||||||
#split-by-sections
|
#split-by-sections
|
||||||
split-by-sections.title=Dividir PDF por seções
|
split-by-sections.title=Dividir PDF por seções
|
||||||
split-by-sections.header=Divida o PDF em seções
|
split-by-sections.header=Divida o PDF em seções
|
||||||
split-by-sections.horizontal.label=Divisões Horizontais
|
split-by-sections.horizontal.label=Divisões horizontais
|
||||||
split-by-sections.vertical.label=Divisões Verticais
|
split-by-sections.vertical.label=Divisões Verticais
|
||||||
split-by-sections.horizontal.placeholder=Insira o número de divisões horizontais
|
split-by-sections.horizontal.placeholder=Insira o número de divisões horizontais
|
||||||
split-by-sections.vertical.placeholder=Insira o número de divisões verticais
|
split-by-sections.vertical.placeholder=Insira o número de divisões verticais
|
||||||
@@ -1181,8 +1144,8 @@ printFile.submit=Imprimir
|
|||||||
|
|
||||||
#licenses
|
#licenses
|
||||||
licenses.nav=Licenças
|
licenses.nav=Licenças
|
||||||
licenses.title=Licenças de Terceiros
|
licenses.title=Licenças de terceiros
|
||||||
licenses.header=Licenças de Terceiros
|
licenses.header=Licenças de terceiros
|
||||||
licenses.module=Módulo
|
licenses.module=Módulo
|
||||||
licenses.version=Versão
|
licenses.version=Versão
|
||||||
licenses.license=Licença
|
licenses.license=Licença
|
||||||
@@ -1191,10 +1154,8 @@ licenses.license=Licença
|
|||||||
survey.nav=Pesquisa
|
survey.nav=Pesquisa
|
||||||
survey.title=Pesquisa Stirling-PDF
|
survey.title=Pesquisa Stirling-PDF
|
||||||
survey.description=Stirling-PDF não tem rastreamento, então queremos ouvir nossos usuários para melhorar o Stirling-PDF!
|
survey.description=Stirling-PDF não tem rastreamento, então queremos ouvir nossos usuários para melhorar o Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF mudou desde o a última pesquisa! Para saber mais acesse nosso post no blog:
|
|
||||||
survey.changes2=Com essas mudanças estamos implementando suporte empresarial pago e financeamento
|
|
||||||
survey.please=Por favor, considere responder à nossa pesquisa!
|
survey.please=Por favor, considere responder à nossa pesquisa!
|
||||||
survey.disabled=(O pop-up da pesquisa será desativado nas atualizações seguintes, mas estará disponível no rodapé da página)
|
survey.disabled=(O pop-up da pesquisa será desativado nas atualizações seguintes, mas estará disponível no final da página)
|
||||||
survey.button=Responda a pesquisa
|
survey.button=Responda a pesquisa
|
||||||
survey.dontShowAgain=Não mostre novamente
|
survey.dontShowAgain=Não mostre novamente
|
||||||
|
|
||||||
@@ -1202,11 +1163,11 @@ survey.dontShowAgain=Não mostre novamente
|
|||||||
#error
|
#error
|
||||||
error.sorry=Desculpe pelo problema!
|
error.sorry=Desculpe pelo problema!
|
||||||
error.needHelp=Precisa de ajuda / Encontrou um problema?
|
error.needHelp=Precisa de ajuda / Encontrou um problema?
|
||||||
error.contactTip=Se você ainda estiver com problemas, não hesite em entrar em contato conosco para obter ajuda. Você pode enviar um tíquete em nossa página GitHub ou entrar em contato conosco através do Discord:
|
error.contactTip=Se você ainda estiver com problemas, não hesite em entrar em contato conosco para obter ajuda. Você pode enviar um ticket em nossa página GitHub ou entrar em contato conosco através do Discord:
|
||||||
error.404.head=404 - Página não encontrada | Ops, tropeçamos no código!
|
error.404.head=404 - Página não encontrada | Ops, tropeçamos no código!
|
||||||
error.404.1=Não conseguimos encontrar a página que você está procurando.
|
error.404.1=Não conseguimos encontrar a página que você está procurando.
|
||||||
error.404.2=Algo deu errado
|
error.404.2=Algo deu errado
|
||||||
error.github=Submeter um tíquete no GitHub
|
error.github=Submeter um ticket no GitHub
|
||||||
error.showStack=Mostrar rastreamento de pilha
|
error.showStack=Mostrar rastreamento de pilha
|
||||||
error.copyStack=Copiar rastreamento de pilha
|
error.copyStack=Copiar rastreamento de pilha
|
||||||
error.githubSubmit=GitHub - Submeter um tíquete
|
error.githubSubmit=GitHub - Submeter um tíquete
|
||||||
@@ -1214,19 +1175,7 @@ error.discordSubmit=Discord - Submeter um post de suporte
|
|||||||
|
|
||||||
|
|
||||||
#remove-image
|
#remove-image
|
||||||
removeImage.title=Remover Imagem
|
removeImage.title=Remover imagem
|
||||||
removeImage.header=Remover imagem
|
removeImage.header=Remover imagem
|
||||||
removeImage.removeImage=Remover imagem
|
removeImage.removeImage=Remover imagem
|
||||||
removeImage.submit=Remover imagem
|
removeImage.submit=Remover imagem
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Dividir PDF por Capítulos
|
|
||||||
splitByChapters.header=Dividir PDF por Capítulos
|
|
||||||
splitByChapters.bookmarkLevel=Nível de Marcador
|
|
||||||
splitByChapters.includeMetadata=Incluir Metadados
|
|
||||||
splitByChapters.allowDuplicates=Permitir Cópias
|
|
||||||
splitByChapters.desc.1=Essa ferramenta divide um arquivo PDF em vários arquivos PDFs baseado na estrutura de cápitulos.
|
|
||||||
splitByChapters.desc.2=Nível de Marcador: Escolha o nível de marcador a ser usado para divisão (0 para o primeiro nível, 1 para o segundo nível, etc).
|
|
||||||
splitByChapters.desc.3=Incluir Metadados: Se marcado, os metadados do PDF original serão incluidos em cada divisão do PDF.
|
|
||||||
splitByChapters.desc.4=Permitir Cópias: Se marcado, habilita vários marcadores na mesma página para criar PDFs separados.
|
|
||||||
splitByChapters.submit=Dividir PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Descarregar
|
pipelineOptions.saveButton=Descarregar
|
||||||
pipelineOptions.validateButton=Validar
|
pipelineOptions.validateButton=Validar
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Edição Automática
|
autoRedact.title=Edição Automática
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Books and Comics to PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Desenhar Assinatura
|
|||||||
sign.text=Inserir Texto
|
sign.text=Inserir Texto
|
||||||
sign.clear=Limpar
|
sign.clear=Limpar
|
||||||
sign.add=Adicionar
|
sign.add=Adicionar
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licença
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Donează
|
|||||||
color=Culoare
|
color=Culoare
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Informații
|
info=Informații
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Descarcă
|
pipelineOptions.saveButton=Descarcă
|
||||||
pipelineOptions.validateButton=Validează
|
pipelineOptions.validateButton=Validează
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convertește din PDF
|
|||||||
navbar.sections.security=Semnează & Securitate
|
navbar.sections.security=Semnează & Securitate
|
||||||
navbar.sections.advance=Avansat
|
navbar.sections.advance=Avansat
|
||||||
navbar.sections.edit=Vizualizează & Editează
|
navbar.sections.edit=Vizualizează & Editează
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=Fișierul nu a fost găsit
|
|||||||
database.fileNullOrEmpty=Fișierul nu trebuie să fie nul sau gol
|
database.fileNullOrEmpty=Fișierul nu trebuie să fie nul sau gol
|
||||||
database.failedImportFile=Importul Fișierului a Eșuat
|
database.failedImportFile=Importul Fișierului a Eșuat
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Elimină imagine
|
|||||||
home.removeImagePdf.desc=Elimină imaginea din PDF pentru a reduce dimensiunea fișierului
|
home.removeImagePdf.desc=Elimină imaginea din PDF pentru a reduce dimensiunea fișierului
|
||||||
removeImagePdf.tags=Elimină Imagine,Operații pagină,Back end,server side
|
removeImagePdf.tags=Elimină Imagine,Operații pagină,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Acces Refuzat
|
|||||||
login.oauth2InvalidTokenResponse=Răspuns Invalid la Token
|
login.oauth2InvalidTokenResponse=Răspuns Invalid la Token
|
||||||
login.oauth2InvalidIdToken=Token de Id Invalid
|
login.oauth2InvalidIdToken=Token de Id Invalid
|
||||||
login.userIsDisabled=Utilizatorul este dezactivat, conectarea este în prezent blocată cu acest nume de utilizator. Te rugăm să contactezi administratorul.
|
login.userIsDisabled=Utilizatorul este dezactivat, conectarea este în prezent blocată cu acest nume de utilizator. Te rugăm să contactezi administratorul.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redactare Automată
|
autoRedact.title=Redactare Automată
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Culoare Evidențiere 2:
|
|||||||
compare.document.1=Documentul 1
|
compare.document.1=Documentul 1
|
||||||
compare.document.2=Documentul 2
|
compare.document.2=Documentul 2
|
||||||
compare.submit=Compară
|
compare.submit=Compară
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Cărți și Benzi Desenate în PDF
|
BookToPDF.title=Cărți și Benzi Desenate în PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Desenează Semnătura
|
|||||||
sign.text=Introdu Textul
|
sign.text=Introdu Textul
|
||||||
sign.clear=Curăță
|
sign.clear=Curăță
|
||||||
sign.add=Adaugă
|
sign.add=Adaugă
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licență
|
|||||||
survey.nav=Sondaj
|
survey.nav=Sondaj
|
||||||
survey.title=Sondaj Stirling-PDF
|
survey.title=Sondaj Stirling-PDF
|
||||||
survey.description=Stirling-PDF nu are urmărire, așa că vrem să auzim de la utilizatorii noștri pentru a îmbunătăți Stirling-PDF!
|
survey.description=Stirling-PDF nu are urmărire, așa că vrem să auzim de la utilizatorii noștri pentru a îmbunătăți Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Te rugăm să iei în considerare completarea sondajului nostru!
|
survey.please=Te rugăm să iei în considerare completarea sondajului nostru!
|
||||||
survey.disabled=(Fereastra pop-up a sondajului va fi dezactivată în următoarele actualizări, dar va fi disponibilă în subsolul paginii)
|
survey.disabled=(Fereastra pop-up a sondajului va fi dezactivată în următoarele actualizări, dar va fi disponibilă în subsolul paginii)
|
||||||
survey.button=Completează Sondajul
|
survey.button=Completează Sondajul
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Elimină imagine
|
|||||||
removeImage.header=Elimină imagine
|
removeImage.header=Elimină imagine
|
||||||
removeImage.removeImage=Elimină imagine
|
removeImage.removeImage=Elimină imagine
|
||||||
removeImage.submit=Elimină imagine
|
removeImage.submit=Elimină imagine
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Пожертвовать
|
|||||||
color=Цвет
|
color=Цвет
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Конвейер:
|
|||||||
pipelineOptions.saveButton=Скачать
|
pipelineOptions.saveButton=Скачать
|
||||||
pipelineOptions.validateButton=Проверить
|
pipelineOptions.validateButton=Проверить
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматическое редактирование
|
autoRedact.title=Автоматическое редактирование
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Сравнить
|
compare.submit=Сравнить
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Книги и комиксы в PDF
|
BookToPDF.title=Книги и комиксы в PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Нарисовать подпись
|
|||||||
sign.text=Ввод текста
|
sign.text=Ввод текста
|
||||||
sign.clear=Очистить
|
sign.clear=Очистить
|
||||||
sign.add=Добавить
|
sign.add=Добавить
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Лицензия
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
@@ -76,11 +76,8 @@ donate=Darovať
|
|||||||
color=Farba
|
color=Farba
|
||||||
sponsor=Sponzorovať
|
sponsor=Sponzorovať
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
loading=Loading...
|
|
||||||
addToDoc=Add to Document
|
|
||||||
|
|
||||||
legal.privacy=Privacy Policy
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=Terms and Conditions
|
legal.terms=Terms and Conditions
|
||||||
@@ -113,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Stiahnuť
|
pipelineOptions.saveButton=Stiahnuť
|
||||||
pipelineOptions.validateButton=Overiť
|
pipelineOptions.validateButton=Overiť
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=Upgrade to Pro
|
|
||||||
enterpriseEdition.warning=This feature is only available to Pro users.
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF Pro supports YAML configuration files and other SSO features.
|
|
||||||
enterpriseEdition.ssoAdvert=Looking for more user management features? Check out Stirling PDF Pro
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=Do you want make Stirling PDF better?
|
|
||||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
|
||||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
|
||||||
analytics.enable=Enable analytics
|
|
||||||
analytics.disable=Disable analytics
|
|
||||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -147,7 +128,6 @@ navbar.sections.convertFrom=Convert from PDF
|
|||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Sign & Security
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Advanced
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=View & Edit
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -245,8 +225,6 @@ database.fileNotFound=File not Found
|
|||||||
database.fileNullOrEmpty=File must not be null or empty
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
database.failedImportFile=Failed Import File
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -504,11 +482,6 @@ home.removeImagePdf.title=Remove image
|
|||||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
|
||||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
|
||||||
|
|
||||||
#replace-invert-color
|
#replace-invert-color
|
||||||
replace-color.title=Replace-Invert-Color
|
replace-color.title=Replace-Invert-Color
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
@@ -553,9 +526,7 @@ login.oauth2AccessDenied=Access Denied
|
|||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
login.toManySessions=You have too many active sessions
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatické redigovanie
|
autoRedact.title=Automatické redigovanie
|
||||||
@@ -784,9 +755,6 @@ compare.highlightColor.2=Highlight Color 2:
|
|||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porovnať
|
compare.submit=Porovnať
|
||||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
|
||||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
|
||||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Knihy a komiksy do PDF
|
BookToPDF.title=Knihy a komiksy do PDF
|
||||||
@@ -809,11 +777,6 @@ sign.draw=Kresliť podpis
|
|||||||
sign.text=Textový vstup
|
sign.text=Textový vstup
|
||||||
sign.clear=Vymazať
|
sign.clear=Vymazať
|
||||||
sign.add=Pridať
|
sign.add=Pridať
|
||||||
sign.saved=Saved Signatures
|
|
||||||
sign.save=Save Signature
|
|
||||||
sign.personalSigs=Personal Signatures
|
|
||||||
sign.sharedSigs=Shared Signatures
|
|
||||||
sign.noSavedSigs=No saved signatures found
|
|
||||||
|
|
||||||
|
|
||||||
#repair
|
#repair
|
||||||
@@ -1191,8 +1154,6 @@ licenses.license=Licencia
|
|||||||
survey.nav=Survey
|
survey.nav=Survey
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Survey
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Please consider taking our survey!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
||||||
survey.button=Take Survey
|
survey.button=Take Survey
|
||||||
@@ -1218,15 +1179,3 @@ removeImage.title=Remove image
|
|||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|
||||||
|
|
||||||
splitByChapters.title=Split PDF by Chapters
|
|
||||||
splitByChapters.header=Split PDF by Chapters
|
|
||||||
splitByChapters.bookmarkLevel=Bookmark Level
|
|
||||||
splitByChapters.includeMetadata=Include Metadata
|
|
||||||
splitByChapters.allowDuplicates=Allow Duplicates
|
|
||||||
splitByChapters.desc.1=This tool splits a PDF file into multiple PDFs based on its chapter structure.
|
|
||||||
splitByChapters.desc.2=Bookmark Level: Choose the level of bookmarks to use for splitting (0 for top-level, 1 for second-level, etc.).
|
|
||||||
splitByChapters.desc.3=Include Metadata: If checked, the original PDF's metadata will be included in each split PDF.
|
|
||||||
splitByChapters.desc.4=Allow Duplicates: If checked, allows multiple bookmarks on the same page to create separate PDFs.
|
|
||||||
splitByChapters.submit=Split PDF
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user