Merge branch 'main' into session_2025_03_22

This commit is contained in:
Ludy 2025-04-14 10:14:43 +00:00 committed by GitHub
commit e76e83c427
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 331 additions and 56 deletions

View File

@ -37,6 +37,7 @@ jobs:
pr_repository: ${{ steps.get-pr-info.outputs.repository }}
pr_ref: ${{ steps.get-pr-info.outputs.ref }}
comment_id: ${{ github.event.comment.id }}
enable_security: ${{ steps.check-security-flag.outputs.enable_security }}
steps:
- name: Harden Runner
@ -83,6 +84,19 @@ jobs:
core.setOutput('repository', repository);
core.setOutput('ref', pr.head.ref);
- name: Check for security/login flag
id: check-security-flag
env:
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
if [[ "$COMMENT_BODY" == *"security"* ]] || [[ "$COMMENT_BODY" == *"login"* ]]; then
echo "Security flags detected in comment"
echo "enable_security=true" >> $GITHUB_OUTPUT
else
echo "No security flags detected in comment"
echo "enable_security=false" >> $GITHUB_OUTPUT
fi
- name: Add 'in_progress' reaction to comment
id: add-eyes-reaction
@ -140,9 +154,14 @@ jobs:
distribution: "temurin"
- name: Run Gradle Command
run: ./gradlew clean build
run: |
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
export DOCKER_ENABLE_SECURITY=true
else
export DOCKER_ENABLE_SECURITY=false
fi
./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
STIRLING_PDF_DESKTOP_UI: false
- name: Set up Docker Buildx
@ -179,8 +198,19 @@ jobs:
- name: Deploy to VPS
id: deploy
run: |
# Set security settings based on flags
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
DOCKER_SECURITY="true"
LOGIN_SECURITY="true"
SECURITY_STATUS="🔒 Security Enabled"
else
DOCKER_SECURITY="false"
LOGIN_SECURITY="false"
SECURITY_STATUS="Security Disabled"
fi
# First create the docker-compose content locally
cat > docker-compose.yml << 'EOF'
cat > docker-compose.yml << EOF
version: '3.3'
services:
stirling-pdf:
@ -193,8 +223,8 @@ jobs:
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
SECURITY_ENABLELOGIN: "false"
DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}"
SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}"
SYSTEM_DEFAULTLOCALE: en-GB
UI_APPNAME: "Stirling-PDF PR#${{ needs.check-comment.outputs.pr_number }}"
UI_HOMEDESCRIPTION: "PR#${{ needs.check-comment.outputs.pr_number }} for Stirling-PDF Latest"
@ -208,7 +238,7 @@ jobs:
# Then copy the file and execute commands
scp -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null docker-compose.yml ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }}:/tmp/docker-compose.yml
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH'
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << ENDSSH
# Create PR-specific directories
mkdir -p /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/{data,config,logs}
@ -220,6 +250,9 @@ jobs:
docker-compose pull
docker-compose up -d
ENDSSH
# Set output for use in PR comment
echo "security_status=${SECURITY_STATUS}" >> $GITHUB_ENV
- name: Add success reaction to comment
if: success()
@ -270,11 +303,13 @@ jobs:
const { GITHUB_REPOSITORY } = process.env;
const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/');
const prNumber = ${{ needs.check-comment.outputs.pr_number }};
const securityStatus = process.env.security_status || "Security Disabled";
const deploymentUrl = `http://${{ secrets.VPS_HOST }}:${prNumber}`;
const commentBody = `## 🚀 PR Test Deployment\n\n` +
`Your PR has been deployed for testing!\n\n` +
`🔗 **Test URL:** [${deploymentUrl}](${deploymentUrl})\n\n` +
`🔗 **Test URL:** [${deploymentUrl}](${deploymentUrl})\n` +
`${securityStatus}\n\n` +
`This deployment will be automatically cleaned up when the PR is closed.\n\n`;
await github.rest.issues.createComment({

View File

@ -124,32 +124,32 @@ Stirling-PDF currently supports 39 languages!
| Croatian (Hrvatski) (hr_HR) | ![81%](https://geps.dev/progress/81) |
| Czech (Česky) (cs_CZ) | ![92%](https://geps.dev/progress/92) |
| Danish (Dansk) (da_DK) | ![80%](https://geps.dev/progress/80) |
| Dutch (Nederlands) (nl_NL) | ![80%](https://geps.dev/progress/80) |
| Dutch (Nederlands) (nl_NL) | ![79%](https://geps.dev/progress/79) |
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| French (Français) (fr_FR) | ![92%](https://geps.dev/progress/92) |
| German (Deutsch) (de_DE) | ![95%](https://geps.dev/progress/95) |
| Greek (Ελληνικά) (el_GR) | ![92%](https://geps.dev/progress/92) |
| German (Deutsch) (de_DE) | ![94%](https://geps.dev/progress/94) |
| Greek (Ελληνικά) (el_GR) | ![91%](https://geps.dev/progress/91) |
| Hindi (हिंदी) (hi_IN) | ![92%](https://geps.dev/progress/92) |
| Hungarian (Magyar) (hu_HU) | ![89%](https://geps.dev/progress/89) |
| Indonesian (Bahasa Indonesia) (id_ID) | ![81%](https://geps.dev/progress/81) |
| Irish (Gaeilge) (ga_IE) | ![92%](https://geps.dev/progress/92) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
| Japanese (日本語) (ja_JP) | ![89%](https://geps.dev/progress/89) |
| Korean (한국어) (ko_KR) | ![93%](https://geps.dev/progress/93) |
| Norwegian (Norsk) (no_NB) | ![87%](https://geps.dev/progress/87) |
| Korean (한국어) (ko_KR) | ![92%](https://geps.dev/progress/92) |
| Norwegian (Norsk) (no_NB) | ![86%](https://geps.dev/progress/86) |
| Persian (فارسی) (fa_IR) | ![88%](https://geps.dev/progress/88) |
| Polish (Polski) (pl_PL) | ![96%](https://geps.dev/progress/96) |
| Portuguese (Português) (pt_PT) | ![91%](https://geps.dev/progress/91) |
| Portuguese Brazilian (Português) (pt_BR) | ![94%](https://geps.dev/progress/94) |
| Romanian (Română) (ro_RO) | ![76%](https://geps.dev/progress/76) |
| Romanian (Română) (ro_RO) | ![75%](https://geps.dev/progress/75) |
| Russian (Русский) (ru_RU) | ![94%](https://geps.dev/progress/94) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![60%](https://geps.dev/progress/60) |
| Simplified Chinese (简体中文) (zh_CN) | ![93%](https://geps.dev/progress/93) |
| Slovakian (Slovensky) (sk_SK) | ![69%](https://geps.dev/progress/69) |
| Slovenian (Slovenščina) (sl_SI) | ![95%](https://geps.dev/progress/95) |
| Spanish (Español) (es_ES) | ![94%](https://geps.dev/progress/94) |
| Swedish (Svenska) (sv_SE) | ![88%](https://geps.dev/progress/88) |
| Spanish (Español) (es_ES) | ![93%](https://geps.dev/progress/93) |
| Swedish (Svenska) (sv_SE) | ![87%](https://geps.dev/progress/87) |
| Thai (ไทย) (th_TH) | ![80%](https://geps.dev/progress/80) |
| Tibetan (བོད་ཡིག་) (zh_BO) | ![89%](https://geps.dev/progress/89) |
| Traditional Chinese (繁體中文) (zh_TW) | ![99%](https://geps.dev/progress/99) |

View File

@ -29,7 +29,7 @@ ext {
}
group = "stirling.software"
version = "0.45.4"
version = "0.45.5"
java {
// 17 is lowest but we support and recommend 21

View File

@ -53,24 +53,37 @@ public class KeygenLicenseVerifier {
}
public License verifyLicense(String licenseKeyOrCert) {
if (isCertificateLicense(licenseKeyOrCert)) {
log.info("Detected certificate-based license. Processing...");
return resultToEnum(verifyCertificateLicense(licenseKeyOrCert), License.ENTERPRISE);
} else if (isJWTLicense(licenseKeyOrCert)) {
log.info("Detected JWT-style license key. Processing...");
return resultToEnum(verifyJWTLicense(licenseKeyOrCert), License.ENTERPRISE);
} else {
log.info("Detected standard license key. Processing...");
return resultToEnum(verifyStandardLicense(licenseKeyOrCert), License.PRO);
}
License license;
if (isCertificateLicense(licenseKeyOrCert)) {
log.info("Detected certificate-based license. Processing...");
boolean isValid = verifyCertificateLicense(licenseKeyOrCert);
if (isValid) {
license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO;
} else {
license = License.NORMAL;
}
} else if (isJWTLicense(licenseKeyOrCert)) {
log.info("Detected JWT-style license key. Processing...");
boolean isValid = verifyJWTLicense(licenseKeyOrCert);
if (isValid) {
license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO;
} else {
license = License.NORMAL;
}
} else {
log.info("Detected standard license key. Processing...");
boolean isValid = verifyStandardLicense(licenseKeyOrCert);
if (isValid) {
license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO;
} else {
license = License.NORMAL;
}
}
return license;
}
private License resultToEnum(boolean result, License option) {
if (result) {
return option;
}
return License.NORMAL;
}
private boolean isEnterpriseLicense = false;
private boolean isCertificateLicense(String license) {
return license != null && license.trim().startsWith(CERT_PREFIX);
@ -82,8 +95,6 @@ public class KeygenLicenseVerifier {
private boolean verifyCertificateLicense(String licenseFile) {
try {
log.info("Verifying certificate-based license");
String encodedPayload = licenseFile;
// Remove the header
encodedPayload = encodedPayload.replace(CERT_PREFIX, "");
@ -106,8 +117,6 @@ public class KeygenLicenseVerifier {
encryptedData = (String) attrs.get("enc");
encodedSignature = (String) attrs.get("sig");
algorithm = (String) attrs.get("alg");
log.info("Certificate algorithm: {}", algorithm);
} catch (JSONException e) {
log.error("Failed to parse license file: {}", e.getMessage());
return false;
@ -151,7 +160,6 @@ public class KeygenLicenseVerifier {
private boolean verifyEd25519Signature(String encryptedData, String encodedSignature) {
try {
log.info("Signature to verify: {}", encodedSignature);
log.info("Public key being used: {}", PUBLIC_KEY);
byte[] signatureBytes = Base64.getDecoder().decode(encodedSignature);
@ -185,7 +193,7 @@ public class KeygenLicenseVerifier {
private boolean processCertificateData(String certData) {
try {
log.info("Processing certificate data: {}", certData);
JSONObject licenseData = new JSONObject(certData);
JSONObject metaObj = licenseData.optJSONObject("meta");
@ -234,18 +242,9 @@ public class KeygenLicenseVerifier {
applicationProperties.getPremium().setMaxUsers(users);
log.info("License allows for {} users", users);
}
isEnterpriseLicense = metadataObj.optBoolean("isEnterprise", false);
}
// Check maxUsers directly in attributes if present from policy definition
// if (attributesObj.has("maxUsers")) {
// int maxUsers = attributesObj.optInt("maxUsers", 0);
// if (maxUsers > 0) {
// applicationProperties.getPremium().setMaxUsers(maxUsers);
// log.info("License directly specifies {} max users",
// maxUsers);
// }
// }
// Check license status if available
String status = attributesObj.optString("status", null);
if (status != null
@ -388,9 +387,10 @@ public class KeygenLicenseVerifier {
String policyId = policyObj.optString("id", "unknown");
log.info("License uses policy: {}", policyId);
// Extract max users from policy if available (customize based on your policy
// structure)
// Extract max users and isEnterprise from policy or metadata
int users = policyObj.optInt("users", 0);
isEnterpriseLicense = policyObj.optBoolean("isEnterprise", false);
if (users > 0) {
applicationProperties.getPremium().setMaxUsers(users);
log.info("License allows for {} users", users);
@ -402,12 +402,16 @@ public class KeygenLicenseVerifier {
users = metadata.optInt("users", 1);
applicationProperties.getPremium().setMaxUsers(users);
log.info("License allows for {} users (from metadata)", users);
// Check for isEnterprise flag in metadata
isEnterpriseLicense = metadata.optBoolean("isEnterprise", false);
} else {
// Default value
applicationProperties.getPremium().setMaxUsers(1);
log.info("Using default of 1 user for license");
}
}
}
return true;
@ -494,6 +498,7 @@ public class KeygenLicenseVerifier {
log.info("Validation detail: " + detail);
log.info("Validation code: " + code);
// Extract user count
int users =
jsonResponse
.path("data")
@ -502,6 +507,16 @@ public class KeygenLicenseVerifier {
.path("users")
.asInt(0);
applicationProperties.getPremium().setMaxUsers(users);
// Extract isEnterprise flag
isEnterpriseLicense =
jsonResponse
.path("data")
.path("attributes")
.path("metadata")
.path("isEnterprise")
.asBoolean(false);
log.info(applicationProperties.toString());
} else {

View File

@ -20,6 +20,8 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.spring6.SpringTemplateEngine;
import com.posthog.java.shaded.kotlin.text.Regex;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
@ -107,6 +109,33 @@ public class AppConfig {
return (rateLimit != null) ? Boolean.valueOf(rateLimit) : false;
}
@Bean(name = "uploadLimit")
public long uploadLimit() {
String maxUploadSize =
applicationProperties.getSystem().getFileUploadLimit() != null
? applicationProperties.getSystem().getFileUploadLimit()
: "";
if (maxUploadSize.isEmpty()) {
return 0;
} else if (!new Regex("^[1-9][0-9]{0,2}[KMGkmg][Bb]$").matches(maxUploadSize)) {
log.error(
"Invalid maxUploadSize format. Expected format: [1-9][0-9]{0,2}[KMGkmg][Bb], but got: {}",
maxUploadSize);
return 0;
} else {
String unit = maxUploadSize.replaceAll("[1-9][0-9]{0,2}", "").toUpperCase();
String number = maxUploadSize.replaceAll("[KMGkmg][Bb]", "");
long size = Long.parseLong(number);
return switch (unit) {
case "KB" -> size * 1024;
case "MB" -> size * 1024 * 1024;
case "GB" -> size * 1024 * 1024 * 1024;
default -> 0;
};
}
}
@Bean(name = "RunningInDocker")
public boolean runningInDocker() {
return Files.exists(Paths.get("/.dockerenv"));

View File

@ -0,0 +1,30 @@
package stirling.software.SPDF.controller.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@Component
@ControllerAdvice
public class GlobalUploadLimitWebController {
@Autowired() private long uploadLimit;
@ModelAttribute("uploadLimit")
public long populateUploadLimit() {
return uploadLimit;
}
@ModelAttribute("uploadLimitReadable")
public String populateReadableLimit() {
return humanReadableByteCount(uploadLimit);
}
private String humanReadableByteCount(long bytes) {
if (bytes < 1024) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(1024));
String pre = "KMGTPE".charAt(exp - 1) + "B";
return String.format("%.1f %s", bytes / Math.pow(1024, exp), pre);
}
}

View File

@ -290,6 +290,7 @@ public class ApplicationProperties {
private Boolean disableSanitize;
private Boolean enableUrlToPDF;
private CustomPaths customPaths = new CustomPaths();
private String fileUploadLimit;
public boolean isAnalyticsEnabled() {
return this.getEnableAnalytics() != null && this.getEnableAnalytics();

View File

@ -63,6 +63,8 @@ public class PostHogService {
if (!applicationProperties.getSystem().isAnalyticsEnabled()) {
return;
}
properties.put("app_version", appVersion);
postHog.capture(uniqueId, eventName, properties);
}

View File

@ -10,6 +10,9 @@ multiPdfPrompt=اختر ملفات PDF (2+)
multiPdfDropPrompt=حدد (أو اسحب وأفلت) جميع ملفات PDF التي تحتاجها
imgPrompt=اختر صورة
genericSubmit=إرسال
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=تحذير: يمكن أن تستغرق هذه العملية ما يصل إلى دقيقة حسب حجم الملف
pageOrderPrompt=ترتيب الصفحات (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):
pageSelectionPrompt=اختيار الصفحات المخصص (أدخل قائمة بأرقام الصفحات مفصولة بفواصل 1،5،6 أو دوال مثل 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDFləri Seç (2+)
multiPdfDropPrompt=Ehtiyacınız olan bütün PDFləri seçin (və ya sürükləyib buraxın)
imgPrompt=Şəkil(lər)i Seç
genericSubmit=Təsdiq Et
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Xəbərdarlıq: Bu proses fayl ölçüsündən asılı olaraq bir dəqiqəyə qədər vaxt ala bilər
pageOrderPrompt=Xüsusi Səhifə Ardıcıllığı (Vergüllə ayrılmış səhifə nömrələri listini və ya 2n+1 tərzində Funksiyalar daxil edin) :
pageSelectionPrompt=Xüsusi Səhifə Seçimi (1, 5, 6 tərzində vergüllə ayrılmış səhifə nömrələri listini və ya 2n+1 tərzində Funksiyalar daxil edin) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Изберете PDF (2+)
multiPdfDropPrompt=Изберете (или плъзнете и пуснете) всички PDF файлове, от които се нуждаете
imgPrompt=Изберете изображение(я)
genericSubmit=Подайте
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла
pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1):
pageSelectionPrompt=Персонализиран избор на страница (Въведете списък с номера на страници 1,5,6, разделени със запетая, или функции като 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Selecciona PDFs (2+)
multiPdfDropPrompt=Selecciona (o arrossega) els documents PDF
imgPrompt=Selecciona Imatge(s)
genericSubmit=Envia
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Alerta: Aquest procés pot tardar 1 minut depenent de la mida de l'arxiu
pageOrderPrompt=Ordre de Pàgines (Llista separada per comes) :
pageSelectionPrompt=Selecció de pàgines personalitzada (Introdueix una llista separada per comes de números de pàgina, 1,5,6 o funcions com 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Vyberte PDF soubory (2+)
multiPdfDropPrompt=Vyberte (nebo přetáhněte) všechny požadované PDF soubory
imgPrompt=Vyberte obrázek(y)
genericSubmit=Odeslat
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Upozornění: Tento proces může trvat až minutu v závislosti na velikosti souboru
pageOrderPrompt=Vlastní pořadí stránek (Zadejte seznam čísel stránek oddělených čárkou nebo funkci jako např. 2n+1):
pageSelectionPrompt=Vlastní výběr stránek (Zadejte seznam čísel stránek oddělených čárkou jako 1,5,6 nebo funkci jako např. 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Vælg PDF-filerne (2+)
multiPdfDropPrompt=Vælg (eller drag & drop) alle PDF-filerne du skal bruge
imgPrompt=Vælg Billede(r)
genericSubmit=Indsend
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Advarsel: Denne proces kan tage op til et helt minut, alt efter størrelsen på filen
pageOrderPrompt=Brugerdefineret siderækkefølge (Indtast en kommasepareret liste af sidenumre eller funktioner som 2n+1) :
pageSelectionPrompt=Brugerdefineret sidevalg (Indtast en kommasepareret liste af sidenumre 1,5,6 eller funktioner som 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDFs auswählen(2+)
multiPdfDropPrompt=Wählen Sie alle gewünschten PDFs aus (oder ziehen Sie sie per Drag & Drop hierhin)
imgPrompt=Wählen Sie ein Bild
genericSubmit=Absenden
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Achtung: Abhängig von der Dateigröße kann dieser Prozess bis zu einer Minute dauern
pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Komma getrennte Liste von Seitenzahlen ein):
pageSelectionPrompt=Benutzerdefinierte Seitenauswahl (Geben Sie eine durch Kommas getrennte Liste von Seitenzahlen 1,5,6 oder Funktionen wie 2n+1 ein):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Επιλέξτε PDFs (2+)
multiPdfDropPrompt=Επιλέξτε (ή σύρετε & αφήστε) όλα τα PDF που χρειάζεστε
imgPrompt=Επιλέξτε εικόνα(ες)
genericSubmit=Υποβολή
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Προειδοποίηση: Αυτή η διαδικασία μπορεί να διαρκέσει έως ένα λεπτό ανάλογα με το μέγεθος του αρχείου
pageOrderPrompt=Προσαρμοσμένη σειρά σελίδων (Εισάγετε μια λίστα αριθμών σελίδων χωρισμένη με κόμματα ή συναρτήσεις όπως 2n+1):
pageSelectionPrompt=Προσαρμοσμένη επιλογή σελίδων (Εισάγετε μια λίστα αριθμών σελίδων χωρισμένη με κόμματα 1,5,6 ή συναρτήσεις όπως 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Select PDFs (2+)
multiPdfDropPrompt=Select (or drag & drop) all PDFs you require
imgPrompt=Select Image(s)
genericSubmit=Submit
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Warning: This process can take up to a minute depending on file-size
pageOrderPrompt=Custom Page Order (Enter a comma-separated list of page numbers or Functions like 2n+1) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Select PDFs (2+)
multiPdfDropPrompt=Select (or drag & drop) all PDFs you require
imgPrompt=Select Image(s)
genericSubmit=Submit
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Warning: This process can take up to a minute depending on file-size
pageOrderPrompt=Custom Page Order (Enter a comma-separated list of page numbers or Functions like 2n+1) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Seleccionar PDFs (2+)
multiPdfDropPrompt=Seleccione (o arrastre y suelte) todos los PDFs que quiera
imgPrompt=Seleccionar Imagen(es)
genericSubmit=Enviar
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Advertencia: este proceso puede tardar hasta un minuto dependiendo del tamaño del archivo
pageOrderPrompt=Orden de páginas (Introduzca una lista de números de página separados por coma):
pageSelectionPrompt=Selección de página personalizada (Intruduzca una lista de números de página separados por comas 1,5,6 o funciones como 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Hautatu PDFak (2+)
multiPdfDropPrompt=Hautatu (edo arrastatu eta jaregin) nahi dituzun PDFak
imgPrompt=Hautatu Irudia(k)
genericSubmit=Bidali
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Oharra: prozesu honetarako minutu bat ere beharko da fitxategiaren tamaiaren arabera
pageOrderPrompt=Orrialdeen ordena (sartu komaz bereizitako orrialde-zenbakien zerrenda)
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=انتخاب فایل‌های PDF (دو یا بیشتر)
multiPdfDropPrompt=انتخاب (یا کشیدن و رها کردن) تمام فایل‌های PDF مورد نیاز
imgPrompt=انتخاب تصویر(ها)
genericSubmit=ارسال
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=هشدار: این فرآیند ممکن است بسته به اندازه فایل تا یک دقیقه طول بکشد
pageOrderPrompt=ترتیب صفحات سفارشی (یک لیست از شماره صفحات به صورت جدا شده با کاما وارد کنید یا از توابعی مانند 2n+1 استفاده کنید):
pageSelectionPrompt=انتخاب صفحات سفارشی (یک لیست از شماره صفحات به صورت جدا شده با کاما وارد کنید مانند 1,5,6 یا از توابعی مانند 2n+1 استفاده کنید):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Sélectionnez les PDF
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
imgPrompt=Choisir une image
genericSubmit=Envoyer
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Attention, ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier.
pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Roghnaigh PDFs (2+)
multiPdfDropPrompt=Roghnaigh (nó tarraing & scaoil) gach PDF atá uait
imgPrompt=Roghnaigh Íomhá(í)
genericSubmit=Cuir isteach
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Rabhadh: Féadfaidh an próiseas seo suas le nóiméad a ghlacadh ag brath ar mhéid an chomhaid
pageOrderPrompt=Ordú Leathanach Saincheaptha (Iontráil liosta uimhreacha leathanaigh nó Feidhmeanna ar nós 2n+1 le camóga deighilte):
pageSelectionPrompt=Roghnú Leathanach Saincheaptha (Iontráil liosta leathanach scartha le camóg d'uimhreacha 1,5,6 nó Feidhmeanna ar nós 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=पीडीएफ फ़ाइलें चुनें (2+)
multiPdfDropPrompt=आवश्यक सभी पीडीएफ फ़ाइलों को चुनें (या खींच कर छोड़ें)
imgPrompt=छवि(यां) चुनें
genericSubmit=जमा करें
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=चेतावनी: फ़ाइल के आकार के आधार पर यह प्रक्रिया एक मिनट तक ले सकती है
pageOrderPrompt=कस्टम पृष्ठ क्रम (पृष्ठ संख्याओं की अल्पविराम से अलग सूची या 2n+1 जैसे फ़ंक्शन दर्ज करें):
pageSelectionPrompt=कस्टम पृष्ठ चयन (पृष्ठ संख्याओं 1,5,6 या 2n+1 जैसे फ़ंक्शन की अल्पविराम से अलग सूची दर्ज करें):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Odaberi PDF-ove (2+)
multiPdfDropPrompt=Odaberi (ili povuci i ispusti) sve potrebne PDF-ove
imgPrompt=Odaberi sliku (slike)
genericSubmit=Pošalji
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Upozorenje: Ovaj proces može trajati i do minutu, u zavisnosti od veličine dokumenta
pageOrderPrompt=Prilagođeni redoslijed stranica (unesi listu brojeva stranica ili funkcija, kao što su 2n+1, razdvojene zarezima) :
pageSelectionPrompt=Prilagođeni odabir stranica (unesi listu brojeva stranica ili funkcija, kao što su 2n+1, razdvojene zarezima) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDF-fájlok kiválasztása (2+)
multiPdfDropPrompt=Válassza ki (vagy húzza ide) az összes szükséges PDF-fájlt
imgPrompt=Kép kiválasztása
genericSubmit=Küldés
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Figyelmeztetés: A folyamat akár egy percig is eltarthat a fájlmérettől függően
pageOrderPrompt=Egyedi oldalsorrend (Adja meg az oldalszámokat vesszővel elválasztva vagy használjon függvényeket, pl. 2n+1):
pageSelectionPrompt=Egyedi oldalválasztás (Adja meg az oldalszámokat vesszővel elválasztva, pl. 1,5,6 vagy használjon függvényeket, pl. 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Pilih PDF (2+)
multiPdfDropPrompt=Pilih (atau seret & letakkan)) semua PDF yang Anda butuhkan
imgPrompt=Pilih Gambar
genericSubmit=Kirim
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Peringatan: Proses ini dapat memakan waktu hingga satu menit, tergantung pada ukuran berkas
pageOrderPrompt=Urutan Halaman Khusus (Masukkan daftar nomor halaman yang dipisahkan dengan koma atau Fungsi seperti 2n + 1) :
pageSelectionPrompt=Pemilihan Halaman Kustom (Masukkan daftar nomor halaman dipisahkan dengan koma 1,5,6 atau Fungsi seperti 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Scegli 2 o più PDF
multiPdfDropPrompt=Scegli (o trascina e rilascia) uno o più PDF
imgPrompt=Scegli immagine/i
genericSubmit=Invia
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Nota: Questo processo potrebbe richiedere fino a un minuto in base alla dimensione dei file
pageOrderPrompt=Ordine delle pagine (inserisci una lista di numeri separati da virgola):
pageSelectionPrompt=Selezione pagina personalizzata (inserisci un elenco separato da virgole di numeri di pagina 1,5,6 o funzioni come 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDFを選択 (2つ以上)
multiPdfDropPrompt=PDFを選択 (又はドラッグ&ドロップ)
imgPrompt=画像を選択
genericSubmit=送信
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=警告:この処理はファイルサイズによって1分程度かかることがあります
pageOrderPrompt=ページ順序 (ページ番号をカンマ区切り又は2n+1のような関数で入力):
pageSelectionPrompt=カスタムページ選択(ページ番号1、5、6または2n + 1などの関数のコンマ区切りリストを入力します):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDF 선택 (2개 이상)
multiPdfDropPrompt=필요한 모든 PDF를 선택(또는 끌어다 놓기)하세요
imgPrompt=이미지 선택
genericSubmit=제출
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=경고: 이 과정은 파일 크기에 따라 최대 1분이 소요될 수 있습니다
pageOrderPrompt=사용자 지정 페이지 순서 (쉼표로 구분된 페이지 번호 목록 또는 2n+1과 같은 함수 입력):
pageSelectionPrompt=사용자 지정 페이지 선택 (페이지 번호 1,5,6 또는 2n+1과 같은 함수를 쉼표로 구분하여 목록 입력):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Selecteer PDF's (2+)
multiPdfDropPrompt=Selecteer (of sleep & zet neer) alle PDF's die je nodig hebt
imgPrompt=Selecteer afbeelding(en)
genericSubmit=Indienen
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Waarschuwing: Dit proces kan tot een minuut duren afhankelijk van de bestandsgrootte
pageOrderPrompt=Aangepaste pagina volgorde (Voer een komma-gescheiden lijst van paginanummers of functies in, zoals 2n+1) :
pageSelectionPrompt=Aangepaste pagina selectie (Voer een komma-gescheiden lijst van paginanummer 1,5,6 of functies zoals 2n+1 in) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Velg PDF-filer (2+)
multiPdfDropPrompt=Velg (eller dra og slipp) alle PDF-ene du trenger
imgPrompt=Velg Bilde(r)
genericSubmit=Send inn
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Denne prosessen kan ta opptil ett minutt avhengig av filstørrelse
pageOrderPrompt=Tilpasset side rekkefølge (Skriv inn en kommaseparert liste over sidetall eller funksjoner som 2n+1):
pageSelectionPrompt=Tilpasset Sidevalg (Skriv inn en kommaseparert liste over sidetall 1,5,6 eller Funksjoner som 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Wybierz PDF (2+)
multiPdfDropPrompt=Wybierz (lub przeciągnij i puść) wszystkie dokumenty PDF
imgPrompt=Wybierz obraz(y)
genericSubmit=Wyślij
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Ostrzeżenie: Ten proces może potrwać do minuty, w zależności od rozmiaru pliku
pageOrderPrompt=Kolejność stron (wprowadź listę numerów stron oddzielonych przecinkami) :
pageSelectionPrompt=Niestandardowy wybór strony (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Selecione os PDFs (2+)
multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs desejados:
imgPrompt=Selecione a(s) Imagem(ns)
genericSubmit=Enviar
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Aviso: Este processo pode levar até um minuto, dependendo do tamanho do arquivo
pageOrderPrompt=Ordem de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula ou funções como 2n+1):
pageSelectionPrompt=Seleção de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula como 1,5,6 ou funções como 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Selecione PDFs (2+)
multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs necessários
imgPrompt=Selecione Imagem(ns)
genericSubmit=Submeter
uploadLimit=Tamanho máximo de ficheiro:
uploadLimitExceededSingular=é muito grande. O tamanho máximo permitido é
uploadLimitExceededPlural=são muito grandes. O tamanho máximo permitido é
processTimeWarning=Aviso: Este processo pode demorar até um minuto dependendo do tamanho do ficheiro
pageOrderPrompt=Ordem Personalizada de Páginas (Insira uma lista de números de página separados por vírgulas ou Funções como 2n+1):
pageSelectionPrompt=Seleção Personalizada de Páginas (Insira uma lista de números de página separados por vírgulas 1,5,6 ou Funções como 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Selectează mai multe fișiere PDF (2+)
multiPdfDropPrompt=Selectează (sau trage și plasează) toate fișierele PDF de care ai nevoie
imgPrompt=Selectează imagini
genericSubmit=Trimite
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Avertisment: Acest proces poate dura până la un minut în funcție de dimensiunea fișierului
pageOrderPrompt=Ordinea paginilor (Introdu o listă separată prin virgulă de numere de pagină):
pageSelectionPrompt=Selecție Personalizată de Pagini (Introduceți o listă separată prin virgule a numerelor de pagini 1,5,6 sau funcții precum 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Выберите PDF-файлы (2+)
multiPdfDropPrompt=Выберите (или перетащите) все необходимые PDF-файлы
imgPrompt=Выберите изображение(я)
genericSubmit=Отправить
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Внимание: Данный процесс может занять до минуты в зависимости от размера файла
pageOrderPrompt=Пользовательский порядок страниц (Введите список номеров страниц через запятую или функции типа 2n+1):
pageSelectionPrompt=Выбор страниц (Введите список номеров страниц через запятую 1,5,6 или функции типа 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Vyberte PDF súbory (2+)
multiPdfDropPrompt=Vyberte (alebo pretiahnite) všetky požadované PDF súbory
imgPrompt=Vyberte obrázok(y)
genericSubmit=Odoslať
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Varovanie: Tento proces môže trvať až minútu v závislosti od veľkosti súboru
pageOrderPrompt=Vlastné poradie stránok (Zadajte zoznam čísel stránok oddelených čiarkou alebo funkcie ako 2n+1):
pageSelectionPrompt=Vlastný výber stránok (Zadajte zoznam čísel stránok oddelených čiarkou 1,5,6 alebo funkcie ako 2n+1):

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Izberi PDF (2+)
multiPdfDropPrompt=Izberite (ali povlecite in spustite) vse datoteke PDF, ki jih potrebujete
imgPrompt=Izberite sliko(e)
genericSubmit=Pošlji
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Opozorilo: ta postopek lahko traja do minute, odvisno od velikosti datoteke
pageOrderPrompt=Vrstni red strani po meri (Vnesite z vejicami ločen seznam številk strani ali funkcij, kot je 2n+1) :
pageSelectionPrompt=Izbira strani po meri (Vnesite z vejicami ločen seznam številk strani 1,5,6 ali funkcije, kot je 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Odaberi PDF-ove (2+)
multiPdfDropPrompt=Odaberi (prevuci i pusti ) sve PDF-ove koji su vam potrebni
imgPrompt=Odaberi sliku (slike)
genericSubmit=Prihvatiti
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Warning:Upozorenje: Ovaj proces može trajati i do minut, u zavisnosti od veličine dokumenta
pageOrderPrompt=Prilagođeni redosled stranica (unesi listu brojeva stranica ili funkcija, kao što su 2n+1, razdvojene zarezima) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Välj PDF-filer (2+)
multiPdfDropPrompt=Välj (eller dra och släpp) alla PDF-filer du behöver
imgPrompt=Välj bild(er)
genericSubmit=Skicka
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Varning: Denna process kan ta upp till en minut beroende på filstorlek
pageOrderPrompt=Sidordning (Ange en kommaseparerad lista med sidnummer) :
pageSelectionPrompt=Anpassat sidval (Ange en kommaseparerad lista med sidnummer 1,5,6 eller funktioner som 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=เลือก PDF หลายไฟล์ (2 ขึ้นไ
multiPdfDropPrompt=เลือก (หรือลากและวาง) PDF ทั้งหมดที่คุณต้องการ
imgPrompt=เลือกภาพ
genericSubmit=ส่ง
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=คำเตือน: กระบวนการนี้อาจใช้เวลาสูงสุดหนึ่งนาทีขึ้นอยู่กับขนาดไฟล์
pageOrderPrompt=เรียงลำดับหน้าตามความต้องการ (ป้อนหมายเลขหน้าแยกด้วยเครื่องหมายจุลภาคหรือฟังก์ชัน เช่น 2n+1) :
pageSelectionPrompt=เลือกหน้าตามความต้องการ (ป้อนหมายเลขหน้าแยกด้วยเครื่องหมายจุลภาค เช่น 1,5,6 หรือฟังก์ชัน เช่น 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDFleri seçin (2+)
multiPdfDropPrompt=Tüm gerekli PDF'leri seçin (ya da sürükleyip bırakın)
imgPrompt=Resim(leri) seçin
genericSubmit=Gönder
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Uyarı: Bu işlem, dosya boyutuna bağlı olarak bir dakikaya kadar sürebilir.
pageOrderPrompt=Özel Sayfa Sırası (Virgülle ayrılmış sayfa numaraları veya 2n+1 gibi bir fonksiyon girin) :
pageSelectionPrompt=Özel Sayfa Seçimi (1,5,6 sayfa numaralarının virgülle ayrılmış bir listesini veya 2n+1 gibi bir fonksiyon girin) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Оберіть PDFи (2+)
multiPdfDropPrompt=Оберіть (або перетягніть) всі необхідні PDFи
imgPrompt=Оберіть зображення(я)
genericSubmit=Надіслати
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Увага: Цей процес може тривати до хвилини в залежності від розміру файлу.
pageOrderPrompt=Порядок сторінок (введіть список номерів сторінок через кому):
pageSelectionPrompt=Користувацький вибір сторінки (введіть список номерів сторінок через кому 1,5,6 або функції типу 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=Chọn các tệp PDF (2+)
multiPdfDropPrompt=Chọn (hoặc kéo và thả) tất cả các tệp PDF bạn cần
imgPrompt=Chọn (các) hình ảnh
genericSubmit=Gửi
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=Cảnh báo: Quá trình này có thể mất đến một phút tùy thuộc vào kích thước tệp
pageOrderPrompt=Thứ tự trang tùy chỉnh (Nhập danh sách số trang được phân tách bằng dấu phẩy hoặc Các hàm như 2n+1) :
pageSelectionPrompt=Lựa chọn trang tùy chỉnh (Nhập danh sách số trang được phân tách bằng dấu phẩy 1,5,6 hoặc Các hàm như 2n+1) :

View File

@ -10,6 +10,9 @@ multiPdfPrompt=PDF གཉིས་ཡན་འདེམས་རོགས།
multiPdfDropPrompt=དགོས་མཁོ་འདི་ PDF ཡིག་ཆ་ཚང་མ་འདེམས་པའམ་འཐེན་རོགས།
imgPrompt=པར་རིས་འདེམས་རོགས།
genericSubmit=ཕུལ་བཅོས།
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=ཉེན་བཅོས། བྱ་རིམ་འདི་ཡིག་ཆའི་ཆེ་ཆུང་ལ་གཞིགས་ནས་སྐར་མ་གཅིག་བར་འགོར་སྲིད།
pageOrderPrompt=ཤོག་ངོས་གོ་རིམ་རང་སྒྲིག(ཤོག་གྲངས་ཀྱི་ཐོ་གཞུང་ངམ་རྩིས་རྒྱག་བྱེད་ཐབས་ 2n+1 ལྟ་བུ་འཇུག་རོགས།)
pageSelectionPrompt=ཤོག་ངོས་འདེམས་སྒྲུག(ཤོག་གྲངས་ཀྱི་ཐོ་གཞུང་ 1,5,6 འམ་རྩིས་རྒྱག་བྱེད་ཐབས་ 2n+1 ལྟ་བུ་འཇུག་རོགས།)

View File

@ -10,6 +10,9 @@ multiPdfPrompt=选择多个 PDF2个或更多
multiPdfDropPrompt=选择(或拖拽)所需的 PDF
imgPrompt=选择图像
genericSubmit=提交
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小
pageOrderPrompt=页面顺序(输入逗号分隔的页码列表或函数):
pageSelectionPrompt=自定义页面选择输入以逗号分隔的页码列表或函数1,5,6、2n+1

View File

@ -10,6 +10,9 @@ multiPdfPrompt=選擇多個 PDF 檔案
multiPdfDropPrompt=選擇(或拖放)所有需要的 PDF 檔案
imgPrompt=選擇圖片
genericSubmit=送出
uploadLimit=Maximum file size:
uploadLimitExceededSingular=is too large. Maximum allowed size is
uploadLimitExceededPlural=are too large. Maximum allowed size is
processTimeWarning=警告:此過程可能長達一分鐘,具體取決於檔案大小
pageOrderPrompt=自訂頁面順序(輸入以逗號分隔的頁碼或函式,如 2n+1
pageSelectionPrompt=自訂頁面選擇(輸入以逗號分隔的頁碼 1、5、6 或 2n+1 等函式的清單):

View File

@ -110,6 +110,7 @@ system:
operations:
weasyprint: '' #Defaults to /opt/venv/bin/weasyprint
unoconvert: '' #Defaults to /opt/venv/bin/unoconvert
fileUploadLimit: '' # Defaults to "". No limit when string is empty. Set a number, between 0 and 999, followed by one of the following strings to set a limit. "KB", "MB", "GB".
ui:
appName: '' # application's visible name

View File

@ -43,6 +43,20 @@
firstErrorOccurred = false;
const url = this.action;
let files = $('#fileInput-input')[0].files;
const uploadLimit = window.stirlingPDF?.uploadLimit ?? 0;
if (uploadLimit > 0) {
const oversizedFiles = Array.from(files).filter(f => f.size > uploadLimit);
if (oversizedFiles.length > 0) {
const names = oversizedFiles.map(f => `"${f.name}"`).join(', ');
if (names.length === 1) {
alert(`${names} ${window.stirlingPDF.uploadLimitExceededSingular} ${window.stirlingPDF.uploadLimitReadable}.`);
} else {
alert(`${names} ${window.stirlingPDF.uploadLimitExceededPlural} ${window.stirlingPDF.uploadLimitReadable}.`);
}
files = Array.from(files).filter(f => f.size <= uploadLimit);
if (files.length === 0) return;
}
}
const formData = new FormData(this);
const submitButton = document.getElementById('submitBtn');
const showGameBtn = document.getElementById('show-game-btn');

View File

@ -196,6 +196,28 @@ function setupFileInput(chooser) {
await checkZipFile();
const uploadLimit = window.stirlingPDF?.uploadLimit ?? 0;
if (uploadLimit > 0) {
const oversizedFiles = allFiles.filter(f => f.size > uploadLimit);
if (oversizedFiles.length > 0) {
const names = oversizedFiles.map(f => `"${f.name}"`).join(', ');
if (names.length === 1) {
alert(`${names} ${window.stirlingPDF.uploadLimitExceededSingular} ${window.stirlingPDF.uploadLimitReadable}.`);
} else {
alert(`${names} ${window.stirlingPDF.uploadLimitExceededPlural} ${window.stirlingPDF.uploadLimitReadable}.`);
}
allFiles = allFiles.filter(f => f.size <= uploadLimit);
const dataTransfer = new DataTransfer();
allFiles.forEach(f => dataTransfer.items.add(f));
input.files = dataTransfer.files;
if (allFiles.length === 0) {
inputContainer.querySelector('#fileInputText').innerHTML = originalText;
return;
}
}
}
allFiles = await Promise.all(
allFiles.map(async (file) => {
let decryptedFile = file;

View File

@ -331,7 +331,7 @@ window.addEventListener('load', (e) => {
document.selection.empty();
}
}
viewer.onmouseup = (e) => {
if (redactionMode !== RedactionModes.TEXT) return;
const containsText = window.getSelection() && window.getSelection().toString() != '';

View File

@ -84,13 +84,11 @@
function UpdatePosthogConsent(){
if(typeof(posthog) == "undefined") {
console.log("Posthog not initialised");
return;
}
window.CookieConsent.acceptedCategory('analytics')?
posthog.opt_in_capturing() : posthog.opt_out_capturing();
console.log("Posthog: Opted " + (posthog.has_opted_out_capturing()? "out" : "in"));
}
const stirlingPDFLabel = /*[[${@StirlingPDFLabel}]]*/ '';
const analyticsEnabled = /*[[${@analyticsEnabled}]]*/ false;
@ -150,8 +148,9 @@
const baseUrl = window.location.hostname;
posthog.register_once({
'hostname': baseUrl,
'UUID': /*[[${@UUID}]]*/ ''
})
'UUID': /*[[${@UUID}]]*/ '',
'app_version': /*[[${@appVersion}]]*/ '',
});
}
window.addEventListener("cc:onConsent", UpdatePosthogConsent);
@ -241,6 +240,10 @@
window.stirlingPDF.sessionExpired = /*[[#{session.expired}]]*/ '';
window.stirlingPDF.refreshPage = /*[[#{session.refreshPage}]]*/ 'Refresh Page';
window.stirlingPDF.error = /*[[#{error}]]*/ "Error";
window.stirlingPDF.uploadLimit = /*[[${uploadLimit}]]*/ 0;
window.stirlingPDF.uploadLimitReadable = /*[[${uploadLimitReadable}]]*/ 'Unlimited';
window.stirlingPDF.uploadLimitExceededSingular = /*[[#{uploadLimitExceededSingular}]]*/ 'is too large. Maximum allowed size is';
window.stirlingPDF.uploadLimitExceededPlural = /*[[#{uploadLimitExceededPlural}]]*/ 'are too large. Maximum allowed size is';
})();
</script>
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
@ -289,8 +292,11 @@
</div>
</div>
<div class="selected-files flex-wrap"></div>
<div class="text-muted small mt-0 text-end w-100" th:if="${uploadLimit != 0}">
<span th:text="#{uploadLimit}">Maximum file size: </span>
<span th:text="${uploadLimitReadable}"></span>
</div>
</div>
<div class="progressBarContainer" style="display: none; position: relative;">
<div class="progress" style="height: 1rem;">
<div class="progressBar progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar"