Compare commits
22 Commits
autoPrintE
...
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 |
15
.github/workflows/build.yml
vendored
15
.github/workflows/build.yml
vendored
@@ -37,21 +37,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew build --no-build-cache
|
run: ./gradlew build --no-build-cache
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Upload JUnit test results
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: junit-test-results
|
|
||||||
path: '**/build/test-results/test/TEST-*.xml'
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
- name: Check for test failures
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
echo "Tests failed. Please check the JUnit test results artifact for details."
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
docker-compose-tests:
|
docker-compose-tests:
|
||||||
# if: github.event_name == 'push' && github.ref == 'refs/heads/main' ||
|
# if: github.event_name == 'push' && github.ref == 'refs/heads/main' ||
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -110,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.
|
|
||||||
68
README.md
68
README.md
@@ -172,42 +172,42 @@ 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.)
|
||||||
|
|
||||||
|
|||||||
24
build.gradle
24
build.gradle
@@ -16,13 +16,13 @@ ext {
|
|||||||
springBootVersion = "3.3.4"
|
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.30.0"
|
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/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,8 +134,6 @@ 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"
|
||||||
@@ -146,20 +146,12 @@ dependencies {
|
|||||||
//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"
|
||||||
@@ -201,7 +193,7 @@ 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.23.0"
|
implementation "org.commonmark:commonmark:0.23.0"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 0.30.0
|
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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,36 +1,25 @@
|
|||||||
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;
|
||||||
@@ -42,20 +31,13 @@ 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
|
||||||
@@ -66,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();
|
||||||
@@ -86,15 +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());
|
|
||||||
}
|
|
||||||
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||||
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
http.sessionManagement(
|
http.sessionManagement(
|
||||||
@@ -106,355 +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))
|
||||||
.invalidateHttpSession(true) // Invalidate session
|
.defaultSuccessUrl("/")
|
||||||
.deleteCookies("JSESSIONID", "remember-me"));
|
.failureHandler(
|
||||||
http.rememberMe(
|
new CustomAuthenticationFailureHandler(
|
||||||
rememberMeConfigurer ->
|
loginAttemptService, userService))
|
||||||
rememberMeConfigurer // Use the configurator directly
|
.permitAll())
|
||||||
.key("uniqueAndSecret")
|
.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()))
|
||||||
.tokenRepository(persistentTokenRepository())
|
.logout(
|
||||||
.tokenValiditySeconds(1209600) // 2 weeks
|
logout ->
|
||||||
);
|
logout.logoutRequestMatcher(
|
||||||
http.authorizeHttpRequests(
|
new AntPathRequestMatcher("/logout"))
|
||||||
authz ->
|
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
|
||||||
authz.requestMatchers(
|
.invalidateHttpSession(true) // Invalidate session
|
||||||
req -> {
|
.deleteCookies("JSESSIONID", "remember-me"))
|
||||||
String uri = req.getRequestURI();
|
.rememberMe(
|
||||||
String contextPath = req.getContextPath();
|
rememberMeConfigurer ->
|
||||||
|
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()) {
|
|
||||||
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());
|
||||||
}
|
|
||||||
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
|
|
||||||
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
|
||||||
@@ -473,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;
|
||||||
@@ -45,10 +44,6 @@ public class UserService implements UserServiceInterface {
|
|||||||
|
|
||||||
@Autowired DatabaseBackupInterface databaseBackupHelper;
|
@Autowired DatabaseBackupInterface databaseBackupHelper;
|
||||||
|
|
||||||
public long getTotalUserCount() {
|
|
||||||
return userRepository.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle OAUTH2 login and user auto creation.
|
// Handle OAUTH2 login and user auto creation.
|
||||||
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
|
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
|
||||||
throws IllegalArgumentException, IOException {
|
throws IllegalArgumentException, IOException {
|
||||||
@@ -339,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,48 +0,0 @@
|
|||||||
package stirling.software.SPDF.config.security.saml2;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
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 java.util.Base64;
|
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
|
|
||||||
public class CertificateUtils {
|
|
||||||
|
|
||||||
public static X509Certificate readCertificate(Resource certificateResource) throws Exception {
|
|
||||||
String certificateString =
|
|
||||||
new String(
|
|
||||||
FileCopyUtils.copyToByteArray(certificateResource.getInputStream()),
|
|
||||||
StandardCharsets.UTF_8);
|
|
||||||
String certContent =
|
|
||||||
certificateString
|
|
||||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
|
||||||
.replace("-----END CERTIFICATE-----", "")
|
|
||||||
.replaceAll("\\R", "")
|
|
||||||
.replaceAll("\\s+", "");
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
byte[] decodedCert = Base64.getDecoder().decode(certContent);
|
|
||||||
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception {
|
|
||||||
String privateKeyString =
|
|
||||||
new String(
|
|
||||||
FileCopyUtils.copyToByteArray(privateKeyResource.getInputStream()),
|
|
||||||
StandardCharsets.UTF_8);
|
|
||||||
String privateKeyContent =
|
|
||||||
privateKeyString
|
|
||||||
.replace("-----BEGIN PRIVATE KEY-----", "")
|
|
||||||
.replace("-----END PRIVATE KEY-----", "")
|
|
||||||
.replaceAll("\\R", "")
|
|
||||||
.replaceAll("\\s+", "");
|
|
||||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
|
||||||
byte[] decodedKey = Base64.getDecoder().decode(privateKeyContent);
|
|
||||||
return (RSAPrivateKey) kf.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 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -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,44 +51,27 @@ 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(
|
|
||||||
"/oauth2/authorization/" + google.getName(),
|
|
||||||
google.getClientName());
|
|
||||||
}
|
|
||||||
|
|
||||||
GithubProvider github = client.getGithub();
|
|
||||||
if (github.isSettingsValid()) {
|
|
||||||
providerList.put(
|
|
||||||
"/oauth2/authorization/" + github.getName(),
|
|
||||||
github.getClientName());
|
|
||||||
}
|
|
||||||
|
|
||||||
KeycloakProvider keycloak = client.getKeycloak();
|
|
||||||
if (keycloak.isSettingsValid()) {
|
|
||||||
providerList.put(
|
|
||||||
"/oauth2/authorization/" + keycloak.getName(),
|
|
||||||
keycloak.getClientName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
Client client = oauth.getClient();
|
||||||
|
if (client != null) {
|
||||||
|
GoogleProvider google = client.getGoogle();
|
||||||
|
if (google.isSettingsValid()) {
|
||||||
|
providerList.put(google.getName(), google.getClientName());
|
||||||
|
}
|
||||||
|
|
||||||
SAML2 saml2 = securityProps.getSaml2();
|
GithubProvider github = client.getGithub();
|
||||||
if (saml2 != null) {
|
if (github.isSettingsValid()) {
|
||||||
if (saml2.getEnabled()) {
|
providerList.put(github.getName(), github.getClientName());
|
||||||
providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2");
|
}
|
||||||
|
|
||||||
|
KeycloakProvider keycloak = client.getKeycloak();
|
||||||
|
if (keycloak.isSettingsValid()) {
|
||||||
|
providerList.put(keycloak.getName(), keycloak.getClientName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove any null keys/values from the providerList
|
// Remove any null keys/values from the providerList
|
||||||
@@ -100,8 +80,9 @@ public class AccountWebController {
|
|||||||
.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());
|
||||||
model.addAttribute("altLogin", securityProps.isAltLogin());
|
model.addAttribute(
|
||||||
|
"oAuth2Enabled", applicationProperties.getSecurity().getOauth2().getEnabled());
|
||||||
|
|
||||||
model.addAttribute("currentPage", "login");
|
model.addAttribute("currentPage", "login");
|
||||||
|
|
||||||
@@ -368,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 =
|
||||||
|
|||||||
@@ -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'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ donate=تبرع
|
|||||||
color=لون
|
color=لون
|
||||||
sponsor=راعٍ
|
sponsor=راعٍ
|
||||||
info=معلومات
|
info=معلومات
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=حجب تلقائي
|
autoRedact.title=حجب تلقائي
|
||||||
@@ -1182,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=المشاركة في الاستطلاع
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Направете дарение
|
|||||||
color=Цвят
|
color=Цвят
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Отказан достъп
|
|||||||
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
||||||
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматично редактиране
|
autoRedact.title=Автоматично редактиране
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
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
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ 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
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
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
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ 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
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Rediger
|
autoRedact.title=Auto Rediger
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Spenden
|
|||||||
color=Farbe
|
color=Farbe
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Informationen
|
info=Informationen
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Herunterladen
|
pipelineOptions.saveButton=Herunterladen
|
||||||
pipelineOptions.validateButton=Validieren
|
pipelineOptions.validateButton=Validieren
|
||||||
|
|
||||||
########################
|
|
||||||
# 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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,11 +482,6 @@ 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=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
|
||||||
@@ -551,10 +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=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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisch zensieren/schwärzen
|
autoRedact.title=Automatisch zensieren/schwärzen
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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=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,7 +76,6 @@ donate=Δωρισε
|
|||||||
color=Χρώμα
|
color=Χρώμα
|
||||||
sponsor=Yποστηρικτής
|
sponsor=Yποστηρικτής
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
|
autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
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
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donar
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Patrocinador
|
sponsor=Patrocinador
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Canalización:
|
|||||||
pipelineOptions.saveButton=Descargar
|
pipelineOptions.saveButton=Descargar
|
||||||
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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -502,11 +482,6 @@ 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=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
|
||||||
@@ -551,10 +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=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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Redactar
|
autoRedact.title=Auto Redactar
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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=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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Idatzi
|
autoRedact.title=Auto Idatzi
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ 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
|
||||||
|
|
||||||
@@ -111,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=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 #
|
||||||
@@ -145,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=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Accès refusé
|
|||||||
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
|
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
|
||||||
login.oauth2InvalidIdToken=Jeton d'identification invalide
|
login.oauth2InvalidIdToken=Jeton d'identification invalide
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Caviarder automatiquement
|
autoRedact.title=Caviarder automatiquement
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ 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
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
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
|
||||||
@@ -1182,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é
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=पृष्ठ
|
page=पृष्ठ
|
||||||
pages=पृष्ठों
|
pages=पृष्ठों
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=स्वत: गोपनीयकरण
|
autoRedact.title=स्वत: गोपनीयकरण
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Doniraj
|
|||||||
color=Boja
|
color=Boja
|
||||||
sponsor=Sponzor
|
sponsor=Sponzor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatsko uređivanje
|
autoRedact.title=Automatsko uređivanje
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Érzékeny tartalom eltávolítása
|
autoRedact.title=Érzékeny tartalom eltávolítása
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redaksional Otomatis
|
autoRedact.title=Redaksional Otomatis
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,9 +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
|
|
||||||
|
|
||||||
legal.privacy=Informativa sulla privacy
|
legal.privacy=Informativa sulla privacy
|
||||||
legal.terms=Termini e Condizioni
|
legal.terms=Termini e Condizioni
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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=Populare
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Si prega di uscire dai dispositivi e riprovare. In alternativa, è possibile effettuare l'upgrade a Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redazione automatica
|
autoRedact.title=Redazione automatica
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=寄付する
|
|||||||
color=色
|
color=色
|
||||||
sponsor=スポンサー
|
sponsor=スポンサー
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自動塗りつぶし
|
autoRedact.title=自動塗りつぶし
|
||||||
@@ -1182,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=アンケートに答える
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=기부하기
|
|||||||
color=색상
|
color=색상
|
||||||
sponsor=스폰서
|
sponsor=스폰서
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=자동 검열
|
autoRedact.title=자동 검열
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Doneer
|
|||||||
color=Kleur
|
color=Kleur
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisch censureren
|
autoRedact.title=Automatisch censureren
|
||||||
@@ -1182,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.
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Doner
|
|||||||
color=Farge
|
color=Farge
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatisk Sensurering
|
autoRedact.title=Automatisk Sensurering
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Podaruj
|
|||||||
color=kolor
|
color=kolor
|
||||||
sponsor=sponsor
|
sponsor=sponsor
|
||||||
info=informacje
|
info=informacje
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Automatyzacja
|
|||||||
pipelineOptions.saveButton=Pobierz
|
pipelineOptions.saveButton=Pobierz
|
||||||
pipelineOptions.validateButton=Waliduj
|
pipelineOptions.validateButton=Waliduj
|
||||||
|
|
||||||
########################
|
|
||||||
# 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 #
|
||||||
@@ -145,7 +128,6 @@ navbar.sections.convertFrom=Przetwórz z PDF
|
|||||||
navbar.sections.security=Podpis i bezpieczeństwo
|
navbar.sections.security=Podpis i bezpieczeństwo
|
||||||
navbar.sections.advance=Zaawansowane
|
navbar.sections.advance=Zaawansowane
|
||||||
navbar.sections.edit=Podgląd i edycja
|
navbar.sections.edit=Podgląd i edycja
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,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=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Brak dostępu
|
|||||||
login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token
|
login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token
|
||||||
login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu
|
login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatyczne zaciemnienie
|
autoRedact.title=Automatyczne zaciemnienie
|
||||||
@@ -1182,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 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=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ę
|
||||||
@@ -1209,17 +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,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,30 +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
|
|
||||||
|
|
||||||
legal.privacy=Política de Privacidade
|
legal.privacy=Política de Privacidade
|
||||||
legal.terms=Termos e Condições
|
legal.terms=Termos e Condições
|
||||||
@@ -90,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
|
||||||
@@ -103,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -162,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
|
||||||
@@ -235,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 #
|
||||||
#############
|
#############
|
||||||
@@ -257,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
|
||||||
@@ -269,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
|
||||||
|
|
||||||
|
|
||||||
@@ -287,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
|
||||||
@@ -303,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.
|
||||||
@@ -339,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)
|
||||||
@@ -355,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
|
||||||
@@ -378,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
|
||||||
|
|
||||||
@@ -426,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
|
||||||
|
|
||||||
@@ -468,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
|
||||||
|
|
||||||
|
|
||||||
@@ -481,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
|
||||||
@@ -495,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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -541,24 +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
|
|
||||||
login.toManySessions2=Por favor saida dos aparelhos e tente novamente. Alternativamente você pode adquirir Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redação Automática de Dados
|
autoRedact.title=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
|
||||||
@@ -644,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
|
||||||
@@ -739,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):
|
||||||
@@ -753,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
|
||||||
@@ -765,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
|
||||||
|
|
||||||
|
|
||||||
@@ -837,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
|
||||||
@@ -884,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
|
||||||
@@ -893,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?
|
||||||
@@ -907,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
|
||||||
@@ -972,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
|
||||||
@@ -981,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.
|
||||||
|
|
||||||
@@ -992,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
|
||||||
@@ -1009,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
|
||||||
@@ -1044,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
|
||||||
@@ -1052,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
|
||||||
@@ -1136,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
|
||||||
@@ -1154,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
|
||||||
@@ -1172,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
|
||||||
@@ -1182,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
|
||||||
|
|
||||||
@@ -1193,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
|
||||||
@@ -1205,21 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Edição Automática
|
autoRedact.title=Edição Automática
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ 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
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Redactare Automată
|
autoRedact.title=Redactare Automată
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Пожертвовать
|
|||||||
color=Цвет
|
color=Цвет
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматическое редактирование
|
autoRedact.title=Автоматическое редактирование
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Darovať
|
|||||||
color=Farba
|
color=Farba
|
||||||
sponsor=Sponzorovať
|
sponsor=Sponzorovať
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Automatické redigovanie
|
autoRedact.title=Automatické redigovanie
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Preuzmi
|
pipelineOptions.saveButton=Preuzmi
|
||||||
pipelineOptions.validateButton=Proveri
|
pipelineOptions.validateButton=Proveri
|
||||||
|
|
||||||
########################
|
|
||||||
# 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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Auto Cenzura
|
autoRedact.title=Auto Cenzura
|
||||||
@@ -1182,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
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Donera
|
|||||||
color=Färg
|
color=Färg
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Ladda ner
|
pipelineOptions.saveButton=Ladda ner
|
||||||
pipelineOptions.validateButton=Validera
|
pipelineOptions.validateButton=Validera
|
||||||
|
|
||||||
########################
|
|
||||||
# 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 #
|
||||||
@@ -145,7 +128,6 @@ navbar.sections.convertFrom=Konvertera från PDF
|
|||||||
navbar.sections.security=Signera & Säkerhet
|
navbar.sections.security=Signera & Säkerhet
|
||||||
navbar.sections.advance=Avancerat
|
navbar.sections.advance=Avancerat
|
||||||
navbar.sections.edit=Visa & Redigera
|
navbar.sections.edit=Visa & Redigera
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,8 +225,6 @@ database.fileNotFound=Filen hittades inte
|
|||||||
database.fileNullOrEmpty=Filen får inte vara null eller tom
|
database.fileNullOrEmpty=Filen får inte vara null eller tom
|
||||||
database.failedImportFile=Misslyckades med att importera fil
|
database.failedImportFile=Misslyckades med att importera fil
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -502,11 +482,6 @@ home.removeImagePdf.title=Ta bort bild
|
|||||||
home.removeImagePdf.desc=Ta bort bild från PDF för att minska filstorlek
|
home.removeImagePdf.desc=Ta bort bild från PDF för att minska filstorlek
|
||||||
removeImagePdf.tags=Ta bort bild,Sidoperationer,Backend,serversida
|
removeImagePdf.tags=Ta bort bild,Sidoperationer,Backend,serversida
|
||||||
|
|
||||||
|
|
||||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
|
||||||
home.splitPdfByChapters.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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Åtkomst nekad
|
|||||||
login.oauth2InvalidTokenResponse=Ogiltigt token-svar
|
login.oauth2InvalidTokenResponse=Ogiltigt token-svar
|
||||||
login.oauth2InvalidIdToken=Ogiltigt Id-token
|
login.oauth2InvalidIdToken=Ogiltigt Id-token
|
||||||
login.userIsDisabled=Användaren är inaktiverad, inloggning är för närvarande blockerad med detta användarnamn. Kontakta administratören.
|
login.userIsDisabled=Användaren är inaktiverad, inloggning är för närvarande blockerad med detta användarnamn. Kontakta administratören.
|
||||||
login.alreadyLoggedIn=You are already logged in to
|
|
||||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
|
||||||
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-redigera
|
autoRedact.title=Auto-redigera
|
||||||
@@ -1182,8 +1154,6 @@ licenses.license=Licens
|
|||||||
survey.nav=Undersökning
|
survey.nav=Undersökning
|
||||||
survey.title=Stirling-PDF-undersökning
|
survey.title=Stirling-PDF-undersökning
|
||||||
survey.description=Stirling-PDF har ingen spårning så vi vill höra från våra användare för att förbättra Stirling-PDF!
|
survey.description=Stirling-PDF har ingen spårning så vi vill höra från våra användare för att förbättra Stirling-PDF!
|
||||||
survey.changes=Stirling-PDF has changed since the last survey! To find out more please check our blog post here:
|
|
||||||
survey.changes2=With these changes we are getting paid business support and funding
|
|
||||||
survey.please=Vänligen överväg att delta i vår undersökning!
|
survey.please=Vänligen överväg att delta i vår undersökning!
|
||||||
survey.disabled=(Undersökningspopup kommer att inaktiveras i kommande uppdateringar men finns tillgänglig längst ner på sidan)
|
survey.disabled=(Undersökningspopup kommer att inaktiveras i kommande uppdateringar men finns tillgänglig längst ner på sidan)
|
||||||
survey.button=Delta i undersökningen
|
survey.button=Delta i undersökningen
|
||||||
@@ -1209,17 +1179,3 @@ removeImage.title=Ta bort bild
|
|||||||
removeImage.header=Ta bort bild
|
removeImage.header=Ta bort bild
|
||||||
removeImage.removeImage=Ta bort bild
|
removeImage.removeImage=Ta bort bild
|
||||||
removeImage.submit=Ta bort bild
|
removeImage.submit=Ta bort bild
|
||||||
|
|
||||||
|
|
||||||
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,7 +76,6 @@ donate=บริจาค
|
|||||||
color=สี
|
color=สี
|
||||||
sponsor=ผู้สนับสนุน
|
sponsor=ผู้สนับสนุน
|
||||||
info=ข้อมูล
|
info=ข้อมูล
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=การเข้าถึงถูกปฏิเส
|
|||||||
login.oauth2InvalidTokenResponse=การตอบกลับโทเค็นไม่ถูกต้อง
|
login.oauth2InvalidTokenResponse=การตอบกลับโทเค็นไม่ถูกต้อง
|
||||||
login.oauth2InvalidIdToken=โทเค็น Id ไม่ถูกต้อง
|
login.oauth2InvalidIdToken=โทเค็น Id ไม่ถูกต้อง
|
||||||
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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=ซ่อนข้อมูลอัตโนมัติ
|
autoRedact.title=ซ่อนข้อมูลอัตโนมัติ
|
||||||
@@ -1182,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=เริ่มสำรวจ
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Bağış Yapın
|
|||||||
color=Renk
|
color=Renk
|
||||||
sponsor=Bağış
|
sponsor=Bağış
|
||||||
info=Bilgi
|
info=Bilgi
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Çoklu İşlemler:
|
|||||||
pipelineOptions.saveButton=İndir
|
pipelineOptions.saveButton=İndir
|
||||||
pipelineOptions.validateButton=Doğrula
|
pipelineOptions.validateButton=Doğrula
|
||||||
|
|
||||||
########################
|
|
||||||
# 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 #
|
||||||
@@ -145,7 +128,6 @@ navbar.sections.convertFrom=PDF'den dönüştür
|
|||||||
navbar.sections.security=Oturum ve Güvenlik
|
navbar.sections.security=Oturum ve Güvenlik
|
||||||
navbar.sections.advance=Gelişmiş
|
navbar.sections.advance=Gelişmiş
|
||||||
navbar.sections.edit=Görüntüle ve Düzenle
|
navbar.sections.edit=Görüntüle ve Düzenle
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,8 +225,6 @@ database.fileNotFound=Dosya bulunamadı
|
|||||||
database.fileNullOrEmpty=Dosya yok veya boş olmamalıdır
|
database.fileNullOrEmpty=Dosya yok veya boş olmamalıdır
|
||||||
database.failedImportFile=Dosya İçe Aktarılamadı
|
database.failedImportFile=Dosya İçe Aktarılamadı
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -502,11 +482,6 @@ home.removeImagePdf.title=Resmi kaldır
|
|||||||
home.removeImagePdf.desc=Dosya boyutunu küçültmek için PDF'den resmi kaldırın
|
home.removeImagePdf.desc=Dosya boyutunu küçültmek için PDF'den resmi kaldırın
|
||||||
removeImagePdf.tags=Resmi Kaldır,Sayfa İşlemleri,Arka uç,sunucu tarafı
|
removeImagePdf.tags=Resmi Kaldır,Sayfa İşlemleri,Arka uç,sunucu tarafı
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Erişim Reddedildi
|
|||||||
login.oauth2InvalidTokenResponse=Geçersiz Belirteç Yanıtı
|
login.oauth2InvalidTokenResponse=Geçersiz Belirteç Yanıtı
|
||||||
login.oauth2InvalidIdToken=Geçersiz Kimlik Belirteci
|
login.oauth2InvalidIdToken=Geçersiz Kimlik Belirteci
|
||||||
login.userIsDisabled=Kullanıcı devre dışı bırakıldı, şu anda bu kullanıcı adıyla giriş engellendi. Lütfen yöneticiyle iletişime geçin.
|
login.userIsDisabled=Kullanıcı devre dışı bırakıldı, şu anda bu kullanıcı adıyla giriş engellendi. Lütfen yöneticiyle iletişime geçin.
|
||||||
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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Otomatik Karartma
|
autoRedact.title=Otomatik Karartma
|
||||||
@@ -1182,8 +1154,6 @@ licenses.license=Lisans
|
|||||||
survey.nav=Anket
|
survey.nav=Anket
|
||||||
survey.title=Stirling-PDF Anketi
|
survey.title=Stirling-PDF Anketi
|
||||||
survey.description=Stirling-PDF'te izleme yok, bu yüzden Stirling-PDF'i iyileştirmek için kullanıcılarımızdan geri bildirim almak istiyoruz!
|
survey.description=Stirling-PDF'te izleme yok, bu yüzden Stirling-PDF'i iyileştirmek için kullanıcılarımızdan geri bildirim almak istiyoruz!
|
||||||
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=Lütfen anketimize katılmayı düşünün!
|
survey.please=Lütfen anketimize katılmayı düşünün!
|
||||||
survey.disabled=(Anket açılır penceresi sonraki güncellemelerde devre dışı bırakılacak ancak sayfanın alt kısmında yer alacaktır)
|
survey.disabled=(Anket açılır penceresi sonraki güncellemelerde devre dışı bırakılacak ancak sayfanın alt kısmında yer alacaktır)
|
||||||
survey.button=Ankete Katıl
|
survey.button=Ankete Katıl
|
||||||
@@ -1209,17 +1179,3 @@ removeImage.title=Resmi kaldır
|
|||||||
removeImage.header=Resmi kaldır
|
removeImage.header=Resmi kaldır
|
||||||
removeImage.removeImage=Resmi kaldır
|
removeImage.removeImage=Resmi kaldır
|
||||||
removeImage.submit=Resmi kaldır
|
removeImage.submit=Resmi kaldır
|
||||||
|
|
||||||
|
|
||||||
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,7 +76,6 @@ donate=Задонатити
|
|||||||
color=Колір
|
color=Колір
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Інформація
|
info=Інформація
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,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 #
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Доступ заблоковано
|
|||||||
login.oauth2InvalidTokenResponse=Недійсна відповідь з токеном
|
login.oauth2InvalidTokenResponse=Недійсна відповідь з токеном
|
||||||
login.oauth2InvalidIdToken=Недійсний Id токен
|
login.oauth2InvalidIdToken=Недійсний Id токен
|
||||||
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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Автоматичне редагування
|
autoRedact.title=Автоматичне редагування
|
||||||
@@ -1182,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=Пройти опитування
|
||||||
@@ -1209,17 +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,7 +76,6 @@ donate=Ủng hộ
|
|||||||
color=Màu sắc
|
color=Màu sắc
|
||||||
sponsor=Nhà tài trợ
|
sponsor=Nhà tài trợ
|
||||||
info=Thông tin
|
info=Thông tin
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,24 +110,8 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Tải xuống
|
pipelineOptions.saveButton=Tải xuống
|
||||||
pipelineOptions.validateButton=Xác thực
|
pipelineOptions.validateButton=Xác thực
|
||||||
|
|
||||||
########################
|
|
||||||
# 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 #
|
||||||
@@ -145,7 +128,6 @@ navbar.sections.convertFrom=Chuyển đổi từ PDF
|
|||||||
navbar.sections.security=Ký & Bảo mật
|
navbar.sections.security=Ký & Bảo mật
|
||||||
navbar.sections.advance=Nâng cao
|
navbar.sections.advance=Nâng cao
|
||||||
navbar.sections.edit=Xem & Chỉnh sửa
|
navbar.sections.edit=Xem & Chỉnh sửa
|
||||||
navbar.sections.popular=Popular
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@@ -243,8 +225,6 @@ database.fileNotFound=Không tìm thấy tệp
|
|||||||
database.fileNullOrEmpty=Tệp không được để trống hoặc rỗng
|
database.fileNullOrEmpty=Tệp không được để trống hoặc rỗng
|
||||||
database.failedImportFile=Không thể nhập tệp
|
database.failedImportFile=Không thể nhập tệp
|
||||||
|
|
||||||
session.expired=Your session has expired. Please refresh the page and try again.
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=Truy cập bị từ chối
|
|||||||
login.oauth2InvalidTokenResponse=Phản hồi token không hợp lệ
|
login.oauth2InvalidTokenResponse=Phản hồi token không hợp lệ
|
||||||
login.oauth2InvalidIdToken=Id Token không hợp lệ
|
login.oauth2InvalidIdToken=Id Token không hợp lệ
|
||||||
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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=Tự động biên tập
|
autoRedact.title=Tự động biên tập
|
||||||
@@ -1182,8 +1154,6 @@ licenses.license=Giấy phép
|
|||||||
survey.nav=Khảo sát
|
survey.nav=Khảo sát
|
||||||
survey.title=Khảo sát Stirling-PDF
|
survey.title=Khảo sát Stirling-PDF
|
||||||
survey.description=Stirling-PDF không có cài đặt theo dõi nên chúng tôi muốn nghe từ người dùng để cải thiện Stirling-PDF!
|
survey.description=Stirling-PDF không có cài đặt theo dõi nên chúng tôi muốn nghe từ người dùng để cải thiện 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=Vui lòng cân nhắc tham gia khảo sát của chúng tôi!
|
survey.please=Vui lòng cân nhắc tham gia khảo sát của chúng tôi!
|
||||||
survey.disabled=(Cửa sổ popup khảo sát sẽ bị vô hiệu hóa trong các bản cập nhật tiếp theo nhưng vẫn tìm thấy ở cuối trang)
|
survey.disabled=(Cửa sổ popup khảo sát sẽ bị vô hiệu hóa trong các bản cập nhật tiếp theo nhưng vẫn tìm thấy ở cuối trang)
|
||||||
survey.button=Tham gia khảo sát
|
survey.button=Tham gia khảo sát
|
||||||
@@ -1209,17 +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
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ green=绿色
|
|||||||
blue=蓝色
|
blue=蓝色
|
||||||
custom=自定义...
|
custom=自定义...
|
||||||
WorkInProgess=工作正在进行中,可能无法工作或有错误,请报告任何问题!
|
WorkInProgess=工作正在进行中,可能无法工作或有错误,请报告任何问题!
|
||||||
poweredBy=服务来源:
|
poweredBy=Powered by
|
||||||
yes=是
|
yes=是
|
||||||
no=否
|
no=否
|
||||||
changedCredsMessage=凭证已更改!
|
changedCredsMessage=凭证已更改!
|
||||||
@@ -76,7 +76,6 @@ donate=捐款
|
|||||||
color=颜色
|
color=颜色
|
||||||
sponsor=赞助
|
sponsor=赞助
|
||||||
info=信息
|
info=信息
|
||||||
pro=Pro
|
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@@ -111,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 #
|
||||||
@@ -145,13 +128,12 @@ 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 #
|
||||||
#############
|
#############
|
||||||
settings.title=设置
|
settings.title=设置
|
||||||
settings.update=有可用的更新
|
settings.update=可更新
|
||||||
settings.updateAvailable=当前版本为 {0},新版本 ({1}) 可用。
|
settings.updateAvailable=当前版本为 {0},新版本 ({1}) 可用。
|
||||||
settings.appVersion=应用程序版本:
|
settings.appVersion=应用程序版本:
|
||||||
settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
|
settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
|
||||||
@@ -243,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 #
|
||||||
#############
|
#############
|
||||||
@@ -502,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
|
||||||
@@ -551,10 +526,7 @@ login.oauth2AccessDenied=拒绝访问
|
|||||||
login.oauth2InvalidTokenResponse=无效的Token响应
|
login.oauth2InvalidTokenResponse=无效的Token响应
|
||||||
login.oauth2InvalidIdToken=无效的Token
|
login.oauth2InvalidIdToken=无效的Token
|
||||||
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
|
|
||||||
login.toManySessions2=Please log out of the devices and try again. Alternatively, you can upgrade to Stirling PDF Pro.
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自动删除
|
autoRedact.title=自动删除
|
||||||
@@ -1182,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=参与调查
|
||||||
@@ -1209,17 +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 檔案
|
multiPdfPrompt=選擇多個 PDF 檔案
|
||||||
multiPdfDropPrompt=選擇(或拖放)所有需要的 PDF 檔案
|
multiPdfDropPrompt=選擇(或拖放)所有需要的 PDF 檔案
|
||||||
@@ -12,7 +12,7 @@ imgPrompt=選擇圖片
|
|||||||
genericSubmit=送出
|
genericSubmit=送出
|
||||||
processTimeWarning=警告:此過程可能長達一分鐘,具體取決於檔案大小
|
processTimeWarning=警告:此過程可能長達一分鐘,具體取決於檔案大小
|
||||||
pageOrderPrompt=自訂頁面順序(輸入以逗號分隔的頁碼或函式,如 2n+1):
|
pageOrderPrompt=自訂頁面順序(輸入以逗號分隔的頁碼或函式,如 2n+1):
|
||||||
pageSelectionPrompt=自訂頁面選擇(輸入以逗號分隔的頁碼 1、5、6 或 2n+1 等函式的清單):
|
pageSelectionPrompt=自訂頁面選擇(輸入以逗號分隔的頁碼 1、5、6 或 2n+1 等函數的清單):
|
||||||
goToPage=前往
|
goToPage=前往
|
||||||
true=是
|
true=是
|
||||||
false=否
|
false=否
|
||||||
@@ -51,84 +51,67 @@ poweredBy=Powered by
|
|||||||
yes=是
|
yes=是
|
||||||
no=否
|
no=否
|
||||||
changedCredsMessage=憑證已變更!
|
changedCredsMessage=憑證已變更!
|
||||||
notAuthenticatedMessage=使用者未通過驗證。
|
notAuthenticatedMessage=使用者未認證。
|
||||||
userNotFoundMessage=找不到使用者。
|
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=輸入的密碼必需和確認密碼相同。
|
||||||
deleteCurrentUserMessage=無法刪除目前登入的使用者。
|
deleteCurrentUserMessage=無法刪除目前登錄的使用者。
|
||||||
deleteUsernameExistsMessage=使用者名稱不存在,無法刪除。
|
deleteUsernameExistsMessage=使用者名不存在,無法刪除。
|
||||||
downgradeCurrentUserMessage=無法降級目前使用者的角色
|
downgradeCurrentUserMessage=無法降級目前使用者的角色
|
||||||
disabledCurrentUserMessage=無法停用目前使用者
|
disabledCurrentUserMessage=The current user cannot be disabled
|
||||||
downgradeCurrentUserLongMessage=無法降級目前使用者的角色。因此,將不會顯示目前使用者。
|
downgradeCurrentUserLongMessage=無法降級目前使用者的角色。因此,不會顯示目前的使用者。
|
||||||
userAlreadyExistsOAuthMessage=使用者已經以 OAuth2 使用者身份存在。
|
userAlreadyExistsOAuthMessage=該使用者已於 OAuth2 註冊。
|
||||||
userAlreadyExistsWebMessage=使用者已經以網頁使用者身份存在。
|
userAlreadyExistsWebMessage=該使用者已於網頁註冊。
|
||||||
error=錯誤
|
error=錯誤
|
||||||
oops=哎呀!
|
oops=哎呀!
|
||||||
help=說明
|
help=幫助
|
||||||
goHomepage=前往首頁
|
goHomepage=前往首頁
|
||||||
joinDiscord=加入我們的 Discord 伺服器
|
joinDiscord=加入我們的 Discord 伺服器
|
||||||
seeDockerHub=造訪 Docker Hub 儲存庫
|
seeDockerHub=查看 Docker Hub
|
||||||
visitGithub=造訪 GitHub 專案
|
visitGithub=訪問 GitHub 存儲庫
|
||||||
donate=捐款
|
donate=捐贈
|
||||||
color=顏色
|
color=顏色
|
||||||
sponsor=贊助
|
sponsor=贊助
|
||||||
info=資訊
|
info=Info
|
||||||
pro=專業版
|
page=Page
|
||||||
page=頁面
|
pages=Pages
|
||||||
pages=頁面
|
|
||||||
|
|
||||||
legal.privacy=隱私權政策
|
legal.privacy=Privacy Policy
|
||||||
legal.terms=使用條款
|
legal.terms=Terms and Conditions
|
||||||
legal.accessibility=無障礙性聲明
|
legal.accessibility=Accessibility
|
||||||
legal.cookie=Cookie 政策
|
legal.cookie=Cookie Policy
|
||||||
legal.impressum=版本說明
|
legal.impressum=Impressum
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=管道功能選單(測試版)
|
pipeline.header=管道選單(測試版)
|
||||||
pipeline.uploadButton=上傳自訂
|
pipeline.uploadButton=上傳自定義
|
||||||
pipeline.configureButton=設定
|
pipeline.configureButton=配置
|
||||||
pipeline.defaultOption=自訂
|
pipeline.defaultOption=自訂
|
||||||
pipeline.submitButton=送出
|
pipeline.submitButton=送出
|
||||||
pipeline.help=管道功能說明
|
pipeline.help=管道説明
|
||||||
pipeline.scanHelp=資料夾掃描說明
|
pipeline.scanHelp=資料夾掃描説明
|
||||||
pipeline.deletePrompt=您確定要刪除此管道嗎?
|
pipeline.deletePrompt=確定刪除該管道?
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
######################
|
######################
|
||||||
pipelineOptions.header=管道設定
|
pipelineOptions.header=管道配置
|
||||||
pipelineOptions.pipelineNameLabel=管道名稱
|
pipelineOptions.pipelineNameLabel=管道名稱
|
||||||
pipelineOptions.saveSettings=儲存操作設定
|
pipelineOptions.saveSettings=保存操作設置
|
||||||
pipelineOptions.pipelineNamePrompt=請在此輸入管道名稱
|
pipelineOptions.pipelineNamePrompt=在此處輸入管道名稱
|
||||||
pipelineOptions.selectOperation=選擇操作
|
pipelineOptions.selectOperation=選擇操作
|
||||||
pipelineOptions.addOperationButton=新增操作
|
pipelineOptions.addOperationButton=添加操作
|
||||||
pipelineOptions.pipelineHeader=管道:
|
pipelineOptions.pipelineHeader=管道:
|
||||||
pipelineOptions.saveButton=下載
|
pipelineOptions.saveButton=下載
|
||||||
pipelineOptions.validateButton=驗證
|
pipelineOptions.validateButton=驗證
|
||||||
|
|
||||||
########################
|
|
||||||
# ENTERPRISE EDITION #
|
|
||||||
########################
|
|
||||||
enterpriseEdition.button=升級至專業版
|
|
||||||
enterpriseEdition.warning=此功能僅提供給專業版使用者使用。
|
|
||||||
enterpriseEdition.yamlAdvert=Stirling PDF 專業版支援 YAML 設定檔和其他單一登入 (SSO) 功能。
|
|
||||||
enterpriseEdition.ssoAdvert=需要更多使用者管理功能嗎?請參考 Stirling PDF 專業版
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Analytics #
|
|
||||||
#################
|
|
||||||
analytics.title=您想協助改善 Stirling PDF 嗎?
|
|
||||||
analytics.paragraph1=Stirling PDF 有選擇性的分析功能,可幫助我們改進產品。我們不會追蹤任何個人資訊或檔案內容。
|
|
||||||
analytics.paragraph2=請考慮啟用分析功能,以協助 Stirling-PDF 成長並讓我們更了解使用者需求。
|
|
||||||
analytics.enable=啟用分析功能
|
|
||||||
analytics.disable=停用分析功能
|
|
||||||
analytics.settings=您可以在 config/settings.yml 檔案中變更分析功能的設定
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
@@ -138,36 +121,35 @@ navbar.darkmode=深色模式
|
|||||||
navbar.language=語言
|
navbar.language=語言
|
||||||
navbar.settings=設定
|
navbar.settings=設定
|
||||||
navbar.allTools=工具
|
navbar.allTools=工具
|
||||||
navbar.multiTool=多功能工具
|
navbar.multiTool=萬用工具
|
||||||
navbar.sections.organize=整理
|
navbar.sections.organize=組織
|
||||||
navbar.sections.convertTo=轉換為 PDF
|
navbar.sections.convertTo=轉換為 PDF
|
||||||
navbar.sections.convertFrom=從 PDF 轉換
|
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 #
|
||||||
#############
|
#############
|
||||||
settings.title=設定
|
settings.title=設定
|
||||||
settings.update=有更新可用
|
settings.update=有更新可用
|
||||||
settings.updateAvailable=目前安裝的版本是 {0}。有新版本({1})可供使用。
|
settings.updateAvailable=當前版本為 {0}。歡迎你更新至最新版 ({1})。。
|
||||||
settings.appVersion=應用程式版本:
|
settings.appVersion=應用版本:
|
||||||
settings.downloadOption.title=選擇下載選項(適用於單一檔案非壓縮下載):
|
settings.downloadOption.title=選擇下載選項(對於單一檔案非壓縮下載):
|
||||||
settings.downloadOption.1=在同一視窗中開啟
|
settings.downloadOption.1=在同一視窗中開啟
|
||||||
settings.downloadOption.2=在新視窗中開啟
|
settings.downloadOption.2=在新視窗中開啟
|
||||||
settings.downloadOption.3=下載檔案
|
settings.downloadOption.3=下載檔案
|
||||||
settings.zipThreshold=當下載檔案數量超過此數值時,將檔案壓縮
|
settings.zipThreshold=當下載的檔案數量超過時,壓縮檔案
|
||||||
settings.signOut=登出
|
settings.signOut=登出
|
||||||
settings.accountSettings=帳號設定
|
settings.accountSettings=帳戶設定
|
||||||
settings.bored.help=啟用彩蛋遊戲
|
settings.bored.help=啟用彩蛋
|
||||||
settings.cacheInputs.name=儲存表單輸入
|
settings.cacheInputs.name=輸入檔案下載
|
||||||
settings.cacheInputs.help=啟用此功能以儲存先前使用的輸入,以便日後使用
|
settings.cacheInputs.help=開啟記住先前的輸入,做為日後使用
|
||||||
|
|
||||||
changeCreds.title=變更憑證
|
changeCreds.title=變更憑證
|
||||||
changeCreds.header=更新您的帳號詳細資訊
|
changeCreds.header=更新你的帳戶詳細資訊
|
||||||
changeCreds.changePassword=您正在使用預設登入憑證。請輸入新密碼
|
changeCreds.changePassword=你使用的是預設登錄認證。請輸入新密碼
|
||||||
changeCreds.newUsername=新使用者名稱
|
changeCreds.newUsername=新使用者名稱
|
||||||
changeCreds.oldPassword=目前密碼
|
changeCreds.oldPassword=目前密碼
|
||||||
changeCreds.newPassword=新密碼
|
changeCreds.newPassword=新密碼
|
||||||
@@ -176,9 +158,9 @@ changeCreds.submit=送出變更
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
account.title=帳號設定
|
account.title=帳戶設定
|
||||||
account.accountSettings=帳號設定
|
account.accountSettings=帳戶設定
|
||||||
account.adminSettings=管理員設定 - 檢視和新增使用者
|
account.adminSettings=管理設定 - 檢視和新增使用者
|
||||||
account.userControlSettings=使用者控制設定
|
account.userControlSettings=使用者控制設定
|
||||||
account.changeUsername=修改使用者名稱
|
account.changeUsername=修改使用者名稱
|
||||||
account.newUsername=新使用者名稱
|
account.newUsername=新使用者名稱
|
||||||
@@ -188,43 +170,43 @@ account.newPassword=新密碼
|
|||||||
account.changePassword=修改密碼
|
account.changePassword=修改密碼
|
||||||
account.confirmNewPassword=確認新密碼
|
account.confirmNewPassword=確認新密碼
|
||||||
account.signOut=登出
|
account.signOut=登出
|
||||||
account.yourApiKey=您的 API 金鑰
|
account.yourApiKey=你的 API 金鑰
|
||||||
account.syncTitle=將瀏覽器設定與帳號同步
|
account.syncTitle=將瀏覽器設定與帳戶同步
|
||||||
account.settingsCompare=設定比較:
|
account.settingsCompare=設定比較:
|
||||||
account.property=屬性
|
account.property=屬性
|
||||||
account.webBrowserSettings=網頁瀏覽器設定
|
account.webBrowserSettings=網頁瀏覽器設定
|
||||||
account.syncToBrowser=同步帳號 → 瀏覽器
|
account.syncToBrowser=同步帳戶 → 瀏覽器
|
||||||
account.syncToAccount=同步帳號 ← 瀏覽器
|
account.syncToAccount=同步帳戶 ← 瀏覽器
|
||||||
|
|
||||||
|
|
||||||
adminUserSettings.title=使用者控制設定
|
adminUserSettings.title=使用者控制設定
|
||||||
adminUserSettings.header=管理員使用者控制設定
|
adminUserSettings.header=管理使用者控制設定
|
||||||
adminUserSettings.admin=管理員
|
adminUserSettings.admin=管理員
|
||||||
adminUserSettings.user=使用者
|
adminUserSettings.user=使用者
|
||||||
adminUserSettings.addUser=新增使用者
|
adminUserSettings.addUser=新增使用者
|
||||||
adminUserSettings.deleteUser=刪除使用者
|
adminUserSettings.deleteUser=刪除使用者
|
||||||
adminUserSettings.confirmDeleteUser=確定要刪除此使用者?
|
adminUserSettings.confirmDeleteUser=確認刪除該使用者?
|
||||||
adminUserSettings.confirmChangeUserStatus=是否要停用/啟用此使用者?
|
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
||||||
adminUserSettings.usernameInfo=使用者名稱只能包含字母、數字和以下特殊字元 @._+- 或必須是有效的電子郵件地址。
|
adminUserSettings.usernameInfo=使用者名稱只能包含字母、數字和以下特殊字元 @._+-,或必須是有效的電子郵件地址。
|
||||||
adminUserSettings.roles=角色
|
adminUserSettings.roles=角色
|
||||||
adminUserSettings.role=角色
|
adminUserSettings.role=角色
|
||||||
adminUserSettings.actions=操作
|
adminUserSettings.actions=操作
|
||||||
adminUserSettings.apiUser=受限制的 API 使用者
|
adminUserSettings.apiUser=受限制的 API 使用者
|
||||||
adminUserSettings.extraApiUser=額外受限制的 API 使用者
|
adminUserSettings.extraApiUser=其他受限 API 使用者
|
||||||
adminUserSettings.webOnlyUser=僅網頁版使用者
|
adminUserSettings.webOnlyUser=僅使用網頁的使用者
|
||||||
adminUserSettings.demoUser=示範使用者(無自訂設定)
|
adminUserSettings.demoUser=示範用途的使用者(無自訂設定)
|
||||||
adminUserSettings.internalApiUser=內部 API 使用者
|
adminUserSettings.internalApiUser=內部 API 使用者
|
||||||
adminUserSettings.forceChange=強制使用者在登入時變更密碼
|
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=資料庫匯入/匯出
|
||||||
@@ -235,20 +217,18 @@ database.fileSize=檔案大小
|
|||||||
database.deleteBackupFile=刪除備份檔案
|
database.deleteBackupFile=刪除備份檔案
|
||||||
database.importBackupFile=匯入備份檔案
|
database.importBackupFile=匯入備份檔案
|
||||||
database.downloadBackupFile=下載備份檔案
|
database.downloadBackupFile=下載備份檔案
|
||||||
database.info_1=在匯入資料時,確保正確的結構至關重要。如果您不確定自己在做什麼,請尋求專業人士的建議和支援。結構錯誤可能會導致應用程式故障,甚至完全無法執行應用程式。
|
database.info_1=在匯入資料時,確保正確的結構是至關重要的。如果你不確定自己在做什麼,請尋求專業人士的建議和支持。結構錯誤可能會導致應用程式故障,甚至完全無法運行。
|
||||||
database.info_2=上傳時檔案名稱並不重要。上傳後將重新命名為 backup_user_yyyyMMddHHmm.sql 格式,以確保命名規範一致。
|
database.info_2=上傳時檔案名稱無關緊要。上傳後將重新命名為 backup_user_yyyyMMddHHmm.sql 格式,以確保命名規範一致。
|
||||||
database.submit=匯入備份
|
database.submit=匯入備份
|
||||||
database.importIntoDatabaseSuccessed=成功匯入資料庫
|
database.importIntoDatabaseSuccessed=成功匯入資料庫
|
||||||
database.fileNotFound=找不到檔案
|
database.fileNotFound=檔案未找到
|
||||||
database.fileNullOrEmpty=檔案不得為空或空白
|
database.fileNullOrEmpty=檔案不能為空或空白
|
||||||
database.failedImportFile=匯入檔案失敗
|
database.failedImportFile=匯入檔案失敗
|
||||||
|
|
||||||
session.expired=您的工作階段已過期。請重新整理頁面並再試一次。
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
home.desc=你的本機主機一站式 PDF 需求解決方案。
|
home.desc=你的本地主機一站式 PDF 需求解決方案。
|
||||||
home.searchBar=搜尋功能...
|
home.searchBar=搜尋功能...
|
||||||
|
|
||||||
|
|
||||||
@@ -392,7 +372,7 @@ certSign.tags=驗證,PEM,P12,官方,加密
|
|||||||
|
|
||||||
home.removeCertSign.title=移除簽章
|
home.removeCertSign.title=移除簽章
|
||||||
home.removeCertSign.desc=從 PDF 移除簽章
|
home.removeCertSign.desc=從 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 檔案的多個頁面合併到單一頁面
|
||||||
@@ -485,9 +465,9 @@ home.split-by-sections.title=依區段分割 PDF
|
|||||||
home.split-by-sections.desc=將 PDF 的每一頁分割為較小的水平和垂直區段
|
home.split-by-sections.desc=將 PDF 的每一頁分割為較小的水平和垂直區段
|
||||||
split-by-sections.tags=區段分割, 劃分, 自訂
|
split-by-sections.tags=區段分割, 劃分, 自訂
|
||||||
|
|
||||||
home.AddStampRequest.title=將圖章新增到 PDF
|
home.AddStampRequest.title=將圖章添加到 PDF
|
||||||
home.AddStampRequest.desc=在設定位置新增文字或新增影像圖章
|
home.AddStampRequest.desc=在設置位置添加文字或添加圖像圖章
|
||||||
AddStampRequest.tags=圖章,新增圖片,中心影像,浮水印,PDF,嵌入,自訂
|
AddStampRequest.tags=圖章,添加圖片,中心圖像,浮水印,PDF,嵌入,自訂
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF 轉電子書
|
home.PDFToBook.title=PDF 轉電子書
|
||||||
@@ -498,33 +478,28 @@ home.BookToPDF.title=電子書轉 PDF
|
|||||||
home.BookToPDF.desc=使用 calibre 將書籍/漫畫格式轉換為 PDF
|
home.BookToPDF.desc=使用 calibre 將書籍/漫畫格式轉換為 PDF
|
||||||
BookToPDF.tags=電子書,漫畫,Calibre,轉換,日本漫畫,亞馬遜,kindle
|
BookToPDF.tags=電子書,漫畫,Calibre,轉換,日本漫畫,亞馬遜,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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -542,19 +517,16 @@ login.invalid=使用者名稱或密碼無效。
|
|||||||
login.locked=你的帳戶已被鎖定。
|
login.locked=你的帳戶已被鎖定。
|
||||||
login.signinTitle=請登入
|
login.signinTitle=請登入
|
||||||
login.ssoSignIn=透過織網單一簽入
|
login.ssoSignIn=透過織網單一簽入
|
||||||
login.oauth2AutoCreateDisabled=OAuth 2.0 自動建立使用者功能已停用
|
login.oauth2AutoCreateDisabled=OAuth 2.0 自動建立使用者已停用
|
||||||
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=無效的 Token 回應
|
||||||
login.oauth2InvalidIdToken=無效的識別權杖
|
login.oauth2InvalidIdToken=無效的 Tokne
|
||||||
login.userIsDisabled=使用者已停用,目前此使用者無法登入。請聯絡系統管理員。
|
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||||
login.alreadyLoggedIn=您已經登入了
|
|
||||||
login.alreadyLoggedIn2=個裝置。請登出其他裝置後再試一次。
|
|
||||||
login.toManySessions=您有太多使用中的工作階段
|
|
||||||
login.toManySessions2=請登出其他裝置後再試一次。或者,您可以升級至 Stirling PDF 專業版。
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
autoRedact.title=自動塗黑
|
autoRedact.title=自動塗黑
|
||||||
@@ -640,7 +612,7 @@ AddStampRequest.stampType=圖章類型
|
|||||||
AddStampRequest.stampText=圖章文字
|
AddStampRequest.stampText=圖章文字
|
||||||
AddStampRequest.stampImage=圖章圖片
|
AddStampRequest.stampImage=圖章圖片
|
||||||
AddStampRequest.alphabet=字母表
|
AddStampRequest.alphabet=字母表
|
||||||
AddStampRequest.fontSize=字型/影像大小
|
AddStampRequest.fontSize=字體/圖像大小
|
||||||
AddStampRequest.rotation=旋轉
|
AddStampRequest.rotation=旋轉
|
||||||
AddStampRequest.opacity=透明度
|
AddStampRequest.opacity=透明度
|
||||||
AddStampRequest.position=位置
|
AddStampRequest.position=位置
|
||||||
@@ -729,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=送出
|
||||||
|
|
||||||
@@ -738,7 +710,7 @@ scalePages.submit=送出
|
|||||||
certSign.title=憑證簽章
|
certSign.title=憑證簽章
|
||||||
certSign.header=使用你的憑證簽章(進行中)
|
certSign.header=使用你的憑證簽章(進行中)
|
||||||
certSign.selectPDF=選擇要簽章的 PDF 檔案:
|
certSign.selectPDF=選擇要簽章的 PDF 檔案:
|
||||||
certSign.jksNote=注意:如果你的證書類型未在下面列出,請使用 keytool 命令列工具將其轉換為 Java Keystore (.jks) 檔。 然後,選擇下面的 .jks 文件選項。
|
certSign.jksNote=注意:如果你的證書類型未在下面列出,請使用 keytool 命令行工具將其轉換為 Java Keystore (.jks) 檔。 然後,選擇下面的 .jks 文件選項。
|
||||||
certSign.selectKey=選擇你的私鑰文件(PKCS#8 格式,可能是 .pem 或 .der):
|
certSign.selectKey=選擇你的私鑰文件(PKCS#8 格式,可能是 .pem 或 .der):
|
||||||
certSign.selectCert=選擇你的憑證文件(X.509 格式,可能是 .pem 或 .der):
|
certSign.selectCert=選擇你的憑證文件(X.509 格式,可能是 .pem 或 .der):
|
||||||
certSign.selectP12=選擇你的 PKCS#12 金鑰庫文件(.p12 或 .pfx)(可選,如果提供,它應包含你的私鑰和憑證):
|
certSign.selectP12=選擇你的 PKCS#12 金鑰庫文件(.p12 或 .pfx)(可選,如果提供,它應包含你的私鑰和憑證):
|
||||||
@@ -778,8 +750,8 @@ 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=比較
|
||||||
@@ -816,7 +788,7 @@ repair.submit=修復
|
|||||||
#flatten
|
#flatten
|
||||||
flatten.title=平坦化
|
flatten.title=平坦化
|
||||||
flatten.header=PDF 平坦化
|
flatten.header=PDF 平坦化
|
||||||
flatten.flattenOnlyForms=僅將表單平坦化
|
flatten.flattenOnlyForms=Flatten only forms
|
||||||
flatten.submit=平坦化
|
flatten.submit=平坦化
|
||||||
|
|
||||||
|
|
||||||
@@ -831,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。需要安裝 Python 才能執行。
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -914,14 +886,14 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=PDF 多工具
|
multiTool.title=PDF 多工具
|
||||||
multiTool.header=PDF 多工具
|
multiTool.header=PDF 多工具
|
||||||
multiTool.uploadPrompts=檔名
|
multiTool.uploadPrompts=File Name
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=檢視 PDF
|
viewPdf.title=檢視 PDF
|
||||||
@@ -983,7 +955,7 @@ pdfToImage.color=顏色
|
|||||||
pdfToImage.grey=灰度
|
pdfToImage.grey=灰度
|
||||||
pdfToImage.blackwhite=黑白(可能會遺失資料!)
|
pdfToImage.blackwhite=黑白(可能會遺失資料!)
|
||||||
pdfToImage.submit=轉換
|
pdfToImage.submit=轉換
|
||||||
pdfToImage.info=尚未安裝 Python。需要安裝 Python 才能進行 WebP 轉換。
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1020,7 +992,7 @@ watermark.selectText.6=heightSpacer(每個浮水印之間的垂直間距):
|
|||||||
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=圖片
|
||||||
@@ -1171,55 +1143,39 @@ printFile.submit=列印
|
|||||||
|
|
||||||
|
|
||||||
#licenses
|
#licenses
|
||||||
licenses.nav=授權條款
|
licenses.nav=許可證
|
||||||
licenses.title=第三方授權條款
|
licenses.title=第三方許可證
|
||||||
licenses.header=第三方授權條款
|
licenses.header=第三方許可證
|
||||||
licenses.module=模組
|
licenses.module=模組
|
||||||
licenses.version=版本
|
licenses.version=版本
|
||||||
licenses.license=授權條款
|
licenses.license=許可證
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
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 自上次調查以來已有所改變!欲了解更多資訊,請查看我們的部落格文章:
|
survey.please=請考慮參加我們的問卷調查!
|
||||||
survey.changes2=隨著這些變更,我們正在獲得付費的商業支援和資金
|
survey.disabled=(問卷調查彈出窗口將在後續更新中停用,但仍可在頁腳處使用)
|
||||||
survey.please=請考慮參與我們的問卷調查!
|
survey.button=參加問卷調查
|
||||||
survey.disabled=(問卷調查彈出視窗將在後續更新中停用,但仍可在頁尾使用)
|
|
||||||
survey.button=參與問卷調查
|
|
||||||
survey.dontShowAgain=不要再次顯示
|
survey.dontShowAgain=不要再次顯示
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
error.sorry=很抱歉造成您的困擾!
|
error.sorry=對於這個問題,我們感到抱歉!
|
||||||
error.needHelp=需要協助或發現問題?
|
error.needHelp=需要幫助/發現了一個問題?
|
||||||
error.contactTip=如果您仍然遇到問題,請不要猶豫,隨時向我們尋求協助。您可以在我們的 GitHub 頁面回報問題,或透過 Discord 跟我們聯絡:
|
error.contactTip=如果你仍然遇到問題,請不要猶豫,隨時向我們尋求幫助。你可以在我們的 GitHub 頁面提交工單,或通過 Discord 與我們聯繋:
|
||||||
error.404.head=404 - 找不到頁面 | 糟糕,我們在程式碼中迷路了!
|
error.404.head=404 - 找不到頁面 | 哎呀,我們在代碼中走錯了路!
|
||||||
error.404.1=我們似乎找不到您正在尋找的頁面。
|
error.404.1=我們好像找不到你正在尋找的頁面。
|
||||||
error.404.2=發生了一些錯誤
|
error.404.2=出了點錯誤
|
||||||
error.github=在 GitHub 上回報問題
|
error.github=在 GitHub 上提交工單
|
||||||
error.showStack=顯示堆疊追蹤
|
error.showStack=顯示堆疊追蹤
|
||||||
error.copyStack=複製堆疊追蹤
|
error.copyStack=複製堆疊追蹤
|
||||||
error.githubSubmit=GitHub - 回報問題
|
error.githubSubmit=GitHub - 提交工單
|
||||||
error.discordSubmit=Discord - 發表支援文章
|
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,18 +47,6 @@ 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
|
|
||||||
autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
|
|
||||||
blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
|
|
||||||
registrationId: stirling
|
|
||||||
idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata
|
|
||||||
idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml
|
|
||||||
idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml
|
|
||||||
idpIssuer: http://www.okta.com/externalKey
|
|
||||||
idpCert: classpath:octa.crt
|
|
||||||
privateKey: classpath:saml-private-key.key
|
|
||||||
spCert: classpath:saml-public-cert.crt
|
|
||||||
|
|
||||||
# Enterprise edition settings unused for now please ignore!
|
# Enterprise edition settings unused for now please ignore!
|
||||||
enterpriseEdition:
|
enterpriseEdition:
|
||||||
|
|||||||
@@ -63,27 +63,6 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.fasterxml.jackson.jaxrs:jackson-jaxrs-base",
|
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-base",
|
|
||||||
"moduleVersion": "2.17.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider",
|
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-json-provider",
|
|
||||||
"moduleVersion": "2.17.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.fasterxml.jackson.module:jackson-module-jaxb-annotations",
|
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-base",
|
|
||||||
"moduleVersion": "2.17.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names",
|
"moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names",
|
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names",
|
||||||
@@ -132,46 +111,6 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.google.code.findbugs:jsr305",
|
|
||||||
"moduleUrl": "http://findbugs.sourceforge.net/",
|
|
||||||
"moduleVersion": "3.0.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.google.errorprone:error_prone_annotations",
|
|
||||||
"moduleVersion": "2.11.0",
|
|
||||||
"moduleLicense": "Apache 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.google.guava:failureaccess",
|
|
||||||
"moduleUrl": "https://github.com/google/guava/",
|
|
||||||
"moduleVersion": "1.0.1",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.google.guava:guava",
|
|
||||||
"moduleUrl": "https://github.com/google/guava/",
|
|
||||||
"moduleVersion": "31.1-jre",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.google.guava:listenablefuture",
|
|
||||||
"moduleVersion": "9999.0-empty-to-avoid-conflict-with-guava",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.google.j2objc:j2objc-annotations",
|
|
||||||
"moduleUrl": "https://github.com/google/j2objc/",
|
|
||||||
"moduleVersion": "1.3",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.google.zxing:core",
|
"moduleName": "com.google.zxing:core",
|
||||||
"moduleUrl": "https://github.com/zxing/zxing/core",
|
"moduleUrl": "https://github.com/zxing/zxing/core",
|
||||||
@@ -179,25 +118,6 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.googlecode.owasp-java-html-sanitizer:java10-shim",
|
|
||||||
"moduleVersion": "20240325.1",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.googlecode.owasp-java-html-sanitizer:java8-shim",
|
|
||||||
"moduleVersion": "20240325.1",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer",
|
|
||||||
"moduleUrl": "https://owasp.org",
|
|
||||||
"moduleVersion": "20240325.1",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.h2database:h2",
|
"moduleName": "com.h2database:h2",
|
||||||
"moduleUrl": "https://h2database.com",
|
"moduleUrl": "https://h2database.com",
|
||||||
@@ -247,13 +167,6 @@
|
|||||||
"moduleLicense": "Apache 2",
|
"moduleLicense": "Apache 2",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.posthog.java:posthog",
|
|
||||||
"moduleUrl": "http://github.com/PostHog/posthog-java",
|
|
||||||
"moduleVersion": "1.1.1",
|
|
||||||
"moduleLicense": "MIT License",
|
|
||||||
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.sun.istack:istack-commons-runtime",
|
"moduleName": "com.sun.istack:istack-commons-runtime",
|
||||||
"moduleUrl": "https://www.eclipse.org",
|
"moduleUrl": "https://www.eclipse.org",
|
||||||
@@ -263,78 +176,64 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.common:common-image",
|
"moduleName": "com.twelvemonkeys.common:common-image",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.common:common-io",
|
"moduleName": "com.twelvemonkeys.common:common-io",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.common:common-lang",
|
"moduleName": "com.twelvemonkeys.common:common-lang",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-batik",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-batik",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-bmp",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-bmp",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-core",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-core",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-jpeg",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-jpeg",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-metadata",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-metadata",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-tiff",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-tiff",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-webp",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-webp",
|
||||||
"moduleVersion": "3.12.0",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.unboundid.product.scim2:scim2-sdk-client",
|
|
||||||
"moduleUrl": "https://github.com/pingidentity/scim2",
|
|
||||||
"moduleVersion": "2.3.5",
|
|
||||||
"moduleLicense": "UnboundID SCIM2 SDK Free Use License",
|
|
||||||
"moduleLicenseUrl": "https://github.com/pingidentity/scim2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "com.unboundid.product.scim2:scim2-sdk-common",
|
|
||||||
"moduleUrl": "https://github.com/pingidentity/scim2",
|
|
||||||
"moduleVersion": "2.3.5",
|
|
||||||
"moduleLicense": "UnboundID SCIM2 SDK Free Use License",
|
|
||||||
"moduleLicenseUrl": "https://github.com/pingidentity/scim2"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.zaxxer:HikariCP",
|
"moduleName": "com.zaxxer:HikariCP",
|
||||||
"moduleUrl": "https://github.com/brettwooldridge/HikariCP",
|
"moduleUrl": "https://github.com/brettwooldridge/HikariCP",
|
||||||
@@ -349,13 +248,6 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "commons-codec:commons-codec",
|
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-codec/",
|
|
||||||
"moduleVersion": "1.16.1",
|
|
||||||
"moduleLicense": "Apache-2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "commons-collections:commons-collections",
|
"moduleName": "commons-collections:commons-collections",
|
||||||
"moduleUrl": "http://commons.apache.org/collections/",
|
"moduleUrl": "http://commons.apache.org/collections/",
|
||||||
@@ -377,12 +269,6 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "/LICENSE.txt"
|
"moduleLicenseUrl": "/LICENSE.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "io.dropwizard.metrics:metrics-core",
|
|
||||||
"moduleVersion": "4.2.25",
|
|
||||||
"moduleLicense": "Apache License 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "io.github.pixee:java-security-toolkit",
|
"moduleName": "io.github.pixee:java-security-toolkit",
|
||||||
"moduleUrl": "https://github.com/pixee/java-security-toolkit",
|
"moduleUrl": "https://github.com/pixee/java-security-toolkit",
|
||||||
@@ -400,7 +286,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-core",
|
"moduleName": "io.micrometer:micrometer-core",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.13.6",
|
"moduleVersion": "1.13.4",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@@ -536,20 +422,6 @@
|
|||||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "javax.activation:javax.activation-api",
|
|
||||||
"moduleUrl": "http://www.oracle.com",
|
|
||||||
"moduleVersion": "1.2.0",
|
|
||||||
"moduleLicense": "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0",
|
|
||||||
"moduleLicenseUrl": "https://opensource.org/licenses/CDDL-1.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "javax.xml.bind:jaxb-api",
|
|
||||||
"moduleUrl": "http://www.oracle.com/",
|
|
||||||
"moduleVersion": "2.3.1",
|
|
||||||
"moduleLicense": "GPL2 w/ CPE",
|
|
||||||
"moduleLicenseUrl": "https://oss.oracle.com/licenses/CDDL+GPL-1.1"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "net.bytebuddy:byte-buddy",
|
"moduleName": "net.bytebuddy:byte-buddy",
|
||||||
"moduleVersion": "1.14.19",
|
"moduleVersion": "1.14.19",
|
||||||
@@ -570,12 +442,6 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "net.shibboleth.utilities:java-support",
|
|
||||||
"moduleVersion": "8.4.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.antlr:antlr4-runtime",
|
"moduleName": "org.antlr:antlr4-runtime",
|
||||||
"moduleUrl": "https://www.antlr.org/",
|
"moduleUrl": "https://www.antlr.org/",
|
||||||
@@ -604,20 +470,6 @@
|
|||||||
"moduleLicense": "Apache-2.0",
|
"moduleLicense": "Apache-2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.apache.httpcomponents:httpclient",
|
|
||||||
"moduleUrl": "http://hc.apache.org/httpcomponents-client-ga",
|
|
||||||
"moduleVersion": "4.5.14",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.apache.httpcomponents:httpcore",
|
|
||||||
"moduleUrl": "http://hc.apache.org/httpcomponents-core-ga",
|
|
||||||
"moduleVersion": "4.4.16",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.apache.logging.log4j:log4j-api",
|
"moduleName": "org.apache.logging.log4j:log4j-api",
|
||||||
"moduleVersion": "2.23.1",
|
"moduleVersion": "2.23.1",
|
||||||
@@ -664,13 +516,6 @@
|
|||||||
"moduleLicense": "Apache-2.0",
|
"moduleLicense": "Apache-2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.apache.santuario:xmlsec",
|
|
||||||
"moduleUrl": "https://www.apache.org/",
|
|
||||||
"moduleVersion": "2.3.4",
|
|
||||||
"moduleLicense": "Apache-2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
||||||
"moduleUrl": "https://tomcat.apache.org/",
|
"moduleUrl": "https://tomcat.apache.org/",
|
||||||
@@ -678,23 +523,16 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.apache.velocity:velocity-engine-core",
|
|
||||||
"moduleUrl": "https://www.apache.org/",
|
|
||||||
"moduleVersion": "2.3",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.apache.xmlgraphics:batik-all",
|
"moduleName": "org.apache.xmlgraphics:batik-all",
|
||||||
"moduleVersion": "1.18",
|
"moduleVersion": "1.17",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.apache.xmlgraphics:xmlgraphics-commons",
|
"moduleName": "org.apache.xmlgraphics:xmlgraphics-commons",
|
||||||
"moduleUrl": "http://xmlgraphics.apache.org/commons/",
|
"moduleUrl": "http://xmlgraphics.apache.org/commons/",
|
||||||
"moduleVersion": "2.10",
|
"moduleVersion": "2.9",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@@ -733,13 +571,6 @@
|
|||||||
"moduleLicense": "Bouncy Castle Licence",
|
"moduleLicense": "Bouncy Castle Licence",
|
||||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.checkerframework:checker-qual",
|
|
||||||
"moduleUrl": "https://checkerframework.org",
|
|
||||||
"moduleVersion": "3.12.0",
|
|
||||||
"moduleLicense": "The MIT License",
|
|
||||||
"moduleLicenseUrl": "http://opensource.org/licenses/MIT"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.commonmark:commonmark",
|
"moduleName": "org.commonmark:commonmark",
|
||||||
"moduleVersion": "0.23.0",
|
"moduleVersion": "0.23.0",
|
||||||
@@ -752,13 +583,6 @@
|
|||||||
"moduleLicense": "BSD 2-Clause License",
|
"moduleLicense": "BSD 2-Clause License",
|
||||||
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.cryptacular:cryptacular",
|
|
||||||
"moduleUrl": "http://www.cryptacular.org",
|
|
||||||
"moduleVersion": "1.2.5",
|
|
||||||
"moduleLicense": "GNU Lesser General Public License",
|
|
||||||
"moduleLicenseUrl": "http://www.gnu.org/licenses/lgpl-3.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.angus:angus-activation",
|
"moduleName": "org.eclipse.angus:angus-activation",
|
||||||
"moduleUrl": "https://www.eclipse.org",
|
"moduleUrl": "https://www.eclipse.org",
|
||||||
@@ -1004,78 +828,6 @@
|
|||||||
"moduleLicense": "Public Domain, per Creative Commons CC0",
|
"moduleLicense": "Public Domain, per Creative Commons CC0",
|
||||||
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
|
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-core",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-messaging-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-profile-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-saml-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-saml-impl",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-security-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-security-impl",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-soap-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-soap-impl",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-storage-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-xmlsec-api",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "org.opensaml:opensaml-xmlsec-impl",
|
|
||||||
"moduleVersion": "4.3.2",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.ow2.asm:asm",
|
"moduleName": "org.ow2.asm:asm",
|
||||||
"moduleUrl": "http://asm.ow2.org",
|
"moduleUrl": "http://asm.ow2.org",
|
||||||
@@ -1304,13 +1056,6 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.springframework.security:spring-security-saml2-service-provider",
|
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
|
||||||
"moduleVersion": "6.3.3",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-web",
|
"moduleName": "org.springframework.security:spring-security-web",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
|
|||||||
@@ -283,7 +283,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${altLogin}" class="modal fade" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
<div th:if="${oAuth2Enabled}" class="modal fade" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="d-flex justify-content-center">
|
<div class="d-flex justify-content-center">
|
||||||
<ul class="list-unstyled d-flex">
|
<ul class="list-unstyled d-flex">
|
||||||
<li><a class="footer-link px-2" id="licenses" target="_blank" th:href="@{'/licenses'}" th:text="#{licenses.nav}">Licenses</a></li>
|
<li><a class="footer-link px-2" id="licenses" target="_blank" th:href="@{'/licenses'}" th:text="#{licenses.nav}">Licenses</a></li>
|
||||||
<li><a class="footer-link px-2" id="survey" target="_blank" href="https://stirlingpdf.info/s/cm28y3niq000o56dv7liv8wsu" th:text="#{survey.nav}">Survey</a></li>
|
<li><a class="footer-link px-2" id="survey" target="_blank" href="https://stirlingpdf.info/s/clwzgtfw7000gltkmwz1n212m" th:text="#{survey.nav}">Survey</a></li>
|
||||||
<li th:if="${@privacyPolicy != ''}"><a class="footer-link px-2" target="_blank" th:href="${@privacyPolicy}" th:text="#{legal.privacy}">privacyPolicy</a></li>
|
<li th:if="${@privacyPolicy != ''}"><a class="footer-link px-2" target="_blank" th:href="${@privacyPolicy}" th:text="#{legal.privacy}">privacyPolicy</a></li>
|
||||||
<li th:if="${@termsAndConditions != ''}"><a class="footer-link px-2" target="_blank" th:href="${@termsAndConditions}" th:text="#{legal.terms}">termsAndConditions</a></li>
|
<li th:if="${@termsAndConditions != ''}"><a class="footer-link px-2" target="_blank" th:href="${@termsAndConditions}" th:text="#{legal.terms}">termsAndConditions</a></li>
|
||||||
<li th:if="${@accessibilityStatement != ''}"><a class="footer-link px-2" target="_blank" th:href="${@accessibilityStatement}" th:text="#{legal.accessibility}">accessibilityStatement</a></li>
|
<li th:if="${@accessibilityStatement != ''}"><a class="footer-link px-2" target="_blank" th:href="${@accessibilityStatement}" th:text="#{legal.accessibility}">accessibilityStatement</a></li>
|
||||||
|
|||||||
@@ -229,9 +229,6 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdf-by-sections', 'grid_on', 'home.split-by-sections.title', 'home.split-by-sections.desc', 'split-by-sections.tags', 'advance')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdf-by-sections', 'grid_on', 'home.split-by-sections.title', 'home.split-by-sections.desc', 'split-by-sections.tags', 'advance')}">
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdf-by-chapters', 'book', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-by-size-or-count', 'vertical_split', 'home.autoSizeSplitPDF.title', 'home.autoSizeSplitPDF.desc', 'autoSizeSplitPDF.tags', 'advance')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-by-size-or-count', 'vertical_split', 'home.autoSizeSplitPDF.title', 'home.autoSizeSplitPDF.desc', 'autoSizeSplitPDF.tags', 'advance')}">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -319,9 +319,6 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/card :: card(id='split-pdf-by-sections', cardTitle=#{home.split-by-sections.title}, cardText=#{home.split-by-sections.desc}, cardLink='split-pdf-by-sections', toolIcon='grid_on', tags=#{split-by-sections.tags}, toolGroup='advance')}">
|
th:replace="~{fragments/card :: card(id='split-pdf-by-sections', cardTitle=#{home.split-by-sections.title}, cardText=#{home.split-by-sections.desc}, cardLink='split-pdf-by-sections', toolIcon='grid_on', tags=#{split-by-sections.tags}, toolGroup='advance')}">
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
th:replace="~{fragments/card :: card(id='split-pdf-by-chapters', cardTitle=#{home.splitPdfByChapters.title}, cardText=#{home.splitPdfByChapters.desc}, cardLink='split-pdf-by-chapters', toolIcon='book', tags=#{splitPdfByChapters.tags}, toolGroup='advance')}">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -340,12 +337,12 @@
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p><span th:text="#{survey.changes}">Stirling-PDF has changed since the last survey! To find out more please check our blog post here: </span><a href="https://www.stirlingpdf.com/blog/stirling-pdf-future" target="_blank"> Stirling PDF</a></p>
|
<p th:text="#{survey.changes}">Stirling-PDF has changed since the last survey! To find out more please check our blog post here:</h5>
|
||||||
|
<a href="https://stirlingpdf.info/blog/stirling-pdf-survey-results" target="_blank" th:text="#{survey.changes2}">https://stirlingpdf.info/blog/stirling-pdf-survey-results</a>
|
||||||
<p th:text="#{survey.changes2}">With these changes we are getting paid business support and funding</p>
|
<p th:text="#{survey.changes2}">With these changes we are getting paid business support and funding</p>
|
||||||
<p th:text="#{survey.please}">Please consider taking our survey!</p>
|
<p th:text="#{survey.please}">Please consider taking our survey!</p>
|
||||||
<p th:text="#{survey.disabled}">Survey popup will be disabled in following updates but available at foot of page)</p>
|
<p th:text="#{survey.disabled}">Survey popup will be disabled in following updates but available at foot of page)</p>
|
||||||
<a href="https://stirlingpdf.info/s/cm28y3niq000o56dv7liv8wsu" target="_blank" class="btn btn-primary" id="takeSurvey"th:text="#{survey.button}" >Take Survey</a>
|
<a href="https://stirlingpdf.info/s/clwzgtfw7000gltkmwz1n212m" target="_blank" class="btn btn-primary" id="takeSurvey"th:text="#{survey.button}" >Take Survey</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<div class="form-check mb-3">
|
<div class="form-check mb-3">
|
||||||
@@ -475,4 +472,4 @@
|
|||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
<img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144">
|
<img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144">
|
||||||
|
|
||||||
<h1 class="h1 mb-3 fw-normal" th:text="${@appName}">Stirling-PDF</h1>
|
<h1 class="h1 mb-3 fw-normal" th:text="${@appName}">Stirling-PDF</h1>
|
||||||
<div th:if="${altLogin} and (${loginMethod} == 'all' or ${loginMethod} == 'oauth2')">
|
<div th:if="${oAuth2Enabled} and (${loginMethod} == 'all' or ${loginMethod} == 'oauth2')">
|
||||||
<a href="#" class="w-100 btn btn-lg btn-primary" data-bs-toggle="modal" data-bs-target="#loginsModal" th:text="#{login.ssoSignIn}">Login Via SSO</a>
|
<a href="#" class="w-100 btn btn-lg btn-primary" data-bs-toggle="modal" data-bs-target="#loginsModal" th:text="#{login.ssoSignIn}">Login Via SSO</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
</main>
|
</main>
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${altLogin}" class="modal fade" id="loginsModal" tabindex="-1" role="dialog" aria-labelledby="loginsModalLabel" aria-hidden="true">
|
<div th:if="${oAuth2Enabled}" class="modal fade" id="loginsModal" tabindex="-1" role="dialog" aria-labelledby="loginsModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="mb-3" th:each="provider : ${providerlist}">
|
<div class="mb-3" th:each="provider : ${providerlist}">
|
||||||
<a th:href="@{|${provider.key}|}" th:text="${provider.value}" class="w-100 btn btn-lg btn-primary">Login Provider</a>
|
<a th:href="@{|/oauth2/authorization/${provider.key}|}" th:text="${provider.value}" class="w-100 btn btn-lg btn-primary">OpenID Connect</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|||||||
48
test.sh
48
test.sh
@@ -73,16 +73,28 @@ main() {
|
|||||||
|
|
||||||
|
|
||||||
# Building Docker images
|
# Building Docker images
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest -f ./Dockerfile .
|
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest -f ./Dockerfile .
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-ultra-lite -f ./Dockerfile-ultra-lite .
|
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-ultra-lite -f ./Dockerfile-ultra-lite .
|
||||||
|
|
||||||
# Test each configuration
|
# Test each configuration
|
||||||
#run_tests "Stirling-PDF-Ultra-Lite" "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml"
|
run_tests "Stirling-PDF-Ultra-Lite" "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml"
|
||||||
#docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
|
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
|
||||||
|
|
||||||
|
|
||||||
# run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
|
run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
|
||||||
#docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
|
if [ $? -eq 0 ]; then
|
||||||
|
cd cucumber
|
||||||
|
if behave; then
|
||||||
|
passed_tests+=("Stirling-PDF-Regression")
|
||||||
|
else
|
||||||
|
failed_tests+=("Stirling-PDF-Regression")
|
||||||
|
echo "Printing docker logs of failed regression"
|
||||||
|
docker logs "Stirling-PDF"
|
||||||
|
echo "Printed docker logs of failed regression"
|
||||||
|
fi
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
|
||||||
|
|
||||||
export DOCKER_ENABLE_SECURITY=true
|
export DOCKER_ENABLE_SECURITY=true
|
||||||
# Run the gradlew build command and check if it fails
|
# Run the gradlew build command and check if it fails
|
||||||
@@ -93,30 +105,18 @@ main() {
|
|||||||
|
|
||||||
|
|
||||||
# Building Docker images with security enabled
|
# Building Docker images with security enabled
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest -f ./Dockerfile .
|
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest -f ./Dockerfile .
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-ultra-lite -f ./Dockerfile-ultra-lite .
|
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-ultra-lite -f ./Dockerfile-ultra-lite .
|
||||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-fat -f ./Dockerfile-fat .
|
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t frooodle/s-pdf:latest-fat -f ./Dockerfile-fat .
|
||||||
|
|
||||||
|
|
||||||
# Test each configuration with security
|
# Test each configuration with security
|
||||||
# run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
|
run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
|
||||||
#docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
|
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
|
||||||
# run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
|
run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
|
||||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
|
docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
|
||||||
|
|
||||||
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
|
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
cd cucumber
|
|
||||||
if python -m behave; then
|
|
||||||
passed_tests+=("Stirling-PDF-Regression")
|
|
||||||
else
|
|
||||||
failed_tests+=("Stirling-PDF-Regression")
|
|
||||||
echo "Printing docker logs of failed regression"
|
|
||||||
docker logs "Stirling-PDF-Security-Fat"
|
|
||||||
echo "Printed docker logs of failed regression"
|
|
||||||
fi
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
|
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
|
||||||
|
|
||||||
# Report results
|
# Report results
|
||||||
|
|||||||
Reference in New Issue
Block a user