mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2024-11-23 15:21:25 +01:00
Frooodle/license (#1994)
This commit is contained in:
parent
ceeecc37ab
commit
c85463bc18
1
.gitignore
vendored
1
.gitignore
vendored
@ -110,7 +110,6 @@ watchedFolders/
|
|||||||
*.war
|
*.war
|
||||||
*.nar
|
*.nar
|
||||||
*.ear
|
*.ear
|
||||||
*.zip
|
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.rar
|
*.rar
|
||||||
*.db
|
*.db
|
||||||
|
13
build.gradle
13
build.gradle
@ -22,7 +22,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
group = "stirling.software"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
// 17 is lowest but we support and recommend 21
|
// 17 is lowest but we support and recommend 21
|
||||||
@ -32,6 +32,12 @@ 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/maven/releases/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
licenseReport {
|
licenseReport {
|
||||||
@ -127,6 +133,9 @@ dependencies {
|
|||||||
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
|
||||||
|
|
||||||
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
||||||
|
implementation 'com.posthog.java:posthog:1.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"
|
||||||
@ -134,6 +143,8 @@ dependencies {
|
|||||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
||||||
|
|
||||||
|
implementation 'org.springframework.security:spring-security-saml2-service-provider:6.3.3'
|
||||||
|
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
||||||
//2.2.x requires rebuild of DB file.. need migration path
|
//2.2.x requires rebuild of DB file.. need migration path
|
||||||
runtimeOnly "com.h2database:h2:2.1.214"
|
runtimeOnly "com.h2database:h2:2.1.214"
|
||||||
// implementation "com.h2database:h2:2.2.224"
|
// implementation "com.h2database:h2:2.2.224"
|
||||||
|
11
cucumber/exampleFiles/example.html
Normal file
11
cucumber/exampleFiles/example.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>My First Heading</h1>
|
||||||
|
|
||||||
|
<p>My first paragraph.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
16
cucumber/exampleFiles/example.md
Normal file
16
cucumber/exampleFiles/example.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
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.
|
BIN
cucumber/exampleFiles/example_html.zip
Normal file
BIN
cucumber/exampleFiles/example_html.zip
Normal file
Binary file not shown.
@ -123,7 +123,7 @@ Feature: API Validation
|
|||||||
| odt | .odt |
|
| odt | .odt |
|
||||||
| doc | .doc |
|
| doc | .doc |
|
||||||
|
|
||||||
@ocr
|
@ocr @pdfa1
|
||||||
Scenario: PDFA
|
Scenario: PDFA
|
||||||
Given I use an example file at "exampleFiles/pdfa2.pdf" as parameter "fileInput"
|
Given I use an example file at "exampleFiles/pdfa2.pdf" as parameter "fileInput"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
@ -134,7 +134,7 @@ Feature: API Validation
|
|||||||
And the response file should have extension ".pdf"
|
And the response file should have extension ".pdf"
|
||||||
And the response file should have size greater than 100
|
And the response file should have size greater than 100
|
||||||
|
|
||||||
@ocr
|
@ocr @pdfa2
|
||||||
Scenario: PDFA1
|
Scenario: PDFA1
|
||||||
Given I use an example file at "exampleFiles/pdfa1.pdf" as parameter "fileInput"
|
Given I use an example file at "exampleFiles/pdfa1.pdf" as parameter "fileInput"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
@ -219,5 +219,27 @@ Feature: API Validation
|
|||||||
| .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' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
||||||
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: "true"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
UMASK: "022"
|
UMASK: "022"
|
||||||
|
@ -17,9 +17,10 @@ public class EEAppConfig {
|
|||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Bean(name = "RunningEE")
|
@Autowired private LicenseKeyChecker licenseKeyChecker;
|
||||||
|
|
||||||
|
@Bean(name = "runningEE")
|
||||||
public boolean runningEnterpriseEdition() {
|
public boolean runningEnterpriseEdition() {
|
||||||
// TODO: Implement EE detection
|
return licenseKeyChecker.getEnterpriseEnabledResult();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,204 @@
|
|||||||
|
package stirling.software.SPDF.EE;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.posthog.java.shaded.org.json.JSONObject;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.utils.GeneralUtils;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class KeygenLicenseVerifier {
|
||||||
|
private static final String ACCOUNT_ID = "e5430f69-e834-4ae4-befd-b602aae5f372";
|
||||||
|
private static final String BASE_URL = "https://api.keygen.sh/v1/accounts";
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public KeygenLicenseVerifier(ApplicationProperties applicationProperties) {
|
||||||
|
this.applicationProperties = applicationProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verifyLicense(String licenseKey) {
|
||||||
|
try {
|
||||||
|
log.info("Checking license key");
|
||||||
|
String machineFingerprint = generateMachineFingerprint();
|
||||||
|
|
||||||
|
// First, try to validate the license
|
||||||
|
JsonNode validationResponse = validateLicense(licenseKey, machineFingerprint);
|
||||||
|
if (validationResponse != null) {
|
||||||
|
boolean isValid = validationResponse.path("meta").path("valid").asBoolean();
|
||||||
|
String licenseId = validationResponse.path("data").path("id").asText();
|
||||||
|
if (!isValid) {
|
||||||
|
String code = validationResponse.path("meta").path("code").asText();
|
||||||
|
log.debug(code);
|
||||||
|
if ("NO_MACHINE".equals(code)
|
||||||
|
|| "NO_MACHINES".equals(code)
|
||||||
|
|| "FINGERPRINT_SCOPE_MISMATCH".equals(code)) {
|
||||||
|
log.info(
|
||||||
|
"License not activated for this machine. Attempting to activate...");
|
||||||
|
boolean activated =
|
||||||
|
activateMachine(licenseKey, licenseId, machineFingerprint);
|
||||||
|
if (activated) {
|
||||||
|
// Revalidate after activation
|
||||||
|
validationResponse = validateLicense(licenseKey, machineFingerprint);
|
||||||
|
isValid =
|
||||||
|
validationResponse != null
|
||||||
|
&& validationResponse
|
||||||
|
.path("meta")
|
||||||
|
.path("valid")
|
||||||
|
.asBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error verifying license: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode validateLicense(String licenseKey, String machineFingerprint)
|
||||||
|
throws Exception {
|
||||||
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
|
String requestBody =
|
||||||
|
String.format(
|
||||||
|
"{\"meta\":{\"key\":\"%s\",\"scope\":{\"fingerprint\":\"%s\"}}}",
|
||||||
|
licenseKey, machineFingerprint);
|
||||||
|
HttpRequest request =
|
||||||
|
HttpRequest.newBuilder()
|
||||||
|
.uri(
|
||||||
|
URI.create(
|
||||||
|
BASE_URL
|
||||||
|
+ "/"
|
||||||
|
+ ACCOUNT_ID
|
||||||
|
+ "/licenses/actions/validate-key"))
|
||||||
|
.header("Content-Type", "application/vnd.api+json")
|
||||||
|
.header("Accept", "application/vnd.api+json")
|
||||||
|
// .header("Authorization", "License " + licenseKey)
|
||||||
|
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
log.info(" validateLicenseResponse body: " + response.body());
|
||||||
|
JsonNode jsonResponse = objectMapper.readTree(response.body());
|
||||||
|
if (response.statusCode() == 200) {
|
||||||
|
|
||||||
|
JsonNode metaNode = jsonResponse.path("meta");
|
||||||
|
boolean isValid = metaNode.path("valid").asBoolean();
|
||||||
|
|
||||||
|
String detail = metaNode.path("detail").asText();
|
||||||
|
String code = metaNode.path("code").asText();
|
||||||
|
|
||||||
|
log.debug("License validity: " + isValid);
|
||||||
|
log.debug("Validation detail: " + detail);
|
||||||
|
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 {
|
||||||
|
log.error("Error validating license. Status code: " + response.statusCode());
|
||||||
|
}
|
||||||
|
return jsonResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean activateMachine(String licenseKey, String licenseId, String machineFingerprint)
|
||||||
|
throws Exception {
|
||||||
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
|
|
||||||
|
String hostname;
|
||||||
|
try {
|
||||||
|
hostname = java.net.InetAddress.getLocalHost().getHostName();
|
||||||
|
} catch (Exception e) {
|
||||||
|
hostname = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject body =
|
||||||
|
new JSONObject()
|
||||||
|
.put(
|
||||||
|
"data",
|
||||||
|
new JSONObject()
|
||||||
|
.put("type", "machines")
|
||||||
|
.put(
|
||||||
|
"attributes",
|
||||||
|
new JSONObject()
|
||||||
|
.put("fingerprint", machineFingerprint)
|
||||||
|
.put(
|
||||||
|
"platform",
|
||||||
|
System.getProperty(
|
||||||
|
"os.name")) // Added
|
||||||
|
// platform
|
||||||
|
// parameter
|
||||||
|
.put(
|
||||||
|
"name",
|
||||||
|
hostname)) // Added name parameter
|
||||||
|
.put(
|
||||||
|
"relationships",
|
||||||
|
new JSONObject()
|
||||||
|
.put(
|
||||||
|
"license",
|
||||||
|
new JSONObject()
|
||||||
|
.put(
|
||||||
|
"data",
|
||||||
|
new JSONObject()
|
||||||
|
.put(
|
||||||
|
"type",
|
||||||
|
"licenses")
|
||||||
|
.put(
|
||||||
|
"id",
|
||||||
|
licenseId)))));
|
||||||
|
|
||||||
|
HttpRequest request =
|
||||||
|
HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(BASE_URL + "/" + ACCOUNT_ID + "/machines"))
|
||||||
|
.header("Content-Type", "application/vnd.api+json")
|
||||||
|
.header("Accept", "application/vnd.api+json")
|
||||||
|
.header(
|
||||||
|
"Authorization",
|
||||||
|
"License " + licenseKey) // Keep the license key authentication
|
||||||
|
.POST(
|
||||||
|
HttpRequest.BodyPublishers.ofString(
|
||||||
|
body.toString())) // Send the JSON body
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
log.debug("activateMachine Response body: " + response.body());
|
||||||
|
if (response.statusCode() == 201) {
|
||||||
|
log.info("Machine activated successfully");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.error(
|
||||||
|
"Error activating machine. Status code: {}, error: {}",
|
||||||
|
response.statusCode(),
|
||||||
|
response.body());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateMachineFingerprint() {
|
||||||
|
return GeneralUtils.generateMachineFingerprint();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package stirling.software.SPDF.EE;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.utils.GeneralUtils;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class LicenseKeyChecker {
|
||||||
|
|
||||||
|
private final KeygenLicenseVerifier licenseService;
|
||||||
|
|
||||||
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
private boolean enterpriseEnbaledResult = false;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public LicenseKeyChecker(
|
||||||
|
KeygenLicenseVerifier licenseService, ApplicationProperties applicationProperties) {
|
||||||
|
this.licenseService = licenseService;
|
||||||
|
this.applicationProperties = applicationProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 604800000, initialDelay = 1000) // 7 days in milliseconds
|
||||||
|
public void checkLicensePeriodically() {
|
||||||
|
checkLicense();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkLicense() {
|
||||||
|
if (!applicationProperties.getEnterpriseEdition().isEnabled()) {
|
||||||
|
enterpriseEnbaledResult = false;
|
||||||
|
} else {
|
||||||
|
enterpriseEnbaledResult =
|
||||||
|
licenseService.verifyLicense(
|
||||||
|
applicationProperties.getEnterpriseEdition().getKey());
|
||||||
|
if (enterpriseEnbaledResult) {
|
||||||
|
log.info("License key is valid.");
|
||||||
|
} else {
|
||||||
|
log.info("License key is invalid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLicenseKey(String newKey) throws IOException {
|
||||||
|
applicationProperties.getEnterpriseEdition().setKey(newKey);
|
||||||
|
GeneralUtils.saveKeyToConfig("EnterpriseEdition.key", newKey, false);
|
||||||
|
checkLicense();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getEnterpriseEnabledResult() {
|
||||||
|
return enterpriseEnbaledResult;
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,9 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import io.github.pixee.security.SystemCommand;
|
import io.github.pixee.security.SystemCommand;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class LibreOfficeListener {
|
public class LibreOfficeListener {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(LibreOfficeListener.class);
|
private static final Logger logger = LoggerFactory.getLogger(LibreOfficeListener.class);
|
||||||
@ -31,7 +34,7 @@ public class LibreOfficeListener {
|
|||||||
private LibreOfficeListener() {}
|
private LibreOfficeListener() {}
|
||||||
|
|
||||||
private boolean isListenerRunning() {
|
private boolean isListenerRunning() {
|
||||||
System.out.println("waiting for listener to start");
|
log.info("waiting for listener to start");
|
||||||
try (Socket socket = new Socket()) {
|
try (Socket socket = new Socket()) {
|
||||||
socket.connect(
|
socket.connect(
|
||||||
new InetSocketAddress("localhost", 2002), 1000); // Timeout after 1 second
|
new InetSocketAddress("localhost", 2002), 1000); // Timeout after 1 second
|
||||||
|
@ -160,4 +160,27 @@ public class AppConfig {
|
|||||||
public String accessibilityStatement() {
|
public String accessibilityStatement() {
|
||||||
return applicationProperties.getLegal().getAccessibilityStatement();
|
return applicationProperties.getLegal().getAccessibilityStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "analyticsPrompt")
|
||||||
|
public boolean analyticsPrompt() {
|
||||||
|
return applicationProperties.getSystem().getEnableAnalytics() == null
|
||||||
|
|| "undefined".equals(applicationProperties.getSystem().getEnableAnalytics());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "analyticsEnabled")
|
||||||
|
public boolean analyticsEnabled() {
|
||||||
|
if (applicationProperties.getEnterpriseEdition().isEnabled()) return true;
|
||||||
|
return applicationProperties.getSystem().getEnableAnalytics() != null
|
||||||
|
&& Boolean.parseBoolean(applicationProperties.getSystem().getEnableAnalytics());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "StirlingPDFLabel")
|
||||||
|
public String stirlingPDFLabel() {
|
||||||
|
return "Stirling-PDF" + " v" + appVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "UUID")
|
||||||
|
public String uuid() {
|
||||||
|
return applicationProperties.getAutomaticallyGenerated().getUUID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.config.interfaces.ShowAdminInterface;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.utils.GeneralUtils;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
|
||||||
|
public class InitialSetup {
|
||||||
|
|
||||||
|
@Autowired private ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void initUUIDKey() throws IOException {
|
||||||
|
String uuid = applicationProperties.getAutomaticallyGenerated().getUUID();
|
||||||
|
if (!GeneralUtils.isValidUUID(uuid)) {
|
||||||
|
uuid = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
|
||||||
|
GeneralUtils.saveKeyToConfig("AutomaticallyGenerated.UUID", uuid);
|
||||||
|
applicationProperties.getAutomaticallyGenerated().setUUID(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void initSecretKey() throws IOException {
|
||||||
|
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
|
||||||
|
if (!GeneralUtils.isValidUUID(secretKey)) {
|
||||||
|
secretKey = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
|
||||||
|
GeneralUtils.saveKeyToConfig("AutomaticallyGenerated.key", secretKey);
|
||||||
|
applicationProperties.getAutomaticallyGenerated().setKey(secretKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
|||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class Beans implements WebMvcConfigurer {
|
public class LocaleConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
@ -13,6 +13,7 @@ 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 jakarta.servlet.http.HttpSession;
|
||||||
import stirling.software.SPDF.utils.RequestUriUtils;
|
import stirling.software.SPDF.utils.RequestUriUtils;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ -32,10 +33,11 @@ public class MetricsFilter extends OncePerRequestFilter {
|
|||||||
String uri = request.getRequestURI();
|
String uri = request.getRequestURI();
|
||||||
|
|
||||||
if (RequestUriUtils.isTrackableResource(request.getContextPath(), uri)) {
|
if (RequestUriUtils.isTrackableResource(request.getContextPath(), uri)) {
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
String sessionId = (session != null) ? session.getId() : "no-session";
|
||||||
Counter counter =
|
Counter counter =
|
||||||
Counter.builder("http.requests")
|
Counter.builder("http.requests")
|
||||||
.tag("session", request.getSession().getId())
|
.tag("session", sessionId)
|
||||||
.tag("method", request.getMethod())
|
.tag("method", request.getMethod())
|
||||||
.tag("uri", uri)
|
.tag("uri", uri)
|
||||||
.register(meterRegistry);
|
.register(meterRegistry);
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.posthog.java.PostHog;
|
||||||
|
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class PostHogConfig {
|
||||||
|
|
||||||
|
@Value("${posthog.api.key}")
|
||||||
|
private String posthogApiKey;
|
||||||
|
|
||||||
|
@Value("${posthog.host}")
|
||||||
|
private String posthogHost;
|
||||||
|
|
||||||
|
private PostHog postHogClient;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PostHog postHogClient() {
|
||||||
|
postHogClient = new PostHog.Builder(posthogApiKey).host(posthogHost).build();
|
||||||
|
return postHogClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void shutdownPostHog() {
|
||||||
|
if (postHogClient != null) {
|
||||||
|
postHogClient.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
// package stirling.software.SPDF.config.fingerprint;
|
||||||
|
//
|
||||||
|
// import java.io.IOException;
|
||||||
|
//
|
||||||
|
// import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
// import org.springframework.stereotype.Component;
|
||||||
|
// import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
//
|
||||||
|
// import jakarta.servlet.FilterChain;
|
||||||
|
// 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.utils.RequestUriUtils;
|
||||||
|
//
|
||||||
|
//// @Component
|
||||||
|
// @Slf4j
|
||||||
|
// public class FingerprintBasedSessionFilter extends OncePerRequestFilter {
|
||||||
|
// private final FingerprintGenerator fingerprintGenerator;
|
||||||
|
// private final FingerprintBasedSessionManager sessionManager;
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// public FingerprintBasedSessionFilter(
|
||||||
|
// FingerprintGenerator fingerprintGenerator,
|
||||||
|
// FingerprintBasedSessionManager sessionManager) {
|
||||||
|
// this.fingerprintGenerator = fingerprintGenerator;
|
||||||
|
// this.sessionManager = sessionManager;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// protected void doFilterInternal(
|
||||||
|
// HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
|
// throws ServletException, IOException {
|
||||||
|
//
|
||||||
|
// if (RequestUriUtils.isStaticResource(request.getContextPath(), request.getRequestURI())) {
|
||||||
|
// filterChain.doFilter(request, response);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// String fingerprint = fingerprintGenerator.generateFingerprint(request);
|
||||||
|
// log.debug("Generated fingerprint for request: {}", fingerprint);
|
||||||
|
//
|
||||||
|
// HttpSession session = request.getSession();
|
||||||
|
// boolean isNewSession = session.isNew();
|
||||||
|
// String sessionId = session.getId();
|
||||||
|
//
|
||||||
|
// if (isNewSession) {
|
||||||
|
// log.info("New session created: {}", sessionId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!sessionManager.isFingerPrintAllowed(fingerprint)) {
|
||||||
|
// log.info("Blocked fingerprint detected, redirecting: {}", fingerprint);
|
||||||
|
// response.sendRedirect(request.getContextPath() + "/too-many-requests");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// session.setAttribute("userFingerprint", fingerprint);
|
||||||
|
// session.setAttribute(
|
||||||
|
// FingerprintBasedSessionManager.STARTUP_TIMESTAMP,
|
||||||
|
// FingerprintBasedSessionManager.APP_STARTUP_TIME);
|
||||||
|
//
|
||||||
|
// sessionManager.registerFingerprint(fingerprint, sessionId);
|
||||||
|
//
|
||||||
|
// log.debug("Proceeding with request: {}", request.getRequestURI());
|
||||||
|
// filterChain.doFilter(request, response);
|
||||||
|
// }
|
||||||
|
// }
|
@ -0,0 +1,134 @@
|
|||||||
|
// package stirling.software.SPDF.config.fingerprint;
|
||||||
|
//
|
||||||
|
// import java.util.Iterator;
|
||||||
|
// import java.util.Map;
|
||||||
|
// import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
// import java.util.concurrent.TimeUnit;
|
||||||
|
//
|
||||||
|
// import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
// import org.springframework.stereotype.Component;
|
||||||
|
//
|
||||||
|
// import jakarta.servlet.http.HttpSession;
|
||||||
|
// import jakarta.servlet.http.HttpSessionAttributeListener;
|
||||||
|
// import jakarta.servlet.http.HttpSessionEvent;
|
||||||
|
// import jakarta.servlet.http.HttpSessionListener;
|
||||||
|
// import lombok.AllArgsConstructor;
|
||||||
|
// import lombok.Data;
|
||||||
|
// import lombok.extern.slf4j.Slf4j;
|
||||||
|
//
|
||||||
|
// @Slf4j
|
||||||
|
// @Component
|
||||||
|
// public class FingerprintBasedSessionManager
|
||||||
|
// implements HttpSessionListener, HttpSessionAttributeListener {
|
||||||
|
// private static final ConcurrentHashMap<String, FingerprintInfo> activeFingerprints =
|
||||||
|
// new ConcurrentHashMap<>();
|
||||||
|
//
|
||||||
|
// // To be reduced in later version to 8~
|
||||||
|
// private static final int MAX_ACTIVE_FINGERPRINTS = 30;
|
||||||
|
//
|
||||||
|
// static final String STARTUP_TIMESTAMP = "appStartupTimestamp";
|
||||||
|
// static final long APP_STARTUP_TIME = System.currentTimeMillis();
|
||||||
|
// private static final long FINGERPRINT_EXPIRATION = TimeUnit.MINUTES.toMillis(30);
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void sessionCreated(HttpSessionEvent se) {
|
||||||
|
// HttpSession session = se.getSession();
|
||||||
|
// String sessionId = session.getId();
|
||||||
|
// String fingerprint = (String) session.getAttribute("userFingerprint");
|
||||||
|
//
|
||||||
|
// if (fingerprint == null) {
|
||||||
|
// log.warn("Session created without fingerprint: {}", sessionId);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// synchronized (activeFingerprints) {
|
||||||
|
// if (activeFingerprints.size() >= MAX_ACTIVE_FINGERPRINTS
|
||||||
|
// && !activeFingerprints.containsKey(fingerprint)) {
|
||||||
|
// log.info("Max fingerprints reached. Marking session as blocked: {}", sessionId);
|
||||||
|
// session.setAttribute("blocked", true);
|
||||||
|
// } else {
|
||||||
|
// activeFingerprints.put(
|
||||||
|
// fingerprint, new FingerprintInfo(sessionId, System.currentTimeMillis()));
|
||||||
|
// log.info(
|
||||||
|
// "New fingerprint registered: {}. Total active fingerprints: {}",
|
||||||
|
// fingerprint,
|
||||||
|
// activeFingerprints.size());
|
||||||
|
// }
|
||||||
|
// session.setAttribute(STARTUP_TIMESTAMP, APP_STARTUP_TIME);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void sessionDestroyed(HttpSessionEvent se) {
|
||||||
|
// HttpSession session = se.getSession();
|
||||||
|
// String fingerprint = (String) session.getAttribute("userFingerprint");
|
||||||
|
//
|
||||||
|
// if (fingerprint != null) {
|
||||||
|
// synchronized (activeFingerprints) {
|
||||||
|
// activeFingerprints.remove(fingerprint);
|
||||||
|
// log.info(
|
||||||
|
// "Fingerprint removed: {}. Total active fingerprints: {}",
|
||||||
|
// fingerprint,
|
||||||
|
// activeFingerprints.size());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public boolean isFingerPrintAllowed(String fingerprint) {
|
||||||
|
// synchronized (activeFingerprints) {
|
||||||
|
// return activeFingerprints.size() < MAX_ACTIVE_FINGERPRINTS
|
||||||
|
// || activeFingerprints.containsKey(fingerprint);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void registerFingerprint(String fingerprint, String sessionId) {
|
||||||
|
// synchronized (activeFingerprints) {
|
||||||
|
// activeFingerprints.put(
|
||||||
|
// fingerprint, new FingerprintInfo(sessionId, System.currentTimeMillis()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void unregisterFingerprint(String fingerprint) {
|
||||||
|
// synchronized (activeFingerprints) {
|
||||||
|
// activeFingerprints.remove(fingerprint);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Scheduled(fixedRate = 1800000) // Run every 30 mins
|
||||||
|
// public void cleanupStaleFingerprints() {
|
||||||
|
// log.info("Starting cleanup of stale fingerprints");
|
||||||
|
// long now = System.currentTimeMillis();
|
||||||
|
// int removedCount = 0;
|
||||||
|
//
|
||||||
|
// synchronized (activeFingerprints) {
|
||||||
|
// Iterator<Map.Entry<String, FingerprintInfo>> iterator =
|
||||||
|
// activeFingerprints.entrySet().iterator();
|
||||||
|
// while (iterator.hasNext()) {
|
||||||
|
// Map.Entry<String, FingerprintInfo> entry = iterator.next();
|
||||||
|
// FingerprintInfo info = entry.getValue();
|
||||||
|
//
|
||||||
|
// if (now - info.getLastAccessTime() > FINGERPRINT_EXPIRATION) {
|
||||||
|
// iterator.remove();
|
||||||
|
// removedCount++;
|
||||||
|
// log.info("Removed stale fingerprint: {}", entry.getKey());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// log.info("Cleanup complete. Removed {} stale fingerprints", removedCount);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void updateLastAccessTime(String fingerprint) {
|
||||||
|
// FingerprintInfo info = activeFingerprints.get(fingerprint);
|
||||||
|
// if (info != null) {
|
||||||
|
// info.setLastAccessTime(System.currentTimeMillis());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Data
|
||||||
|
// @AllArgsConstructor
|
||||||
|
// private static class FingerprintInfo {
|
||||||
|
// private String sessionId;
|
||||||
|
// private long lastAccessTime;
|
||||||
|
// }
|
||||||
|
// }
|
@ -0,0 +1,77 @@
|
|||||||
|
// package stirling.software.SPDF.config.fingerprint;
|
||||||
|
//
|
||||||
|
// import java.security.MessageDigest;
|
||||||
|
// import java.security.NoSuchAlgorithmException;
|
||||||
|
//
|
||||||
|
// import org.springframework.stereotype.Component;
|
||||||
|
//
|
||||||
|
// import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
//
|
||||||
|
// @Component
|
||||||
|
// public class FingerprintGenerator {
|
||||||
|
//
|
||||||
|
// public String generateFingerprint(HttpServletRequest request) {
|
||||||
|
// if (request == null) {
|
||||||
|
// return "";
|
||||||
|
// }
|
||||||
|
// StringBuilder fingerprintBuilder = new StringBuilder();
|
||||||
|
//
|
||||||
|
// // Add IP address
|
||||||
|
// fingerprintBuilder.append(request.getRemoteAddr());
|
||||||
|
//
|
||||||
|
// // Add X-Forwarded-For header if present (for clients behind proxies)
|
||||||
|
// String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||||
|
// if (forwardedFor != null) {
|
||||||
|
// fingerprintBuilder.append(forwardedFor);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add User-Agent
|
||||||
|
// String userAgent = request.getHeader("User-Agent");
|
||||||
|
// if (userAgent != null) {
|
||||||
|
// fingerprintBuilder.append(userAgent);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add Accept-Language header
|
||||||
|
// String acceptLanguage = request.getHeader("Accept-Language");
|
||||||
|
// if (acceptLanguage != null) {
|
||||||
|
// fingerprintBuilder.append(acceptLanguage);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add Accept header
|
||||||
|
// String accept = request.getHeader("Accept");
|
||||||
|
// if (accept != null) {
|
||||||
|
// fingerprintBuilder.append(accept);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add Connection header
|
||||||
|
// String connection = request.getHeader("Connection");
|
||||||
|
// if (connection != null) {
|
||||||
|
// fingerprintBuilder.append(connection);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add server port
|
||||||
|
// fingerprintBuilder.append(request.getServerPort());
|
||||||
|
//
|
||||||
|
// // Add secure flag
|
||||||
|
// fingerprintBuilder.append(request.isSecure());
|
||||||
|
//
|
||||||
|
// // Generate a hash of the fingerprint
|
||||||
|
// return generateHash(fingerprintBuilder.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private String generateHash(String input) {
|
||||||
|
// try {
|
||||||
|
// MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||||
|
// byte[] hash = digest.digest(input.getBytes());
|
||||||
|
// StringBuilder hexString = new StringBuilder();
|
||||||
|
// for (byte b : hash) {
|
||||||
|
// String hex = Integer.toHexString(0xff & b);
|
||||||
|
// if (hex.length() == 1) hexString.append('0');
|
||||||
|
// hexString.append(hex);
|
||||||
|
// }
|
||||||
|
// return hexString.toString();
|
||||||
|
// } catch (NoSuchAlgorithmException e) {
|
||||||
|
// throw new RuntimeException("Failed to generate fingerprint hash", e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
@ -1,4 +1,4 @@
|
|||||||
package stirling.software.SPDF.config;
|
package stirling.software.SPDF.config.interfaces;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -1,4 +1,4 @@
|
|||||||
package stirling.software.SPDF.config;
|
package stirling.software.SPDF.config.interfaces;
|
||||||
|
|
||||||
public interface ShowAdminInterface {
|
public interface ShowAdminInterface {
|
||||||
default boolean getShowUpdateOnlyAdmins() {
|
default boolean getShowUpdateOnlyAdmins() {
|
@ -7,7 +7,7 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.ShowAdminInterface;
|
import stirling.software.SPDF.config.interfaces.ShowAdminInterface;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
import stirling.software.SPDF.repository.UserRepository;
|
import stirling.software.SPDF.repository.UserRepository;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -14,9 +16,12 @@ 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 jakarta.servlet.http.HttpSession;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
import stirling.software.SPDF.utils.RequestUriUtils;
|
import stirling.software.SPDF.utils.RequestUriUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class FirstLoginFilter extends OncePerRequestFilter {
|
public class FirstLoginFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
@ -50,6 +55,22 @@ public class FirstLoginFilter extends OncePerRequestFilter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
HttpSession session = request.getSession(true);
|
||||||
|
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
String creationTime = timeFormat.format(new Date(session.getCreationTime()));
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Request Info - New: {}, creationTimeSession {}, ID: {}, IP: {}, User-Agent: {}, Referer: {}, Request URL: {}",
|
||||||
|
session.isNew(),
|
||||||
|
creationTime,
|
||||||
|
session.getId(),
|
||||||
|
request.getRemoteAddr(),
|
||||||
|
request.getHeader("User-Agent"),
|
||||||
|
request.getHeader("Referer"),
|
||||||
|
request.getRequestURL().toString());
|
||||||
|
}
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.simpleyaml.configuration.file.YamlFile;
|
|
||||||
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
|
|
||||||
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.DatabaseBackupInterface;
|
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.Role;
|
import stirling.software.SPDF.model.Role;
|
||||||
|
|
||||||
@ -39,15 +34,6 @@ public class InitialSecuritySetup {
|
|||||||
initializeInternalApiUser();
|
initializeInternalApiUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void initSecretKey() throws IOException {
|
|
||||||
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
|
|
||||||
if (!isValidUUID(secretKey)) {
|
|
||||||
secretKey = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
|
|
||||||
saveKeyToConfig(secretKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeAdminUser() throws IOException {
|
private void initializeAdminUser() throws IOException {
|
||||||
String initialUsername =
|
String initialUsername =
|
||||||
applicationProperties.getSecurity().getInitialLogin().getUsername();
|
applicationProperties.getSecurity().getInitialLogin().getUsername();
|
||||||
@ -89,33 +75,4 @@ public class InitialSecuritySetup {
|
|||||||
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
|
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveKeyToConfig(String key) throws IOException {
|
|
||||||
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
|
|
||||||
|
|
||||||
final YamlFile settingsYml = new YamlFile(path.toFile());
|
|
||||||
DumperOptions yamlOptionssettingsYml =
|
|
||||||
((SimpleYamlImplementation) settingsYml.getImplementation()).getDumperOptions();
|
|
||||||
yamlOptionssettingsYml.setSplitLines(false);
|
|
||||||
|
|
||||||
settingsYml.loadWithComments();
|
|
||||||
|
|
||||||
settingsYml
|
|
||||||
.path("AutomaticallyGenerated.key")
|
|
||||||
.set(key)
|
|
||||||
.comment("# Automatically Generated Settings (Do Not Edit Directly)");
|
|
||||||
settingsYml.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidUUID(String uuid) {
|
|
||||||
if (uuid == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
UUID.fromString(uuid);
|
|
||||||
return true;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,57 +1,55 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
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.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
|
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.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.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
|
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
|
||||||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import 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.CustomOAuth2LogoutSuccessHandler;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
||||||
|
import stirling.software.SPDF.config.security.saml.ConvertResponseToAuthentication;
|
||||||
|
import stirling.software.SPDF.config.security.saml.CustomSAMLAuthenticationFailureHandler;
|
||||||
|
import stirling.software.SPDF.config.security.saml.CustomSAMLAuthenticationSuccessHandler;
|
||||||
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.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
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
|
@Slf4j
|
||||||
public class SecurityConfiguration {
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
@Autowired private CustomUserDetailsService userDetailsService;
|
@Autowired private CustomUserDetailsService userDetailsService;
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
|
@Autowired(required = false)
|
||||||
|
private GrantedAuthoritiesMapper userAuthoritiesMapper;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
@ -73,13 +71,18 @@ 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.addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
http.authenticationManager(authenticationManager(http));
|
||||||
|
|
||||||
if (loginEnabledValue) {
|
if (loginEnabledValue) {
|
||||||
|
http.addFilterBefore(
|
||||||
http.csrf(csrf -> csrf.disable());
|
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
||||||
|
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(
|
||||||
@ -135,6 +138,7 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
return trimmedUri.startsWith("/login")
|
return trimmedUri.startsWith("/login")
|
||||||
|| trimmedUri.startsWith("/oauth")
|
|| trimmedUri.startsWith("/oauth")
|
||||||
|
|| trimmedUri.startsWith("/saml2")
|
||||||
|| trimmedUri.endsWith(".svg")
|
|| trimmedUri.endsWith(".svg")
|
||||||
|| trimmedUri.startsWith(
|
|| trimmedUri.startsWith(
|
||||||
"/register")
|
"/register")
|
||||||
@ -184,191 +188,82 @@ public class SecurityConfiguration {
|
|||||||
userService,
|
userService,
|
||||||
loginAttemptService))
|
loginAttemptService))
|
||||||
.userAuthoritiesMapper(
|
.userAuthoritiesMapper(
|
||||||
userAuthoritiesMapper())))
|
userAuthoritiesMapper)))
|
||||||
.logout(
|
.logout(
|
||||||
logout ->
|
logout ->
|
||||||
logout.logoutSuccessHandler(
|
logout.logoutSuccessHandler(
|
||||||
new CustomOAuth2LogoutSuccessHandler(
|
new CustomOAuth2LogoutSuccessHandler(
|
||||||
applicationProperties)));
|
applicationProperties)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle SAML
|
||||||
|
if (applicationProperties.getSecurity().getSaml() != null
|
||||||
|
&& applicationProperties.getSecurity().getSaml().getEnabled()
|
||||||
|
&& !applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getLoginMethod()
|
||||||
|
.equalsIgnoreCase("normal")) {
|
||||||
|
http.saml2Login(
|
||||||
|
saml2 -> {
|
||||||
|
saml2.loginPage("/saml2")
|
||||||
|
.relyingPartyRegistrationRepository(
|
||||||
|
relyingPartyRegistrationRepository)
|
||||||
|
.successHandler(
|
||||||
|
new CustomSAMLAuthenticationSuccessHandler(
|
||||||
|
loginAttemptService,
|
||||||
|
userService,
|
||||||
|
applicationProperties))
|
||||||
|
.failureHandler(
|
||||||
|
new CustomSAMLAuthenticationFailureHandler());
|
||||||
|
})
|
||||||
|
.addFilterBefore(
|
||||||
|
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
http.csrf(csrf -> csrf.disable())
|
if (applicationProperties.getSecurity().getCsrfDisabled()) {
|
||||||
.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
http.csrf(csrf -> csrf.disable());
|
||||||
|
}
|
||||||
|
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client Registration Repository for OAUTH2 OIDC Login
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(
|
@ConditionalOnProperty(
|
||||||
value = "security.oauth2.enabled",
|
name = "security.saml.enabled",
|
||||||
havingValue = "true",
|
havingValue = "true",
|
||||||
matchIfMissing = false)
|
matchIfMissing = false)
|
||||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
public AuthenticationProvider samlAuthenticationProvider() {
|
||||||
List<ClientRegistration> registrations = new ArrayList<>();
|
OpenSaml4AuthenticationProvider authenticationProvider =
|
||||||
|
new OpenSaml4AuthenticationProvider();
|
||||||
githubClientRegistration().ifPresent(registrations::add);
|
authenticationProvider.setResponseAuthenticationConverter(convertResponseToAuthentication);
|
||||||
oidcClientRegistration().ifPresent(registrations::add);
|
return authenticationProvider;
|
||||||
googleClientRegistration().ifPresent(registrations::add);
|
|
||||||
keycloakClientRegistration().ifPresent(registrations::add);
|
|
||||||
|
|
||||||
if (registrations.isEmpty()) {
|
|
||||||
logger.error("At least one OAuth2 provider must be configured");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new InMemoryClientRegistrationRepository(registrations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<ClientRegistration> googleClientRegistration() {
|
// @Bean
|
||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
|
// public AuthenticationProvider daoAuthenticationProvider() {
|
||||||
if (oauth == null || !oauth.getEnabled()) {
|
// DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||||
return Optional.empty();
|
// provider.setUserDetailsService(userDetailsService); // UserDetailsService
|
||||||
}
|
// provider.setPasswordEncoder(passwordEncoder()); // PasswordEncoder
|
||||||
Client client = oauth.getClient();
|
// return provider;
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
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 -> {
|
// authenticationManagerBuilder.authenticationProvider(
|
||||||
// Add existing OAUTH2 Authorities
|
// daoAuthenticationProvider()); // Benutzername/Passwort
|
||||||
mappedAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
|
|
||||||
|
|
||||||
// Add Authorities from database for existing user, if user is present.
|
if (applicationProperties.getSecurity().getSaml() != null
|
||||||
if (authority instanceof OAuth2UserAuthority oauth2Auth) {
|
&& applicationProperties.getSecurity().getSaml().getEnabled()) {
|
||||||
String useAsUsername =
|
authenticationManagerBuilder.authenticationProvider(
|
||||||
applicationProperties
|
samlAuthenticationProvider()); // SAML
|
||||||
.getSecurity()
|
}
|
||||||
.getOauth2()
|
return authenticationManagerBuilder.build();
|
||||||
.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
|
||||||
@ -386,4 +281,14 @@ public class SecurityConfiguration {
|
|||||||
public boolean activSecurity() {
|
public boolean activSecurity() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Only Dev test
|
||||||
|
// @Bean
|
||||||
|
// public WebSecurityCustomizer webSecurityCustomizer() {
|
||||||
|
// return (web) ->
|
||||||
|
// web.ignoring()
|
||||||
|
// .requestMatchers(
|
||||||
|
// "/css/**", "/images/**", "/js/**", "/**.svg",
|
||||||
|
// "/pdfjs-legacy/**");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -30,13 +29,18 @@ import stirling.software.SPDF.model.User;
|
|||||||
@Component
|
@Component
|
||||||
public class UserAuthenticationFilter extends OncePerRequestFilter {
|
public class UserAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
@Autowired @Lazy private UserService userService;
|
private final UserService userService;
|
||||||
|
private final SessionPersistentRegistry sessionPersistentRegistry;
|
||||||
|
private final boolean loginEnabledValue;
|
||||||
|
|
||||||
@Autowired private SessionPersistentRegistry sessionPersistentRegistry;
|
public UserAuthenticationFilter(
|
||||||
|
@Lazy UserService userService,
|
||||||
@Autowired
|
SessionPersistentRegistry sessionPersistentRegistry,
|
||||||
@Qualifier("loginEnabled")
|
@Qualifier("loginEnabled") boolean loginEnabledValue) {
|
||||||
public boolean loginEnabledValue;
|
this.userService = userService;
|
||||||
|
this.sessionPersistentRegistry = sessionPersistentRegistry;
|
||||||
|
this.loginEnabledValue = loginEnabledValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(
|
protected void doFilterInternal(
|
||||||
@ -51,6 +55,19 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
|
// Check for session expiration (unsure if needed)
|
||||||
|
// if (authentication != null && authentication.isAuthenticated()) {
|
||||||
|
// String sessionId = request.getSession().getId();
|
||||||
|
// SessionInformation sessionInfo =
|
||||||
|
// sessionPersistentRegistry.getSessionInformation(sessionId);
|
||||||
|
//
|
||||||
|
// if (sessionInfo != null && sessionInfo.isExpired()) {
|
||||||
|
// SecurityContextHolder.clearContext();
|
||||||
|
// response.sendRedirect(request.getContextPath() + "/login?expired=true");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// Check for API key in the request headers if no authentication exists
|
// Check for API key in the request headers if no authentication exists
|
||||||
if (authentication == null || !authentication.isAuthenticated()) {
|
if (authentication == null || !authentication.isAuthenticated()) {
|
||||||
String apiKey = request.getHeader("X-API-Key");
|
String apiKey = request.getHeader("X-API-Key");
|
||||||
|
@ -19,7 +19,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
|||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.DatabaseBackupInterface;
|
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
||||||
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;
|
||||||
@ -44,6 +44,10 @@ 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 {
|
||||||
|
@ -24,7 +24,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.config.DatabaseBackupInterface;
|
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
|
||||||
import stirling.software.SPDF.utils.FileInfo;
|
import stirling.software.SPDF.utils.FileInfo;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Object> 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,42 @@
|
|||||||
|
package stirling.software.SPDF.config.security.saml;
|
||||||
|
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
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.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.RelyingPartyRegistrations;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class SamlConfig {
|
||||||
|
|
||||||
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(
|
||||||
|
value = "security.saml.enabled",
|
||||||
|
havingValue = "true",
|
||||||
|
matchIfMissing = false)
|
||||||
|
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository()
|
||||||
|
throws CertificateException {
|
||||||
|
RelyingPartyRegistration registration =
|
||||||
|
RelyingPartyRegistrations.fromMetadataLocation(
|
||||||
|
applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getSaml()
|
||||||
|
.getIdpMetadataLocation())
|
||||||
|
.entityId(applicationProperties.getSecurity().getSaml().getEntityId())
|
||||||
|
.registrationId(
|
||||||
|
applicationProperties.getSecurity().getSaml().getRegistrationId())
|
||||||
|
.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;
|
||||||
|
}
|
@ -11,16 +11,19 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class CustomHttpSessionListener implements HttpSessionListener {
|
public class CustomHttpSessionListener implements HttpSessionListener {
|
||||||
|
|
||||||
@Autowired private SessionPersistentRegistry sessionPersistentRegistry;
|
private SessionPersistentRegistry sessionPersistentRegistry;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) {
|
||||||
|
super();
|
||||||
|
this.sessionPersistentRegistry = sessionPersistentRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sessionCreated(HttpSessionEvent se) {
|
public void sessionCreated(HttpSessionEvent se) {}
|
||||||
log.info("Session created: " + se.getSession().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sessionDestroyed(HttpSessionEvent se) {
|
public void sessionDestroyed(HttpSessionEvent se) {
|
||||||
log.info("Session destroyed: " + se.getSession().getId());
|
|
||||||
sessionPersistentRegistry.expireSession(se.getSession().getId());
|
sessionPersistentRegistry.expireSession(se.getSession().getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,14 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (principalName != null) {
|
if (principalName != null) {
|
||||||
|
// Clear old sessions for the principal (unsure if needed)
|
||||||
|
// List<SessionEntity> existingSessions =
|
||||||
|
// sessionRepository.findByPrincipalName(principalName);
|
||||||
|
// for (SessionEntity session : existingSessions) {
|
||||||
|
// session.setExpired(true);
|
||||||
|
// sessionRepository.save(session);
|
||||||
|
// }
|
||||||
|
|
||||||
SessionEntity sessionEntity = new SessionEntity();
|
SessionEntity sessionEntity = new SessionEntity();
|
||||||
sessionEntity.setSessionId(sessionId);
|
sessionEntity.setSessionId(sessionId);
|
||||||
sessionEntity.setPrincipalName(principalName);
|
sessionEntity.setPrincipalName(principalName);
|
||||||
|
@ -25,6 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import stirling.software.SPDF.model.api.general.CropPdfForm;
|
import stirling.software.SPDF.model.api.general.CropPdfForm;
|
||||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
import stirling.software.SPDF.service.CustomPDDocumentFactory;
|
||||||
|
import stirling.software.SPDF.service.PostHogService;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -36,9 +37,13 @@ public class CropController {
|
|||||||
|
|
||||||
private final CustomPDDocumentFactory pdfDocumentFactory;
|
private final CustomPDDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
|
private final PostHogService postHogService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public CropController(CustomPDDocumentFactory pdfDocumentFactory) {
|
public CropController(
|
||||||
|
CustomPDDocumentFactory pdfDocumentFactory, PostHogService postHogService) {
|
||||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
this.pdfDocumentFactory = pdfDocumentFactory;
|
||||||
|
this.postHogService = postHogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/crop", consumes = "multipart/form-data")
|
@PostMapping(value = "/crop", consumes = "multipart/form-data")
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.utils.GeneralUtils;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@Tag(name = "Settings", description = "Settings APIs")
|
||||||
|
@RequestMapping("/api/v1/settings")
|
||||||
|
@Hidden
|
||||||
|
public class SettingsController {
|
||||||
|
|
||||||
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@PostMapping("/update-enable-analytics")
|
||||||
|
@Hidden
|
||||||
|
public ResponseEntity<String> updateApiKey(@RequestBody Boolean enabled) throws IOException {
|
||||||
|
if (!"undefined".equals(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
|
return ResponseEntity.status(HttpStatus.ALREADY_REPORTED)
|
||||||
|
.body(
|
||||||
|
"Setting has already been set, To adjust please edit /config/settings.yml");
|
||||||
|
}
|
||||||
|
GeneralUtils.saveKeyToConfig("system.enableAnalytics", String.valueOf(enabled), false);
|
||||||
|
applicationProperties.getSystem().setEnableAnalytics(String.valueOf(enabled));
|
||||||
|
return ResponseEntity.ok("Updated");
|
||||||
|
}
|
||||||
|
}
|
@ -60,8 +60,6 @@ public class SplitPDFController {
|
|||||||
// PdfMetadata metadata = PdfMetadataService.extractMetadataFromPdf(document);
|
// PdfMetadata metadata = PdfMetadataService.extractMetadataFromPdf(document);
|
||||||
int totalPages = document.getNumberOfPages();
|
int totalPages = document.getNumberOfPages();
|
||||||
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
|
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
|
||||||
System.out.println(
|
|
||||||
pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
|
||||||
if (!pageNumbers.contains(totalPages - 1)) {
|
if (!pageNumbers.contains(totalPages - 1)) {
|
||||||
// Create a mutable ArrayList so we can add to it
|
// Create a mutable ArrayList so we can add to it
|
||||||
pageNumbers = new ArrayList<>(pageNumbers);
|
pageNumbers = new ArrayList<>(pageNumbers);
|
||||||
|
@ -32,9 +32,9 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import stirling.software.SPDF.config.PdfMetadataService;
|
|
||||||
import stirling.software.SPDF.model.PdfMetadata;
|
import stirling.software.SPDF.model.PdfMetadata;
|
||||||
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
|
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
|
||||||
|
import stirling.software.SPDF.service.PdfMetadataService;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -30,6 +30,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
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.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
@ -40,6 +41,7 @@ import stirling.software.SPDF.model.api.user.UsernameAndPass;
|
|||||||
@Controller
|
@Controller
|
||||||
@Tag(name = "User", description = "User APIs")
|
@Tag(name = "User", description = "User APIs")
|
||||||
@RequestMapping("/api/v1/user")
|
@RequestMapping("/api/v1/user")
|
||||||
|
@Slf4j
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
@Autowired private UserService userService;
|
@Autowired private UserService userService;
|
||||||
@ -191,13 +193,11 @@ public class UserController {
|
|||||||
Map<String, String[]> paramMap = request.getParameterMap();
|
Map<String, String[]> paramMap = request.getParameterMap();
|
||||||
Map<String, String> updates = new HashMap<>();
|
Map<String, String> updates = new HashMap<>();
|
||||||
|
|
||||||
System.out.println("Received parameter map: " + paramMap);
|
|
||||||
|
|
||||||
for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
|
for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
|
||||||
updates.put(entry.getKey(), entry.getValue()[0]);
|
updates.put(entry.getKey(), entry.getValue()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Processed updates: " + updates);
|
log.debug("Processed updates: " + updates);
|
||||||
|
|
||||||
// Assuming you have a method in userService to update the settings for a user
|
// Assuming you have a method in userService to update the settings for a user
|
||||||
userService.updateUserSettings(principal.getName(), updates);
|
userService.updateUserSettings(principal.getName(), updates);
|
||||||
@ -209,7 +209,7 @@ public class UserController {
|
|||||||
@PostMapping("/admin/saveUser")
|
@PostMapping("/admin/saveUser")
|
||||||
public RedirectView saveUser(
|
public RedirectView saveUser(
|
||||||
@RequestParam(name = "username", required = true) String username,
|
@RequestParam(name = "username", required = true) String username,
|
||||||
@RequestParam(name = "password", required = true) String password,
|
@RequestParam(name = "password", required = false) String password,
|
||||||
@RequestParam(name = "role") String role,
|
@RequestParam(name = "role") String role,
|
||||||
@RequestParam(name = "authType") String authType,
|
@RequestParam(name = "authType") String authType,
|
||||||
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
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;
|
||||||
@ -14,7 +15,6 @@ 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,6 +66,8 @@ 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,27 +1,39 @@
|
|||||||
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;
|
||||||
|
|
||||||
// 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 ConvertHtmlToPDF {
|
public class ConvertHtmlToPDF {
|
||||||
|
|
||||||
// @Autowired
|
private final boolean bookAndHtmlFormatsInstalled;
|
||||||
@Qualifier("bookAndHtmlFormatsInstalled")
|
|
||||||
private boolean bookAndHtmlFormatsInstalled;
|
private final CustomPDDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
|
@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(
|
||||||
@ -49,6 +61,8 @@ 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
|
||||||
|
@ -10,28 +10,40 @@ 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;
|
||||||
|
|
||||||
// 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 ConvertMarkdownToPdf {
|
public class ConvertMarkdownToPdf {
|
||||||
|
|
||||||
// @Autowired
|
private final boolean bookAndHtmlFormatsInstalled;
|
||||||
@Qualifier("bookAndHtmlFormatsInstalled")
|
|
||||||
private boolean bookAndHtmlFormatsInstalled;
|
private final CustomPDDocumentFactory pdfDocumentFactory;
|
||||||
|
|
||||||
|
@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(
|
||||||
@ -70,7 +82,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,6 +6,7 @@ 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;
|
||||||
@ -20,13 +21,12 @@ 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;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class ConvertPDFToPDFA {
|
|||||||
command.add("-dPDFA=" + ("pdfa".equals(outputFormat) ? "2" : "1"));
|
command.add("-dPDFA=" + ("pdfa".equals(outputFormat) ? "2" : "1"));
|
||||||
command.add("-dNOPAUSE");
|
command.add("-dNOPAUSE");
|
||||||
command.add("-dBATCH");
|
command.add("-dBATCH");
|
||||||
command.add("-sColorConversionStrategy=UseDeviceIndependentColor");
|
command.add("-sColorConversionStrategy=sRGB");
|
||||||
command.add("-sDEVICE=pdfwrite");
|
command.add("-sDEVICE=pdfwrite");
|
||||||
command.add("-dPDFACompatibilityPolicy=2");
|
command.add("-dPDFACompatibilityPolicy=2");
|
||||||
command.add("-o");
|
command.add("-o");
|
||||||
|
@ -60,8 +60,6 @@ public class ExtractImagesController {
|
|||||||
MultipartFile file = request.getFileInput();
|
MultipartFile file = request.getFileInput();
|
||||||
String format = request.getFormat();
|
String format = request.getFormat();
|
||||||
boolean allowDuplicates = request.isAllowDuplicates();
|
boolean allowDuplicates = request.isAllowDuplicates();
|
||||||
System.out.println(
|
|
||||||
System.currentTimeMillis() + " file=" + file.getName() + ", format=" + format);
|
|
||||||
PDDocument document = Loader.loadPDF(file.getBytes());
|
PDDocument document = Loader.loadPDF(file.getBytes());
|
||||||
|
|
||||||
// Determine if multithreading should be used based on PDF size or number of pages
|
// Determine if multithreading should be used based on PDF size or number of pages
|
||||||
|
@ -26,11 +26,13 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/misc")
|
@RequestMapping("/api/v1/misc")
|
||||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||||
|
@Slf4j
|
||||||
public class PrintFileController {
|
public class PrintFileController {
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@ -59,7 +61,7 @@ public class PrintFileController {
|
|||||||
new IllegalArgumentException(
|
new IllegalArgumentException(
|
||||||
"No matching printer found"));
|
"No matching printer found"));
|
||||||
|
|
||||||
System.out.println("Selected Printer: " + selectedService.getName());
|
log.info("Selected Printer: " + selectedService.getName());
|
||||||
|
|
||||||
if ("application/pdf".equals(contentType)) {
|
if ("application/pdf".equals(contentType)) {
|
||||||
PDDocument document = Loader.loadPDF(file.getBytes());
|
PDDocument document = Loader.loadPDF(file.getBytes());
|
||||||
|
@ -58,7 +58,6 @@ public class RedactController {
|
|||||||
float customPadding = request.getCustomPadding();
|
float customPadding = request.getCustomPadding();
|
||||||
boolean convertPDFToImage = request.isConvertPDFToImage();
|
boolean convertPDFToImage = request.isConvertPDFToImage();
|
||||||
|
|
||||||
System.out.println(listOfTextString);
|
|
||||||
String[] listOfText = listOfTextString.split("\n");
|
String[] listOfText = listOfTextString.split("\n");
|
||||||
PDDocument document = pdfDocumentFactory.load(file);
|
PDDocument document = pdfDocumentFactory.load(file);
|
||||||
|
|
||||||
@ -75,7 +74,6 @@ public class RedactController {
|
|||||||
|
|
||||||
for (String text : listOfText) {
|
for (String text : listOfText) {
|
||||||
text = text.trim();
|
text = text.trim();
|
||||||
System.out.println(text);
|
|
||||||
TextFinder textFinder = new TextFinder(text, useRegex, wholeWordSearchBool);
|
TextFinder textFinder = new TextFinder(text, useRegex, wholeWordSearchBool);
|
||||||
List<PDFText> foundTexts = textFinder.getTextLocations(document);
|
List<PDFText> foundTexts = textFinder.getTextLocations(document);
|
||||||
redactFoundText(document, foundTexts, customPadding, redactColor);
|
redactFoundText(document, foundTexts, customPadding, redactColor);
|
||||||
|
@ -108,6 +108,13 @@ public class GeneralWebController {
|
|||||||
return "split-pdf-by-sections";
|
return "split-pdf-by-sections";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/split-pdf-by-chapters")
|
||||||
|
@Hidden
|
||||||
|
public String splitPdfByChapters(Model model) {
|
||||||
|
model.addAttribute("currentPage", "split-pdf-by-chapters");
|
||||||
|
return "split-pdf-by-chapters";
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/view-pdf")
|
@GetMapping("/view-pdf")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String ViewPdfForm2(Model model) {
|
public String ViewPdfForm2(Model model) {
|
||||||
|
@ -11,6 +11,11 @@ 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.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.ToString;
|
import lombok.ToString;
|
||||||
@ -24,6 +29,7 @@ import stirling.software.SPDF.model.provider.UnsupportedProviderException;
|
|||||||
@ConfigurationProperties(prefix = "")
|
@ConfigurationProperties(prefix = "")
|
||||||
@PropertySource(value = "file:./configs/settings.yml", factory = YamlPropertySourceFactory.class)
|
@PropertySource(value = "file:./configs/settings.yml", factory = YamlPropertySourceFactory.class)
|
||||||
@Data
|
@Data
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
public class ApplicationProperties {
|
public class ApplicationProperties {
|
||||||
|
|
||||||
private Legal legal = new Legal();
|
private Legal legal = new Legal();
|
||||||
@ -57,6 +63,7 @@ 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 SAML saml = new SAML();
|
||||||
private int loginAttemptCount;
|
private int loginAttemptCount;
|
||||||
private long loginResetTimeMinutes;
|
private long loginResetTimeMinutes;
|
||||||
private String loginMethod = "all";
|
private String loginMethod = "all";
|
||||||
@ -67,6 +74,34 @@ public class ApplicationProperties {
|
|||||||
@ToString.Exclude private String password;
|
@ToString.Exclude private String password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SAML {
|
||||||
|
private Boolean enabled = false;
|
||||||
|
private String entityId;
|
||||||
|
private String registrationId;
|
||||||
|
private String spBaseUrl;
|
||||||
|
private String idpMetadataLocation;
|
||||||
|
private KeyStore keystore;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class KeyStore {
|
||||||
|
private String keystoreLocation;
|
||||||
|
private String keystorePassword;
|
||||||
|
private String keyAlias;
|
||||||
|
private String keyPassword;
|
||||||
|
private String realmCertificateAlias;
|
||||||
|
|
||||||
|
public Resource getKeystoreResource() {
|
||||||
|
if (keystoreLocation.startsWith("classpath:")) {
|
||||||
|
return new ClassPathResource(
|
||||||
|
keystoreLocation.substring("classpath:".length()));
|
||||||
|
} else {
|
||||||
|
return new FileSystemResource(keystoreLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class OAUTH2 {
|
public static class OAUTH2 {
|
||||||
private Boolean enabled = false;
|
private Boolean enabled = false;
|
||||||
@ -136,6 +171,7 @@ public class ApplicationProperties {
|
|||||||
private boolean customHTMLFiles;
|
private boolean customHTMLFiles;
|
||||||
private String tessdataDir;
|
private String tessdataDir;
|
||||||
private Boolean enableAlphaFunctionality;
|
private Boolean enableAlphaFunctionality;
|
||||||
|
private String enableAnalytics;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -175,11 +211,14 @@ public class ApplicationProperties {
|
|||||||
@Data
|
@Data
|
||||||
public static class AutomaticallyGenerated {
|
public static class AutomaticallyGenerated {
|
||||||
@ToString.Exclude private String key;
|
@ToString.Exclude private String key;
|
||||||
|
private String UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class EnterpriseEdition {
|
public static class EnterpriseEdition {
|
||||||
|
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
|
||||||
|
@ -10,8 +10,10 @@ import org.apache.pdfbox.pdmodel.PDDocument;
|
|||||||
import org.apache.pdfbox.text.PDFTextStripper;
|
import org.apache.pdfbox.text.PDFTextStripper;
|
||||||
import org.apache.pdfbox.text.TextPosition;
|
import org.apache.pdfbox.text.TextPosition;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import stirling.software.SPDF.model.PDFText;
|
import stirling.software.SPDF.model.PDFText;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class TextFinder extends PDFTextStripper {
|
public class TextFinder extends PDFTextStripper {
|
||||||
|
|
||||||
private final String searchText;
|
private final String searchText;
|
||||||
@ -92,7 +94,7 @@ public class TextFinder extends PDFTextStripper {
|
|||||||
|
|
||||||
public List<PDFText> getTextLocations(PDDocument document) throws Exception {
|
public List<PDFText> getTextLocations(PDDocument document) throws Exception {
|
||||||
this.getText(document);
|
this.getText(document);
|
||||||
System.out.println(
|
log.debug(
|
||||||
"Found "
|
"Found "
|
||||||
+ textOccurrences.size()
|
+ textOccurrences.size()
|
||||||
+ " occurrences of '"
|
+ " occurrences of '"
|
||||||
|
@ -13,7 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.PdfMetadataService;
|
|
||||||
import stirling.software.SPDF.model.PdfMetadata;
|
import stirling.software.SPDF.model.PdfMetadata;
|
||||||
import stirling.software.SPDF.model.api.PDFFile;
|
import stirling.software.SPDF.model.api.PDFFile;
|
||||||
|
|
||||||
@ -35,6 +34,36 @@ 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();
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
|
import io.micrometer.core.instrument.search.Search;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MetricsAggregatorService {
|
||||||
|
|
||||||
|
private final MeterRegistry meterRegistry;
|
||||||
|
private final PostHogService postHogService;
|
||||||
|
private final Map<String, Double> lastSentMetrics = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public MetricsAggregatorService(MeterRegistry meterRegistry, PostHogService postHogService) {
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
|
this.postHogService = postHogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 900000) // Run every 15 minutes
|
||||||
|
public void aggregateAndSendMetrics() {
|
||||||
|
Map<String, Object> metrics = new HashMap<>();
|
||||||
|
Search.in(meterRegistry)
|
||||||
|
.name("http.requests")
|
||||||
|
.counters()
|
||||||
|
.forEach(
|
||||||
|
counter -> {
|
||||||
|
String key =
|
||||||
|
String.format(
|
||||||
|
"http_requests_%s_%s",
|
||||||
|
counter.getId().getTag("method"),
|
||||||
|
counter.getId().getTag("uri").replace("/", "_"));
|
||||||
|
|
||||||
|
double currentCount = counter.count();
|
||||||
|
double lastCount = lastSentMetrics.getOrDefault(key, 0.0);
|
||||||
|
double difference = currentCount - lastCount;
|
||||||
|
|
||||||
|
if (difference > 0) {
|
||||||
|
metrics.put(key, difference);
|
||||||
|
lastSentMetrics.put(key, currentCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send aggregated metrics to PostHog
|
||||||
|
if (!metrics.isEmpty()) {
|
||||||
|
postHogService.captureEvent("aggregated_metrics", metrics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package stirling.software.SPDF.config;
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
@ -15,16 +15,16 @@ import stirling.software.SPDF.model.PdfMetadata;
|
|||||||
public class PdfMetadataService {
|
public class PdfMetadataService {
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
private final String appVersion;
|
private final String stirlingPDFLabel;
|
||||||
private final UserServiceInterface userService;
|
private final UserServiceInterface userService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PdfMetadataService(
|
public PdfMetadataService(
|
||||||
ApplicationProperties applicationProperties,
|
ApplicationProperties applicationProperties,
|
||||||
@Qualifier("appVersion") String appVersion,
|
@Qualifier("StirlingPDFLabel") String stirlingPDFLabel,
|
||||||
@Autowired(required = false) UserServiceInterface userService) {
|
@Autowired(required = false) UserServiceInterface userService) {
|
||||||
this.applicationProperties = applicationProperties;
|
this.applicationProperties = applicationProperties;
|
||||||
this.appVersion = appVersion;
|
this.stirlingPDFLabel = stirlingPDFLabel;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,51 +59,40 @@ public class PdfMetadataService {
|
|||||||
|
|
||||||
private void setNewDocumentMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
|
private void setNewDocumentMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
|
||||||
|
|
||||||
String creator = "Stirling-PDF";
|
String creator = stirlingPDFLabel;
|
||||||
|
|
||||||
// if (applicationProperties
|
if (applicationProperties
|
||||||
// .getEnterpriseEdition()
|
.getEnterpriseEdition()
|
||||||
// .getCustomMetadata()
|
.getCustomMetadata()
|
||||||
// .isAutoUpdateMetadata()) {
|
.isAutoUpdateMetadata()) {
|
||||||
|
|
||||||
// producer =
|
creator = applicationProperties.getEnterpriseEdition().getCustomMetadata().getCreator();
|
||||||
//
|
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
|
||||||
// applicationProperties.getEnterpriseEdition().getCustomMetadata().getProducer();
|
}
|
||||||
// creator =
|
|
||||||
// applicationProperties.getEnterpriseEdition().getCustomMetadata().getCreator();
|
|
||||||
// title = applicationProperties.getEnterpriseEdition().getCustomMetadata().getTitle();
|
|
||||||
|
|
||||||
// if ("{filename}".equals(title)) {
|
pdf.getDocumentInformation().setCreator(creator);
|
||||||
// title = "Filename"; // Replace with actual filename logic
|
|
||||||
// } else if ("{unchanged}".equals(title)) {
|
|
||||||
// title = pdfMetadata.getTitle(); // Keep the original title
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pdf.getDocumentInformation().setCreator(creator + " " + appVersion);
|
|
||||||
pdf.getDocumentInformation().setCreationDate(Calendar.getInstance());
|
pdf.getDocumentInformation().setCreationDate(Calendar.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCommonMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
|
private void setCommonMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
|
||||||
String producer = "Stirling-PDF";
|
|
||||||
String title = pdfMetadata.getTitle();
|
String title = pdfMetadata.getTitle();
|
||||||
pdf.getDocumentInformation().setTitle(title);
|
pdf.getDocumentInformation().setTitle(title);
|
||||||
pdf.getDocumentInformation().setProducer(producer + " " + appVersion);
|
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
|
||||||
pdf.getDocumentInformation().setSubject(pdfMetadata.getSubject());
|
pdf.getDocumentInformation().setSubject(pdfMetadata.getSubject());
|
||||||
pdf.getDocumentInformation().setKeywords(pdfMetadata.getKeywords());
|
pdf.getDocumentInformation().setKeywords(pdfMetadata.getKeywords());
|
||||||
pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
|
pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
|
||||||
|
|
||||||
String author = pdfMetadata.getAuthor();
|
String author = pdfMetadata.getAuthor();
|
||||||
// if (applicationProperties
|
if (applicationProperties
|
||||||
// .getEnterpriseEdition()
|
.getEnterpriseEdition()
|
||||||
// .getCustomMetadata()
|
.getCustomMetadata()
|
||||||
// .isAutoUpdateMetadata()) {
|
.isAutoUpdateMetadata()) {
|
||||||
// author = applicationProperties.getEnterpriseEdition().getCustomMetadata().getAuthor();
|
author = applicationProperties.getEnterpriseEdition().getCustomMetadata().getAuthor();
|
||||||
|
|
||||||
// if (userService != null) {
|
if (userService != null) {
|
||||||
// author = author.replace("username", userService.getCurrentUsername());
|
author = author.replace("username", userService.getCurrentUsername());
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
pdf.getDocumentInformation().setAuthor(author);
|
pdf.getDocumentInformation().setAuthor(author);
|
||||||
}
|
}
|
||||||
}
|
}
|
379
src/main/java/stirling/software/SPDF/service/PostHogService.java
Normal file
379
src/main/java/stirling/software/SPDF/service/PostHogService.java
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.management.*;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.posthog.java.PostHog;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PostHogService {
|
||||||
|
private final PostHog postHog;
|
||||||
|
private final String uniqueId;
|
||||||
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public PostHogService(
|
||||||
|
PostHog postHog,
|
||||||
|
@Qualifier("UUID") String uuid,
|
||||||
|
ApplicationProperties applicationProperties) {
|
||||||
|
this.postHog = postHog;
|
||||||
|
this.uniqueId = uuid;
|
||||||
|
this.applicationProperties = applicationProperties;
|
||||||
|
captureSystemInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void captureSystemInfo() {
|
||||||
|
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
postHog.capture(uniqueId, "system_info_captured", captureServerMetrics());
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Handle exceptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void captureEvent(String eventName, Map<String, Object> properties) {
|
||||||
|
if (!Boolean.getBoolean(applicationProperties.getSystem().getEnableAnalytics())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
postHog.capture(uniqueId, eventName, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> captureServerMetrics() {
|
||||||
|
Map<String, Object> metrics = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// System info
|
||||||
|
metrics.put("os_name", System.getProperty("os.name"));
|
||||||
|
metrics.put("os_version", System.getProperty("os.version"));
|
||||||
|
metrics.put("java_version", System.getProperty("java.version"));
|
||||||
|
metrics.put("user_name", System.getProperty("user.name"));
|
||||||
|
metrics.put("user_home", System.getProperty("user.home"));
|
||||||
|
metrics.put("user_dir", System.getProperty("user.dir"));
|
||||||
|
|
||||||
|
// CPU and Memory
|
||||||
|
metrics.put("cpu_cores", Runtime.getRuntime().availableProcessors());
|
||||||
|
metrics.put("total_memory", Runtime.getRuntime().totalMemory());
|
||||||
|
metrics.put("free_memory", Runtime.getRuntime().freeMemory());
|
||||||
|
|
||||||
|
// Network and Server Identity
|
||||||
|
InetAddress localHost = InetAddress.getLocalHost();
|
||||||
|
metrics.put("ip_address", localHost.getHostAddress());
|
||||||
|
metrics.put("hostname", localHost.getHostName());
|
||||||
|
metrics.put("mac_address", getMacAddress());
|
||||||
|
|
||||||
|
// JVM info
|
||||||
|
metrics.put("jvm_vendor", System.getProperty("java.vendor"));
|
||||||
|
metrics.put("jvm_version", System.getProperty("java.vm.version"));
|
||||||
|
|
||||||
|
// Locale and Timezone
|
||||||
|
metrics.put("system_language", System.getProperty("user.language"));
|
||||||
|
metrics.put("system_country", System.getProperty("user.country"));
|
||||||
|
metrics.put("timezone", TimeZone.getDefault().getID());
|
||||||
|
metrics.put("locale", Locale.getDefault().toString());
|
||||||
|
|
||||||
|
// Disk info
|
||||||
|
File root = new File(".");
|
||||||
|
metrics.put("total_disk_space", root.getTotalSpace());
|
||||||
|
metrics.put("free_disk_space", root.getFreeSpace());
|
||||||
|
|
||||||
|
// Process info
|
||||||
|
metrics.put("process_id", ProcessHandle.current().pid());
|
||||||
|
|
||||||
|
// JVM metrics
|
||||||
|
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
|
||||||
|
metrics.put("jvm_uptime_ms", runtimeMXBean.getUptime());
|
||||||
|
metrics.put("jvm_start_time", runtimeMXBean.getStartTime());
|
||||||
|
|
||||||
|
// Memory metrics
|
||||||
|
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
|
||||||
|
metrics.put("heap_memory_usage", memoryMXBean.getHeapMemoryUsage().getUsed());
|
||||||
|
metrics.put("non_heap_memory_usage", memoryMXBean.getNonHeapMemoryUsage().getUsed());
|
||||||
|
|
||||||
|
// CPU metrics
|
||||||
|
OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
|
||||||
|
metrics.put("system_load_average", osMXBean.getSystemLoadAverage());
|
||||||
|
|
||||||
|
// Thread metrics
|
||||||
|
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
||||||
|
metrics.put("thread_count", threadMXBean.getThreadCount());
|
||||||
|
metrics.put("daemon_thread_count", threadMXBean.getDaemonThreadCount());
|
||||||
|
metrics.put("peak_thread_count", threadMXBean.getPeakThreadCount());
|
||||||
|
|
||||||
|
// Garbage collection metrics
|
||||||
|
for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
|
||||||
|
metrics.put("gc_" + gcBean.getName() + "_count", gcBean.getCollectionCount());
|
||||||
|
metrics.put("gc_" + gcBean.getName() + "_time", gcBean.getCollectionTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network interfaces
|
||||||
|
metrics.put("network_interfaces", getNetworkInterfacesInfo());
|
||||||
|
|
||||||
|
// Docker detection and stats
|
||||||
|
boolean isDocker = isRunningInDocker();
|
||||||
|
metrics.put("is_docker", isDocker);
|
||||||
|
if (isDocker) {
|
||||||
|
metrics.put("docker_metrics", getDockerMetrics());
|
||||||
|
}
|
||||||
|
metrics.put("application_properties", captureApplicationProperties());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
metrics.put("error", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return metrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRunningInDocker() {
|
||||||
|
return Files.exists(Paths.get("/.dockerenv"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getDockerMetrics() {
|
||||||
|
Map<String, Object> dockerMetrics = new HashMap<>();
|
||||||
|
|
||||||
|
// Network-related Docker info
|
||||||
|
dockerMetrics.put("docker_network_mode", System.getenv("DOCKER_NETWORK_MODE"));
|
||||||
|
|
||||||
|
// Container name (if set)
|
||||||
|
String containerName = System.getenv("CONTAINER_NAME");
|
||||||
|
if (containerName != null && !containerName.isEmpty()) {
|
||||||
|
dockerMetrics.put("container_name", containerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Docker compose information
|
||||||
|
String composeProject = System.getenv("COMPOSE_PROJECT_NAME");
|
||||||
|
String composeService = System.getenv("COMPOSE_SERVICE_NAME");
|
||||||
|
if (composeProject != null && composeService != null) {
|
||||||
|
dockerMetrics.put("compose_project", composeProject);
|
||||||
|
dockerMetrics.put("compose_service", composeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kubernetes-specific info (if running in K8s)
|
||||||
|
String k8sPodName = System.getenv("KUBERNETES_POD_NAME");
|
||||||
|
if (k8sPodName != null) {
|
||||||
|
dockerMetrics.put("k8s_pod_name", k8sPodName);
|
||||||
|
dockerMetrics.put("k8s_namespace", System.getenv("KUBERNETES_NAMESPACE"));
|
||||||
|
dockerMetrics.put("k8s_node_name", System.getenv("KUBERNETES_NODE_NAME"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// New environment variables
|
||||||
|
dockerMetrics.put("version_tag", System.getenv("VERSION_TAG"));
|
||||||
|
dockerMetrics.put("docker_enable_security", System.getenv("DOCKER_ENABLE_SECURITY"));
|
||||||
|
dockerMetrics.put("fat_docker", System.getenv("FAT_DOCKER"));
|
||||||
|
|
||||||
|
return dockerMetrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addIfNotEmpty(Map<String, Object> map, String key, Object value) {
|
||||||
|
if (value != null) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
String strValue = (String) value;
|
||||||
|
if (!StringUtils.isBlank(strValue)) {
|
||||||
|
map.put(key, strValue.trim());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> captureApplicationProperties() {
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
|
||||||
|
// Capture Legal properties
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"legal_termsAndConditions",
|
||||||
|
applicationProperties.getLegal().getTermsAndConditions());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"legal_privacyPolicy",
|
||||||
|
applicationProperties.getLegal().getPrivacyPolicy());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"legal_accessibilityStatement",
|
||||||
|
applicationProperties.getLegal().getAccessibilityStatement());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"legal_cookiePolicy",
|
||||||
|
applicationProperties.getLegal().getCookiePolicy());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties, "legal_impressum", applicationProperties.getLegal().getImpressum());
|
||||||
|
|
||||||
|
// Capture Security properties
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_enableLogin",
|
||||||
|
applicationProperties.getSecurity().getEnableLogin());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_csrfDisabled",
|
||||||
|
applicationProperties.getSecurity().getCsrfDisabled());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_loginAttemptCount",
|
||||||
|
applicationProperties.getSecurity().getLoginAttemptCount());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_loginResetTimeMinutes",
|
||||||
|
applicationProperties.getSecurity().getLoginResetTimeMinutes());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_loginMethod",
|
||||||
|
applicationProperties.getSecurity().getLoginMethod());
|
||||||
|
|
||||||
|
// Capture OAuth2 properties (excluding sensitive information)
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_oauth2_enabled",
|
||||||
|
applicationProperties.getSecurity().getOauth2().getEnabled());
|
||||||
|
if (applicationProperties.getSecurity().getOauth2().getEnabled()) {
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_oauth2_autoCreateUser",
|
||||||
|
applicationProperties.getSecurity().getOauth2().getAutoCreateUser());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_oauth2_blockRegistration",
|
||||||
|
applicationProperties.getSecurity().getOauth2().getBlockRegistration());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_oauth2_useAsUsername",
|
||||||
|
applicationProperties.getSecurity().getOauth2().getUseAsUsername());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"security_oauth2_provider",
|
||||||
|
applicationProperties.getSecurity().getOauth2().getProvider());
|
||||||
|
}
|
||||||
|
// Capture System properties
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_defaultLocale",
|
||||||
|
applicationProperties.getSystem().getDefaultLocale());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_googlevisibility",
|
||||||
|
applicationProperties.getSystem().getGooglevisibility());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties, "system_showUpdate", applicationProperties.getSystem().isShowUpdate());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_showUpdateOnlyAdmin",
|
||||||
|
applicationProperties.getSystem().getShowUpdateOnlyAdmin());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_customHTMLFiles",
|
||||||
|
applicationProperties.getSystem().isCustomHTMLFiles());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_tessdataDir",
|
||||||
|
applicationProperties.getSystem().getTessdataDir());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_enableAlphaFunctionality",
|
||||||
|
applicationProperties.getSystem().getEnableAlphaFunctionality());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"system_enableAnalytics",
|
||||||
|
applicationProperties.getSystem().getEnableAnalytics());
|
||||||
|
|
||||||
|
// Capture UI properties
|
||||||
|
addIfNotEmpty(properties, "ui_appName", applicationProperties.getUi().getAppName());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"ui_homeDescription",
|
||||||
|
applicationProperties.getUi().getHomeDescription());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties, "ui_appNameNavbar", applicationProperties.getUi().getAppNameNavbar());
|
||||||
|
|
||||||
|
// Capture Metrics properties
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties, "metrics_enabled", applicationProperties.getMetrics().getEnabled());
|
||||||
|
|
||||||
|
// Capture EnterpriseEdition properties
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"enterpriseEdition_enabled",
|
||||||
|
applicationProperties.getEnterpriseEdition().isEnabled());
|
||||||
|
if (applicationProperties.getEnterpriseEdition().isEnabled()) {
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"enterpriseEdition_customMetadata_autoUpdateMetadata",
|
||||||
|
applicationProperties
|
||||||
|
.getEnterpriseEdition()
|
||||||
|
.getCustomMetadata()
|
||||||
|
.isAutoUpdateMetadata());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"enterpriseEdition_customMetadata_author",
|
||||||
|
applicationProperties.getEnterpriseEdition().getCustomMetadata().getAuthor());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"enterpriseEdition_customMetadata_creator",
|
||||||
|
applicationProperties.getEnterpriseEdition().getCustomMetadata().getCreator());
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"enterpriseEdition_customMetadata_producer",
|
||||||
|
applicationProperties.getEnterpriseEdition().getCustomMetadata().getProducer());
|
||||||
|
}
|
||||||
|
// Capture AutoPipeline properties
|
||||||
|
addIfNotEmpty(
|
||||||
|
properties,
|
||||||
|
"autoPipeline_outputFolder",
|
||||||
|
applicationProperties.getAutoPipeline().getOutputFolder());
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMacAddress() {
|
||||||
|
try {
|
||||||
|
Enumeration<NetworkInterface> networkInterfaces =
|
||||||
|
NetworkInterface.getNetworkInterfaces();
|
||||||
|
while (networkInterfaces.hasMoreElements()) {
|
||||||
|
NetworkInterface ni = networkInterfaces.nextElement();
|
||||||
|
byte[] hardwareAddress = ni.getHardwareAddress();
|
||||||
|
if (hardwareAddress != null) {
|
||||||
|
String[] hexadecimal = new String[hardwareAddress.length];
|
||||||
|
for (int i = 0; i < hardwareAddress.length; i++) {
|
||||||
|
hexadecimal[i] = String.format("%02X", hardwareAddress[i]);
|
||||||
|
}
|
||||||
|
return String.join("-", hexadecimal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Handle exception
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getNetworkInterfacesInfo() {
|
||||||
|
Map<String, String> interfacesInfo = new HashMap<>();
|
||||||
|
try {
|
||||||
|
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
|
||||||
|
while (nets.hasMoreElements()) {
|
||||||
|
NetworkInterface netint = nets.nextElement();
|
||||||
|
interfacesInfo.put(netint.getName(), netint.getDisplayName());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
interfacesInfo.put("error", e.getMessage());
|
||||||
|
}
|
||||||
|
return interfacesInfo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
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,16 +2,23 @@ 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;
|
||||||
|
|
||||||
@ -33,19 +40,25 @@ public class FileToPdf {
|
|||||||
try {
|
try {
|
||||||
if (fileName.endsWith(".html")) {
|
if (fileName.endsWith(".html")) {
|
||||||
tempInputFile = Files.createTempFile("input_", ".html");
|
tempInputFile = Files.createTempFile("input_", ".html");
|
||||||
Files.write(tempInputFile, fileBytes);
|
String sanitizedHtml =
|
||||||
} else {
|
sanitizeHtmlContent(new String(fileBytes, StandardCharsets.UTF_8));
|
||||||
|
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 utf-8");
|
command.add("-e");
|
||||||
|
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());
|
||||||
@ -54,10 +67,8 @@ 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");
|
||||||
@ -65,9 +76,7 @@ public class FileToPdf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessExecutorResult returnCode;
|
ProcessExecutorResult returnCode =
|
||||||
|
|
||||||
returnCode =
|
|
||||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||||
.runCommandWithOutputHandling(command);
|
.runCommandWithOutputHandling(command);
|
||||||
|
|
||||||
@ -78,8 +87,6 @@ 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);
|
||||||
}
|
}
|
||||||
@ -87,6 +94,81 @@ 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 =
|
||||||
|
@ -5,18 +5,28 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.FileVisitResult;
|
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.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.simpleyaml.configuration.file.YamlFile;
|
||||||
|
import org.simpleyaml.configuration.file.YamlFileWrapper;
|
||||||
|
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
|
||||||
|
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
@ -262,4 +272,81 @@ public class GeneralUtils {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isValidUUID(String uuid) {
|
||||||
|
if (uuid == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
UUID.fromString(uuid);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveKeyToConfig(String id, String key) throws IOException {
|
||||||
|
saveKeyToConfig(id, key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveKeyToConfig(String id, String key, boolean autoGenerated)
|
||||||
|
throws IOException {
|
||||||
|
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
|
||||||
|
|
||||||
|
final YamlFile settingsYml = new YamlFile(path.toFile());
|
||||||
|
DumperOptions yamlOptionssettingsYml =
|
||||||
|
((SimpleYamlImplementation) settingsYml.getImplementation()).getDumperOptions();
|
||||||
|
yamlOptionssettingsYml.setSplitLines(false);
|
||||||
|
|
||||||
|
settingsYml.loadWithComments();
|
||||||
|
|
||||||
|
YamlFileWrapper writer = settingsYml.path(id).set(key);
|
||||||
|
if (autoGenerated) {
|
||||||
|
writer.comment("# Automatically Generated Settings (Do Not Edit Directly)");
|
||||||
|
}
|
||||||
|
settingsYml.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateMachineFingerprint() {
|
||||||
|
try {
|
||||||
|
// Get the MAC address
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
InetAddress ip = InetAddress.getLocalHost();
|
||||||
|
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
||||||
|
|
||||||
|
if (network == null) {
|
||||||
|
Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
|
||||||
|
while (networks.hasMoreElements()) {
|
||||||
|
NetworkInterface net = networks.nextElement();
|
||||||
|
byte[] mac = net.getHardwareAddress();
|
||||||
|
if (mac != null) {
|
||||||
|
for (int i = 0; i < mac.length; i++) {
|
||||||
|
sb.append(String.format("%02X", mac[i]));
|
||||||
|
}
|
||||||
|
break; // Use the first network interface with a MAC address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
byte[] mac = network.getHardwareAddress();
|
||||||
|
if (mac != null) {
|
||||||
|
for (int i = 0; i < mac.length; i++) {
|
||||||
|
sb.append(String.format("%02X", mac[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash the MAC address for privacy and consistency
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] hash = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
StringBuilder fingerprint = new StringBuilder();
|
||||||
|
for (byte b : hash) {
|
||||||
|
fingerprint.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fingerprint.toString();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "GenericID";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,6 @@ public class PDFToFile {
|
|||||||
Files.deleteIfExists(tempInputFile);
|
Files.deleteIfExists(tempInputFile);
|
||||||
if (tempOutputDir != null) FileUtils.deleteDirectory(tempOutputDir.toFile());
|
if (tempOutputDir != null) FileUtils.deleteDirectory(tempOutputDir.toFile());
|
||||||
}
|
}
|
||||||
System.out.println("fileBytes=" + fileBytes.length);
|
|
||||||
return WebResponseUtils.bytesToWebResponse(
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
|
fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ public class RequestUriUtils {
|
|||||||
|| requestURI.startsWith(contextPath + "/public/")
|
|| requestURI.startsWith(contextPath + "/public/")
|
||||||
|| requestURI.startsWith(contextPath + "/pdfjs/")
|
|| requestURI.startsWith(contextPath + "/pdfjs/")
|
||||||
|| requestURI.startsWith(contextPath + "/login")
|
|| requestURI.startsWith(contextPath + "/login")
|
||||||
|
|| requestURI.startsWith(contextPath + "/error")
|
||||||
|| requestURI.endsWith(".svg")
|
|| requestURI.endsWith(".svg")
|
||||||
|| requestURI.endsWith(".png")
|
|| requestURI.endsWith(".png")
|
||||||
|| requestURI.endsWith(".ico")
|
|| requestURI.endsWith(".ico")
|
||||||
|
@ -6,11 +6,12 @@ import org.springframework.core.io.InputStreamResource;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
import stirling.software.SPDF.model.api.PDFFile;
|
import stirling.software.SPDF.model.api.PDFFile;
|
||||||
import stirling.software.SPDF.model.api.misc.ReplaceAndInvert;
|
import stirling.software.SPDF.model.api.misc.ReplaceAndInvert;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
// @EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public abstract class ReplaceAndInvertColorStrategy extends PDFFile {
|
public abstract class ReplaceAndInvertColorStrategy extends PDFFile {
|
||||||
|
|
||||||
protected ReplaceAndInvert replaceAndInvert;
|
protected ReplaceAndInvert replaceAndInvert;
|
||||||
|
@ -27,9 +27,9 @@ server.servlet.context-path=${SYSTEM_ROOTURIPATH:/}
|
|||||||
|
|
||||||
spring.devtools.restart.enabled=true
|
spring.devtools.restart.enabled=true
|
||||||
spring.devtools.livereload.enabled=true
|
spring.devtools.livereload.enabled=true
|
||||||
|
|
||||||
spring.thymeleaf.encoding=UTF-8
|
spring.thymeleaf.encoding=UTF-8
|
||||||
|
|
||||||
|
spring.web.resources.mime-mappings.webmanifest=application/manifest+json
|
||||||
|
|
||||||
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
|
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
|
||||||
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
|
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
|
||||||
@ -41,7 +41,7 @@ spring.datasource.username=sa
|
|||||||
spring.datasource.password=
|
spring.datasource.password=
|
||||||
spring.h2.console.enabled=false
|
spring.h2.console.enabled=false
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
server.servlet.session.timeout: 30m
|
||||||
# Change the default URL path for OpenAPI JSON
|
# Change the default URL path for OpenAPI JSON
|
||||||
springdoc.api-docs.path=/v1/api-docs
|
springdoc.api-docs.path=/v1/api-docs
|
||||||
|
|
||||||
@ -49,3 +49,5 @@ springdoc.api-docs.path=/v1/api-docs
|
|||||||
springdoc.swagger-ui.url=/v1/api-docs
|
springdoc.swagger-ui.url=/v1/api-docs
|
||||||
|
|
||||||
|
|
||||||
|
posthog.api.key=phc_fiR65u5j6qmXTYL56MNrLZSWqLaDW74OrZH0Insd2xq
|
||||||
|
posthog.host=https://eu.i.posthog.com
|
@ -76,6 +76,7 @@ donate=تبرع
|
|||||||
color=لون
|
color=لون
|
||||||
sponsor=راعٍ
|
sponsor=راعٍ
|
||||||
info=معلومات
|
info=معلومات
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=ضبط حجم/مقياس الصفحة
|
|||||||
home.scalePages.desc=تغيير حجم/مقياس الصفحة و/أو محتواها.
|
home.scalePages.desc=تغيير حجم/مقياس الصفحة و/أو محتواها.
|
||||||
scalePages.tags=تغيير الحجم,تعديل,الأبعاد,تكييف
|
scalePages.tags=تغيير الحجم,تعديل,الأبعاد,تكييف
|
||||||
|
|
||||||
home.pipeline.title=خط الأنابيب (متقدم)
|
home.pipeline.title=خط الأنابيب
|
||||||
home.pipeline.desc=تشغيل إجراءات متعددة على ملفات PDF عن طريق تحديد نصوص خط الأنابيب
|
home.pipeline.desc=تشغيل إجراءات متعددة على ملفات PDF عن طريق تحديد نصوص خط الأنابيب
|
||||||
pipeline.tags=أتمتة,تسلسل,مبرمج,معالجة دفعات
|
pipeline.tags=أتمتة,تسلسل,مبرمج,معالجة دفعات
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=حجب تلقائي
|
||||||
@ -1154,6 +1182,8 @@ 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=المشاركة في الاستطلاع
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Направете дарение
|
|||||||
color=Цвят
|
color=Цвят
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=Автоматично редактиране
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Adjust page size/scale
|
|||||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||||
scalePages.tags=resize,modify,dimension,adapt
|
scalePages.tags=resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Advanced)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||||
pipeline.tags=automate,sequence,scripted,batch-process
|
pipeline.tags=automate,sequence,scripted,batch-process
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Upravit velikost/škálu stránky
|
|||||||
home.scalePages.desc=Změnit velikost/škálu stránky a/nebo její obsah.
|
home.scalePages.desc=Změnit velikost/škálu stránky a/nebo její obsah.
|
||||||
scalePages.tags=změnit velikost,upravit,rozměr,přizpůsobit
|
scalePages.tags=změnit velikost,upravit,rozměr,přizpůsobit
|
||||||
|
|
||||||
home.pipeline.title=Potrubí (Pokročilé)
|
home.pipeline.title=Potrubí
|
||||||
home.pipeline.desc=Spustit více akcí na PDF s definicí skriptů potrubí
|
home.pipeline.desc=Spustit více akcí na PDF s definicí skriptů potrubí
|
||||||
pipeline.tags=automatizovat,sekvence,skriptované,dávkové zpracování
|
pipeline.tags=automatizovat,sekvence,skriptované,dávkové zpracování
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Spenden
|
|||||||
color=Farbe
|
color=Farbe
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Informationen
|
info=Informationen
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Seitengröße/Skalierung anpassen
|
|||||||
home.scalePages.desc=Größe/Skalierung der Seite und/oder des Inhalts ändern
|
home.scalePages.desc=Größe/Skalierung der Seite und/oder des Inhalts ändern
|
||||||
scalePages.tags=größe ändern,ändern,dimensionieren,anpassen
|
scalePages.tags=größe ändern,ändern,dimensionieren,anpassen
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Fortgeschritten)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Mehrere Aktionen auf ein PDF anwenden, definiert durch ein Pipeline Skript
|
home.pipeline.desc=Mehrere Aktionen auf ein PDF anwenden, definiert durch ein Pipeline Skript
|
||||||
pipeline.tags=automatisieren,sequenzieren,skriptgesteuert,batch prozess
|
pipeline.tags=automatisieren,sequenzieren,skriptgesteuert,batch prozess
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Δωρισε
|
|||||||
color=Χρώμα
|
color=Χρώμα
|
||||||
sponsor=Yποστηρικτής
|
sponsor=Yποστηρικτής
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=Αυτόματο Μαύρισμα Κειμένου
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 to import file
|
database.failedImportFile=Failed to import file
|
||||||
|
|
||||||
|
session.expired=Your session has expired. Please refresh the page and try again.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Adjust page size/scale
|
|||||||
home.scalePages.desc=Change the size/scale of a page and/or its contents.
|
home.scalePages.desc=Change the size/scale of a page and/or its contents.
|
||||||
scalePages.tags=resize,modify,dimension,adapt
|
scalePages.tags=resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Advanced)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||||
pipeline.tags=automate,sequence,scripted,batch-process
|
pipeline.tags=automate,sequence,scripted,batch-process
|
||||||
|
|
||||||
@ -482,10 +502,15 @@ 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=Advanced Colour options
|
||||||
replace-color.header=Replace-Invert Color PDF
|
replace-color.header=Replace-Invert Color PDF
|
||||||
home.replaceColorPdf.title=Replace and Invert Color
|
home.replaceColorPdf.title=Advanced Colour options
|
||||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||||
replace-color.selectText.1=Replace or Invert color Options
|
replace-color.selectText.1=Replace or Invert color Options
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,7 +1182,9 @@ 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.please=Please consider taking our survey!
|
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 to have input on the future of Stirling-PDF!
|
||||||
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
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=Don't show again
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donar
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Patrocinador
|
sponsor=Patrocinador
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Escalar/ajustar tamaño de página
|
|||||||
home.scalePages.desc=Escalar/cambiar el tamaño de una pagina y/o su contenido
|
home.scalePages.desc=Escalar/cambiar el tamaño de una pagina y/o su contenido
|
||||||
scalePages.tags=cambiar tamaño,modificar,dimensionar,adaptar
|
scalePages.tags=cambiar tamaño,modificar,dimensionar,adaptar
|
||||||
|
|
||||||
home.pipeline.title=Secuencia (Avanzado)
|
home.pipeline.title=Secuencia
|
||||||
home.pipeline.desc=Ejecutar varias tareas a PDFs definiendo una secuencia de comandos
|
home.pipeline.desc=Ejecutar varias tareas a PDFs definiendo una secuencia de comandos
|
||||||
pipeline.tags=automatizar,secuencia,con script,proceso por lotes
|
pipeline.tags=automatizar,secuencia,con script,proceso por lotes
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ navbar.sections.convertFrom=Convertir depuis PDF
|
|||||||
navbar.sections.security=Signature et sécurité
|
navbar.sections.security=Signature et sécurité
|
||||||
navbar.sections.advance=Mode avancé
|
navbar.sections.advance=Mode avancé
|
||||||
navbar.sections.edit=Voir et modifier
|
navbar.sections.edit=Voir et modifier
|
||||||
|
navbar.sections.popular=Popular
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Ajuster l’échelle ou la taille
|
|||||||
home.scalePages.desc=Modifiez la taille ou l’échelle d’une page et/ou de son contenu.
|
home.scalePages.desc=Modifiez la taille ou l’échelle d’une page et/ou de son contenu.
|
||||||
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
|
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (avancé)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Exécutez plusieurs actions sur les PDF en définissant des scripts de pipeline.
|
home.pipeline.desc=Exécutez plusieurs actions sur les PDF en définissant des scripts de pipeline.
|
||||||
pipeline.tags=automatiser,séquencer,automate,sequence,scripted,batch-process
|
pipeline.tags=automatiser,séquencer,automate,sequence,scripted,batch-process
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ licenses.license=Ceadúnas
|
|||||||
survey.nav=Suirbhé
|
survey.nav=Suirbhé
|
||||||
survey.title=Suirbhé Stirling-PDF
|
survey.title=Suirbhé Stirling-PDF
|
||||||
survey.description=Níl aon rian ar Stirling-PDF agus mar sin ba mhaith linn cloisteáil ónár n-úsáideoirí chun feabhas a chur ar Stirling-PDF!
|
survey.description=Níl aon rian ar Stirling-PDF agus mar sin ba mhaith linn cloisteáil ónár n-úsáideoirí chun feabhas a chur ar Stirling-PDF!
|
||||||
|
survey.changes=Stirling-PDF 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é
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=पृष्ठ
|
page=पृष्ठ
|
||||||
pages=पृष्ठों
|
pages=पृष्ठों
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=स्वत: गोपनीयकरण
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Doniraj
|
|||||||
color=Boja
|
color=Boja
|
||||||
sponsor=Sponzor
|
sponsor=Sponzor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Prilagodite veličinu/razmjer stranice
|
|||||||
home.scalePages.desc=Promijenite veličinu/razmjer stranice i/ili njezin sadržaj.
|
home.scalePages.desc=Promijenite veličinu/razmjer stranice i/ili njezin sadržaj.
|
||||||
scalePages.tags=izmjena,modifikacija,dimenzija,adaptacija
|
scalePages.tags=izmjena,modifikacija,dimenzija,adaptacija
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Advanced)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Izvršite više radnji na PDF-ovima definiranjem skripti u pipeline-u
|
home.pipeline.desc=Izvršite više radnji na PDF-ovima definiranjem skripti u pipeline-u
|
||||||
pipeline.tags=automatizacija,sekvenciranje,skriptirano,batch-process
|
pipeline.tags=automatizacija,sekvenciranje,skriptirano,batch-process
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Menyesuaikan ukuran/skala halaman
|
|||||||
home.scalePages.desc=Mengubah ukuran/skala halaman dan/atau isinya.
|
home.scalePages.desc=Mengubah ukuran/skala halaman dan/atau isinya.
|
||||||
scalePages.tags=mengubah ukuran, memodifikasi, dimensi, mengadaptasi
|
scalePages.tags=mengubah ukuran, memodifikasi, dimensi, mengadaptasi
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Lanjutan)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Menjalankan beberapa tindakan pada PDF dengan mendefinisikan skrip pipeline
|
home.pipeline.desc=Menjalankan beberapa tindakan pada PDF dengan mendefinisikan skrip pipeline
|
||||||
pipeline.tags=mengotomatiskan, mengurutkan, menulis, proses batch
|
pipeline.tags=mengotomatiskan, mengurutkan, menulis, proses batch
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donazione
|
|||||||
color=Colore
|
color=Colore
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Download
|
pipelineOptions.saveButton=Download
|
||||||
pipelineOptions.validateButton=Convalidare
|
pipelineOptions.validateButton=Convalidare
|
||||||
|
|
||||||
|
########################
|
||||||
|
# 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 #
|
||||||
@ -128,6 +145,7 @@ navbar.sections.convertFrom=Converti da PDF
|
|||||||
navbar.sections.security=Firma & Sicurezza
|
navbar.sections.security=Firma & Sicurezza
|
||||||
navbar.sections.advance=Avanzate
|
navbar.sections.advance=Avanzate
|
||||||
navbar.sections.edit=Visualizza & Modifica
|
navbar.sections.edit=Visualizza & Modifica
|
||||||
|
navbar.sections.popular=Popular
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@ -225,6 +243,8 @@ 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=Your session has expired. Please refresh the page and try again.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Regola le dimensioni/scala della pagina
|
|||||||
home.scalePages.desc=Modificare le dimensioni/scala della pagina e/o dei suoi contenuti.
|
home.scalePages.desc=Modificare le dimensioni/scala della pagina e/o dei suoi contenuti.
|
||||||
scalePages.tags=ridimensionare,modificare,dimensionare,adattare
|
scalePages.tags=ridimensionare,modificare,dimensionare,adattare
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (avanzato)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Esegui più azioni sui PDF definendo script di pipeline
|
home.pipeline.desc=Esegui più azioni sui PDF definendo script di pipeline
|
||||||
pipeline.tags=automatizzare,sequenziare,scriptare,elaborare in batch
|
pipeline.tags=automatizzare,sequenziare,scriptare,elaborare in batch
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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=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=Sostituisci-Inverti-Colore
|
replace-color.title=Sostituisci-Inverti-Colore
|
||||||
replace-color.header=Sostituisci-Inverti colore PDF
|
replace-color.header=Sostituisci-Inverti colore PDF
|
||||||
@ -526,7 +551,10 @@ 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=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=Redazione automatica
|
autoRedact.title=Redazione automatica
|
||||||
@ -1154,6 +1182,8 @@ 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 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=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
|
||||||
@ -1179,3 +1209,17 @@ 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=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,6 +76,7 @@ donate=寄付する
|
|||||||
color=色
|
color=色
|
||||||
sponsor=スポンサー
|
sponsor=スポンサー
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=ページの縮尺の調整
|
|||||||
home.scalePages.desc=ページやコンテンツの縮尺を変更します。
|
home.scalePages.desc=ページやコンテンツの縮尺を変更します。
|
||||||
scalePages.tags=resize,modify,dimension,adapt
|
scalePages.tags=resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=パイプライン (高度)
|
home.pipeline.title=パイプライン
|
||||||
home.pipeline.desc=パイプラインスクリプトを定義してPDF上で複数のアクションを実行します。
|
home.pipeline.desc=パイプラインスクリプトを定義してPDF上で複数のアクションを実行します。
|
||||||
pipeline.tags=automate,sequence,scripted,batch-process
|
pipeline.tags=automate,sequence,scripted,batch-process
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=自動塗りつぶし
|
||||||
@ -1154,6 +1182,8 @@ 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=アンケートに答える
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=기부하기
|
|||||||
color=색상
|
color=색상
|
||||||
sponsor=스폰서
|
sponsor=스폰서
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=자동 검열
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Doneer
|
|||||||
color=Kleur
|
color=Kleur
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Aanpassen paginaformaat/schaal
|
|||||||
home.scalePages.desc=Wijzig de grootte/schaal van een pagina en/of de inhoud ervan.
|
home.scalePages.desc=Wijzig de grootte/schaal van een pagina en/of de inhoud ervan.
|
||||||
scalePages.tags=resize,aanpassen,dimensie,aanpassen
|
scalePages.tags=resize,aanpassen,dimensie,aanpassen
|
||||||
|
|
||||||
home.pipeline.title=Pijplijn (Geavanceerd)
|
home.pipeline.title=Pijplijn
|
||||||
home.pipeline.desc=Voer meerdere acties uit op PDF's door pipelinescripts te definiëren
|
home.pipeline.desc=Voer meerdere acties uit op PDF's door pipelinescripts te definiëren
|
||||||
pipeline.tags=automatiseren,volgorde,gescrript,batch-verwerking
|
pipeline.tags=automatiseren,volgorde,gescrript,batch-verwerking
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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.
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Doner
|
|||||||
color=Farge
|
color=Farge
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Podaruj
|
|||||||
color=kolor
|
color=kolor
|
||||||
sponsor=sponsor
|
sponsor=sponsor
|
||||||
info=informacje
|
info=informacje
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Dopasuj rozmiar stron
|
|||||||
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
||||||
scalePages.tags=resize,modify,dimension,adapt
|
scalePages.tags=resize,modify,dimension,adapt
|
||||||
|
|
||||||
home.pipeline.title=Automatyzacja (Zaawansowane)
|
home.pipeline.title=Automatyzacja
|
||||||
home.pipeline.desc=Wykonaj wiele akcji na dokumentach PDF, tworząc automatyzację
|
home.pipeline.desc=Wykonaj wiele akcji na dokumentach PDF, tworząc automatyzację
|
||||||
pipeline.tags=automate,sequence,scripted,batch-process
|
pipeline.tags=automate,sequence,scripted,batch-process
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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ę
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Doar
|
|||||||
color=Cor
|
color=Cor
|
||||||
sponsor=Patrocine
|
sponsor=Patrocine
|
||||||
info=Informações
|
info=Informações
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ pipelineOptions.pipelineHeader=Pipeline:
|
|||||||
pipelineOptions.saveButton=Baixar
|
pipelineOptions.saveButton=Baixar
|
||||||
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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ database.fileNotFound=Arquivo não encontrado
|
|||||||
database.fileNullOrEmpty=O arquivo não 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=Your session has expired. Please refresh the page and try again.
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Ajustar Tamanho/Escala de Página
|
|||||||
home.scalePages.desc=Alterar o tamanho/escala da página e/ou seu conteúdo.
|
home.scalePages.desc=Alterar o tamanho/escala da página e/ou seu conteúdo.
|
||||||
scalePages.tags=redimensionar,modificar,dimensão,adaptar
|
scalePages.tags=redimensionar,modificar,dimensão,adaptar
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Avançado)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Executar várias ações em PDFs definindo scripts de pipeline
|
home.pipeline.desc=Executar várias ações em PDFs definindo scripts de pipeline
|
||||||
pipeline.tags=automatizar,sequência,scriptado,processo-em-lote
|
pipeline.tags=automatizar,sequência,scriptado,processo-em-lote
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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=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
|
||||||
@ -526,7 +551,10 @@ 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=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=Redigir automaticamente
|
autoRedact.title=Redigir automaticamente
|
||||||
@ -1154,6 +1182,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 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=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 final 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
|
||||||
@ -1179,3 +1209,17 @@ 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=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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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ă
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Пожертвовать
|
|||||||
color=Цвет
|
color=Цвет
|
||||||
sponsor=Спонсор
|
sponsor=Спонсор
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=Автоматическое редактирование
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Darovať
|
|||||||
color=Farba
|
color=Farba
|
||||||
sponsor=Sponzorovať
|
sponsor=Sponzorovať
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Prispôsobiť veľkosť/škálovanie stránok
|
|||||||
home.scalePages.desc=Zmeniť veľkosť/škálovanie stránky a/alebo jej obsahu.
|
home.scalePages.desc=Zmeniť veľkosť/škálovanie stránky a/alebo jej obsahu.
|
||||||
scalePages.tags=veľkosť,modifikovať,rozmery,prispôsobiť
|
scalePages.tags=veľkosť,modifikovať,rozmery,prispôsobiť
|
||||||
|
|
||||||
home.pipeline.title=Pipeline (Pokročilé)
|
home.pipeline.title=Pipeline
|
||||||
home.pipeline.desc=Spustiť viacero akcií na PDF definovaním pipeline skriptov
|
home.pipeline.desc=Spustiť viacero akcií na PDF definovaním pipeline skriptov
|
||||||
pipeline.tags=automatizovať,sekvencia,skriptované,dávkové spracovanie
|
pipeline.tags=automatizovať,sekvencia,skriptované,dávkové spracovanie
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=Donate
|
|||||||
color=Color
|
color=Color
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ navbar.sections.convertFrom=Konvertera från PDF
|
|||||||
navbar.sections.security=Signera & Säkerhet
|
navbar.sections.security=Signera & Säkerhet
|
||||||
navbar.sections.advance=Avancerat
|
navbar.sections.advance=Avancerat
|
||||||
navbar.sections.edit=Visa & Redigera
|
navbar.sections.edit=Visa & Redigera
|
||||||
|
navbar.sections.popular=Popular
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ donate=บริจาค
|
|||||||
color=สี
|
color=สี
|
||||||
sponsor=ผู้สนับสนุน
|
sponsor=ผู้สนับสนุน
|
||||||
info=ข้อมูล
|
info=ข้อมูล
|
||||||
|
pro=Pro
|
||||||
page=Page
|
page=Page
|
||||||
pages=Pages
|
pages=Pages
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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=ซ่อนข้อมูลอัตโนมัติ
|
||||||
@ -1154,6 +1182,8 @@ 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=เริ่มสำรวจ
|
||||||
@ -1179,3 +1209,17 @@ 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,6 +76,7 @@ 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
|
||||||
|
|
||||||
@ -110,8 +111,24 @@ 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 #
|
||||||
@ -128,6 +145,7 @@ 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 #
|
||||||
@ -225,6 +243,8 @@ 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 #
|
||||||
#############
|
#############
|
||||||
@ -382,7 +402,7 @@ home.scalePages.title=Sayfa boyutunu/ölçeğini ayarla
|
|||||||
home.scalePages.desc=Bir sayfanın ve/veya içeriğinin boyutunu/ölçeğini değiştirir
|
home.scalePages.desc=Bir sayfanın ve/veya içeriğinin boyutunu/ölçeğini değiştirir
|
||||||
scalePages.tags=boyutlandır,değiştir,boyut,uyarla
|
scalePages.tags=boyutlandır,değiştir,boyut,uyarla
|
||||||
|
|
||||||
home.pipeline.title=Çoklu İşlemler (İleri Seviye)
|
home.pipeline.title=Çoklu İşlemler
|
||||||
home.pipeline.desc=Çoklu İşlemler tanımlayarak PDF'lere birden fazla işlemi çalıştır
|
home.pipeline.desc=Çoklu İşlemler tanımlayarak PDF'lere birden fazla işlemi çalıştır
|
||||||
pipeline.tags=otomatikleştir,sıralı,betikli,toplu-işlem
|
pipeline.tags=otomatikleştir,sıralı,betikli,toplu-işlem
|
||||||
|
|
||||||
@ -482,6 +502,11 @@ 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
|
||||||
@ -526,7 +551,10 @@ 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
|
||||||
@ -1154,6 +1182,8 @@ 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
|
||||||
@ -1179,3 +1209,17 @@ 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
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user