Compare commits

..

11 Commits

Author SHA1 Message Date
Anthony Stirling
1e2eb9b07a additional fix to #364 2023-09-24 21:21:01 +01:00
Anthony Stirling
ece00956d9 fix for config #376 2023-09-24 21:09:34 +01:00
Anthony Stirling
af5bbd8838 Merge pull request #375 from slikie/patch-2
Docs Fix - Ensure proper context path format
2023-09-20 09:21:07 -05:00
slikie
3a8f2495ea fix: Docs - Ensure proper context path format 2023-09-20 22:12:47 +08:00
slikie
993f5e5097 Update README.md
spelling
2023-09-20 22:08:31 +08:00
Anthony Stirling
05ebf3a6b4 Merge pull request #366 from Frooodle/image
image to pdf change and cert atempt fix
2023-09-17 21:21:19 +01:00
Anthony Stirling
1be3046d26 version bump 2023-09-17 21:17:47 +01:00
Anthony Stirling
5b3858ba29 image changes and cert fix 2023-09-17 21:17:13 +01:00
Anthony Stirling
a1f388e524 Merge pull request #365 from NeilJared/main
Update messages_es_ES.properties
2023-09-17 08:04:52 +01:00
NeilJared
cf14ff1540 Update messages_es_ES.properties
Updated es_ES translation including changes of the latest version
2023-09-16 23:39:12 +02:00
Anthony Stirling
a0ac2bc02a Update build.gradle 2023-09-14 21:25:18 +01:00
27 changed files with 385 additions and 232 deletions

View File

@@ -222,7 +222,7 @@ metrics:
- customStaticFilePath. Customise static files such as the app logo by placing files in the /customFiles/static/ directory. An example of customising app logo is placing a /customFiles/static/favicon.svg to override current SVG. This can be used to change any images/icons/css/fonts/js etc in Stirling-PDF
### Environment only parameters
- ``SYSTEM_ROOTURIPATH`` ie set to ``pdf-app`` to Set the application's root URI tp ``localhost:8080/pdf-app``
- ``SYSTEM_ROOTURIPATH`` ie set to ``/pdf-app`` to Set the application's root URI to ``localhost:8080/pdf-app``
- ``SYSTEM_CONNECTIONTIMEOUTMINUTES`` to set custom connection timeout values
- ``DOCKER_ENABLE_SECURITY`` to tell docker to download security jar (required as true for auth login)

View File

@@ -8,7 +8,7 @@ plugins {
}
group = 'stirling.software'
version = '0.14.1'
version = '0.14.3'
sourceCompatibility = '17'
repositories {
@@ -34,7 +34,7 @@ sourceSets {
openApi {
apiDocsUrl = "http://localhost:8080/v3/api-docs"
apiDocsUrl = "http://localhost:8080/v1/api-docs"
outputDir = file("$projectDir")
outputFileName = "SwaggerDoc.json"
}

View File

@@ -12,6 +12,8 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationContextInitializer;
@@ -19,83 +21,109 @@ import org.springframework.context.ConfigurableApplicationContext;
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
try {
ensureConfigExists();
} catch (IOException e) {
throw new RuntimeException("Failed to initialize application configuration", e);
}
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
try {
ensureConfigExists();
} catch (IOException e) {
throw new RuntimeException("Failed to initialize application configuration", e);
}
}
public void ensureConfigExists() throws IOException {
// Define the path to the external config directory
Path destPath = Paths.get("configs", "settings.yml");
public void ensureConfigExists() throws IOException {
// Define the path to the external config directory
Path destPath = Paths.get("configs", "settings.yml");
// Check if the file already exists
if (Files.notExists(destPath)) {
// Ensure the destination directory exists
Files.createDirectories(destPath.getParent());
// Check if the file already exists
if (Files.notExists(destPath)) {
// Ensure the destination directory exists
Files.createDirectories(destPath.getParent());
// Copy the resource from classpath to the external directory
try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
if (in != null) {
Files.copy(in, destPath);
} else {
throw new FileNotFoundException("Resource file not found: settings.yml.template");
}
}
} else {
// If user file exists, we need to merge it with the template from the classpath
List<String> templateLines;
try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
templateLines = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)).lines().collect(Collectors.toList());
}
// Copy the resource from classpath to the external directory
try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
if (in != null) {
Files.copy(in, destPath);
} else {
throw new FileNotFoundException("Resource file not found: settings.yml.template");
}
}
} else {
// If user file exists, we need to merge it with the template from the classpath
List<String> templateLines;
try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
templateLines = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)).lines()
.collect(Collectors.toList());
}
mergeYamlFiles(templateLines, destPath, destPath);
}
}
mergeYamlFiles(templateLines, destPath, destPath);
}
}
public void mergeYamlFiles(List<String> templateLines, Path userFilePath, Path outputPath) throws IOException {
List<String> userLines = Files.readAllLines(userFilePath);
public void mergeYamlFiles(List<String> templateLines, Path userFilePath, Path outputPath) throws IOException {
List<String> userLines = Files.readAllLines(userFilePath);
List<String> mergedLines = new ArrayList<>();
boolean insideAutoGenerated = false;
boolean beforeFirstKey = true;
List<String> mergedLines = new ArrayList<>();
boolean insideAutoGenerated = false;
Function<String, Boolean> isCommented = line -> line.trim().startsWith("#");
Function<String, String> extractKey = line -> {
String[] parts = line.split(":");
return parts.length > 0 ? parts[0].trim().replace("#", "").trim() : "";
};
for (String line : templateLines) {
// Check if we've entered or left the AutomaticallyGenerated section
if (line.trim().equalsIgnoreCase("AutomaticallyGenerated:")) {
insideAutoGenerated = true;
mergedLines.add(line);
continue;
} else if (insideAutoGenerated && line.trim().isEmpty()) {
// We have reached the end of the AutomaticallyGenerated section
insideAutoGenerated = false;
mergedLines.add(line);
continue;
}
Set<String> userKeys = userLines.stream().map(extractKey).collect(Collectors.toSet());
if (insideAutoGenerated) {
// Add lines from user's settings if we are inside AutomaticallyGenerated
Optional<String> userAutoGenValue = userLines.stream().filter(l -> l.trim().startsWith(line.split(":")[0].trim())).findFirst();
if (userAutoGenValue.isPresent()) {
mergedLines.add(userAutoGenValue.get());
continue;
}
} else {
// Outside of AutomaticallyGenerated, continue as before
if (line.contains(": ")) {
String key = line.split(": ")[0].trim();
Optional<String> userValue = userLines.stream().filter(l -> l.trim().startsWith(key)).findFirst();
if (userValue.isPresent()) {
mergedLines.add(userValue.get());
continue;
}
}
mergedLines.add(line);
}
}
for (String line : templateLines) {
String key = extractKey.apply(line);
if (line.trim().equalsIgnoreCase("AutomaticallyGenerated:")) {
insideAutoGenerated = true;
mergedLines.add(line);
continue;
} else if (insideAutoGenerated && line.trim().isEmpty()) {
insideAutoGenerated = false;
mergedLines.add(line);
continue;
}
if (beforeFirstKey && (isCommented.apply(line) || line.trim().isEmpty())) {
// Handle top comments and empty lines before the first key.
mergedLines.add(line);
continue;
}
if (!key.isEmpty())
beforeFirstKey = false;
if (userKeys.contains(key)) {
// If user has any version (commented or uncommented) of this key, skip the
// template line
Optional<String> userValue = userLines.stream()
.filter(l -> extractKey.apply(l).equalsIgnoreCase(key) && !isCommented.apply(l)).findFirst();
if (userValue.isPresent())
mergedLines.add(userValue.get());
continue;
}
if (isCommented.apply(line) || line.trim().isEmpty() || !userKeys.contains(key)) {
mergedLines.add(line); // If line is commented, empty or key not present in user's file, retain the
// template line
continue;
}
}
// Add any additional uncommented user lines that are not present in the
// template
for (String userLine : userLines) {
String userKey = extractKey.apply(userLine);
boolean isPresentInTemplate = templateLines.stream().map(extractKey)
.anyMatch(templateKey -> templateKey.equalsIgnoreCase(userKey));
if (!isPresentInTemplate && !isCommented.apply(userLine)) {
mergedLines.add(userLine);
}
}
Files.write(outputPath, mergedLines, StandardCharsets.UTF_8);
}
Files.write(outputPath, mergedLines, StandardCharsets.UTF_8);
}
}

View File

@@ -79,12 +79,12 @@ public class ConvertImgPDFController {
description = "This endpoint converts one or more images to a PDF file. Users can specify whether to stretch the images to fit the PDF page, and whether to automatically rotate the images. Input:Image Output:PDF Type:SISO?")
public ResponseEntity<byte[]> convertToPdf(@ModelAttribute ConvertToPdfRequest request) throws IOException {
MultipartFile[] file = request.getFileInput();
boolean stretchToFit = request.isStretchToFit();
String fitOption = request.getFitOption();
String colorType = request.getColorType();
boolean autoRotate = request.isAutoRotate();
// Convert the file to PDF and get the resulting bytes
byte[] bytes = PdfUtils.imageToPdf(file, stretchToFit, autoRotate, colorType);
byte[] bytes = PdfUtils.imageToPdf(file, fitOption, autoRotate, colorType);
return WebResponseUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_converted.pdf");
}

View File

@@ -12,6 +12,7 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
@@ -130,7 +131,8 @@ public class CertSignController {
signature.setName(name);
signature.setLocation(location);
signature.setReason(reason);
signature.setSignDate(Calendar.getInstance());
// Load the PDF
try (PDDocument document = PDDocument.load(pdf.getBytes())) {
logger.info("Successfully loaded the provided PDF");

View File

@@ -13,8 +13,11 @@ public class ConvertToPdfRequest {
@Schema(description = "The input images to be converted to a PDF file")
private MultipartFile[] fileInput;
@Schema(description = "Whether to stretch the images to fit the PDF page or maintain the aspect ratio", example = "false")
private boolean stretchToFit;
@Schema(description = "Option to determine how the image will fit onto the page",
allowableValues = { "fillPage", "fitDocumentToImage", "maintainAspectRatio" })
private String fitOption;
@Schema(description = "The color type of the output image(s)", allowableValues = {"color", "greyscale", "blackwhite"})
private String colorType;

View File

@@ -248,7 +248,7 @@ public class PdfUtils {
throw e;
}
}
public static byte[] imageToPdf(MultipartFile[] files, boolean stretchToFit, boolean autoRotate, String colorType) throws IOException {
public static byte[] imageToPdf(MultipartFile[] files, String fitOption, boolean autoRotate, String colorType) throws IOException {
try (PDDocument doc = new PDDocument()) {
for (MultipartFile file : files) {
String contentType = file.getContentType();
@@ -261,7 +261,7 @@ public class PdfUtils {
BufferedImage pageImage = reader.read(i);
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(pageImage, colorType);
PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
addImageToDocument(doc, pdImage, fitOption, autoRotate);
}
} else {
File imageFile = Files.createTempFile("image", ".png").toFile();
@@ -279,7 +279,7 @@ public class PdfUtils {
} else {
pdImage = LosslessFactory.createFromImage(doc, convertedImage);
}
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
addImageToDocument(doc, pdImage, fitOption, autoRotate);
} catch (IOException e) {
logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e);
throw e;
@@ -295,12 +295,20 @@ public class PdfUtils {
}
}
private static void addImageToDocument(PDDocument doc, PDImageXObject image, boolean stretchToFit, boolean autoRotate) throws IOException {
private static void addImageToDocument(PDDocument doc, PDImageXObject image, String fitOption, boolean autoRotate) throws IOException {
boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4;
System.out.println(fitOption);
if (autoRotate && imageIsLandscape) {
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
}
if ("fitDocumentToImage".equals(fitOption)) {
pageSize = new PDRectangle(image.getWidth(), image.getHeight());
}
PDPage page = new PDPage(pageSize);
doc.addPage(page);
@@ -308,9 +316,9 @@ public class PdfUtils {
float pageHeight = page.getMediaBox().getHeight();
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
if (stretchToFit) {
if ("fillPage".equals(fitOption) || "fitDocumentToImage".equals(fitOption)) {
contentStream.drawImage(image, 0, 0, pageWidth, pageHeight);
} else {
} else if ("maintainAspectRatio".equals(fitOption)) {
float imageAspectRatio = (float) image.getWidth() / (float) image.getHeight();
float pageAspectRatio = pageWidth / pageHeight;
@@ -331,6 +339,7 @@ public class PdfUtils {
}
}
public static byte[] overlayImage(byte[] pdfBytes, byte[] imageBytes, float x, float y, boolean everyPage) throws IOException {
PDDocument document = PDDocument.load(new ByteArrayInputStream(pdfBytes));

View File

@@ -665,7 +665,13 @@ split.submit=Split
imageToPDF.title=صورة إلى PDF
imageToPDF.header=صورة إلى PDF
imageToPDF.submit=تحول
imageToPDF.selectText.1=\u062A\u0645\u062F\u062F \u0644\u0644\u0645\u0644\u0627\u0621\u0645\u0629
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=\u062F\u0648\u0631\u0627\u0646 PDF \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627
imageToPDF.selectText.3=\u0627\u0644\u0645\u0646\u0637\u0642 \u0627\u0644\u0645\u062A\u0639\u062F\u062F \u0644\u0644\u0645\u0644\u0641\u0627\u062A (\u0645\u0641\u0639\u0651\u0644 \u0641\u0642\u0637 \u0625\u0630\u0627 \u0643\u0646\u062A \u062A\u0639\u0645\u0644 \u0645\u0639 \u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629)
imageToPDF.selectText.4=\u062F\u0645\u062C \u0641\u064A \u0645\u0644\u0641 PDF \u0648\u0627\u062D\u062F

View File

@@ -665,7 +665,13 @@ split.submit=Divideix
imageToPDF.title=Imatge a PDF
imageToPDF.header=Imatge a PDF
imageToPDF.submit=Converteix
imageToPDF.selectText.1=Estirar per adaptar
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Auto rota PDF
imageToPDF.selectText.3=Lògica de diversos fitxers (només està activada si es treballa amb diverses imatges)
imageToPDF.selectText.4=Combina en un únic PDF

View File

@@ -665,7 +665,13 @@ split.submit=Aufteilen
imageToPDF.title=Bild zu PDF
imageToPDF.header=Bild zu PDF
imageToPDF.submit=Umwandeln
imageToPDF.selectText.1=Auf Seite strecken
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=PDF automatisch drehen
imageToPDF.selectText.3=Mehrere Dateien verarbeiten (nur aktiv, wenn Sie mit mehreren Bildern arbeiten)
imageToPDF.selectText.4=In ein einziges PDF zusammenführen

View File

@@ -665,7 +665,10 @@ split.submit=Split
imageToPDF.title=Image to PDF
imageToPDF.header=Image to PDF
imageToPDF.submit=Convert
imageToPDF.selectText.1=Stretch to fit
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Auto rotate PDF
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
imageToPDF.selectText.4=Merge into single PDF

View File

@@ -665,7 +665,13 @@ split.submit=Split
imageToPDF.title=Image to PDF
imageToPDF.header=Image to PDF
imageToPDF.submit=Convert
imageToPDF.selectText.1=Stretch to fit
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Auto rotate PDF
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
imageToPDF.selectText.4=Merge into single PDF

View File

@@ -31,23 +31,23 @@ sizes.medium=Mediano
sizes.large=Grande
sizes.x-large=Extra grande
error.pdfPassword=El documento PDF está protegido con contraseña y no se ha proporcionado o es incorrecta
delete=Delete
username=Username
password=Password
welcome=Welcome
property=Property
black=Black
white=White
red=Red
green=Green
blue=Blue
custom=Custom...
delete=Borrar
username=Nombre de usuario
password=Contraseña
welcome=Bienvenido
property=Propietario
black=Negro
white=Blanco
red=Rojo
green=Verde
blue=Azul
custom=Personalizado...
changedCredsMessage=Credentials changed!
notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
changedCredsMessage=Se cambiaron las credenciales!
notAuthenticatedMessage=Usuario njo autentificado.
userNotFoundMessage=Usuario no encontrado.
incorrectPasswordMessage=La contraseña actual no es correcta.
usernameExistsMessage=El nuevo nombre de usuario está en uso.
@@ -59,12 +59,12 @@ navbar.security=Seguridad
navbar.other=Otro
navbar.darkmode=Modo oscuro
navbar.pageOps=Operaciones de página
navbar.settings=Ajustes
navbar.settings=Configuración
#############
# SETTINGS #
#############
settings.title=Ajustes
settings.title=Configuración
settings.update=Actualización disponible
settings.appVersion=Versión de la aplicación:
settings.downloadOption.title=Elegir la opción de descarga (para descargas de un solo archivo sin ZIP):
@@ -72,55 +72,55 @@ settings.downloadOption.1=Abrir en la misma ventana
settings.downloadOption.2=Abrir en una nueva ventana
settings.downloadOption.3=Descargar el fichero
settings.zipThreshold=Ficheros ZIP cuando excede el número de ficheros descargados
settings.signOut=Sign Out
settings.accountSettings=Account Settings
settings.signOut=Desconectar
settings.accountSettings=Configuración de la cuenta
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
changeCreds.confirmNewPassword=Confirm New Password
changeCreds.submit=Submit Changes
changeCreds.title=Cambiar Credenciales
changeCreds.header=Actualice los detalles de su cuenta
changeCreds.changeUserAndPassword=Está usando las credenciales por defecto. Por favor, introduzca una nueva contraseña (y usuario si lo desea)
changeCreds.newUsername=Nuevo usuario
changeCreds.oldPassword=Contraseña actual
changeCreds.newPassword=Nueva contraseña
changeCreds.confirmNewPassword=Confirme la nueva contraseña
changeCreds.submit=Enviar cambios
account.title=Account Settings
account.accountSettings=Account Settings
account.adminSettings=Admin Settings - View and Add Users
account.userControlSettings=User Control Settings
account.changeUsername=Change Username
account.changeUsername=Change Username
account.password=Confirmation Password
account.oldPassword=Old password
account.newPassword=New Password
account.changePassword=Change Password
account.confirmNewPassword=Confirm New Password
account.signOut=Sign Out
account.yourApiKey=Your API Key
account.syncTitle=Sync browser settings with Account
account.settingsCompare=Settings Comparison:
account.property=Property
account.webBrowserSettings=Web Browser Setting
account.syncToBrowser=Sync Account -> Browser
account.syncToAccount=Sync Account <- Browser
account.title=Configuración de la cuenta
account.accountSettings=Configuración de la cuenta
account.adminSettings=Configuración de Administrador - Ver y Añadir Usuarios
account.userControlSettings=Configuración de control de usuario
account.changeUsername=Cambiar nombre de usuario
account.changeUsername=Cambiar nombre de usuario
account.password=Confirmar contraseña
account.oldPassword=Contraseña anterior
account.newPassword=Nueva Contraseña
account.changePassword=Cambiar Contraseña
account.confirmNewPassword=Confirmar Nueva Contraseña
account.signOut=Cerrar sesión
account.yourApiKey=Su clave API
account.syncTitle=Sincronizar la configuración del navegador con la cuenta
account.settingsCompare=Comparación de configuraciones:
account.property=Propiedad
account.webBrowserSettings=Configuración del navegador
account.syncToBrowser=Sincronizar cuenta -> Navegador
account.syncToAccount=Sincronizar cuenta <- Navegador
adminUserSettings.title=User Control Settings
adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.title=Configuración de control de usuario
adminUserSettings.header=Configuración de control de usuario administrador
adminUserSettings.admin=Administrador
adminUserSettings.user=Usuario
adminUserSettings.addUser=Añadir Nuevo Usuario
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
adminUserSettings.webOnlyUser=Web Only User
adminUserSettings.forceChange=Force user to change username/password on login
adminUserSettings.submit=Save User
adminUserSettings.role=Rol
adminUserSettings.actions=Acciones
adminUserSettings.apiUser=Usuario limitado de API
adminUserSettings.webOnlyUser=Usuario solo web
adminUserSettings.forceChange=Forzar usuario a cambiar usuario/contraseña en el acceso
adminUserSettings.submit=Guardar Usuario
#############
# HOME-PAGE #
@@ -130,7 +130,7 @@ home.desc=Su ventanilla única autohospedada para todas tus necesidades PDF
home.multiTool.title=Multi-herramienta PDF
home.multiTool.desc=Combinar, rotar, reorganizar y eliminar páginas
multiTool.tags=Multi-herramienta,Multi-operación,Interfaz de usuario,Arrastrar con un click,front end,lado del client
multiTool.tags=Multi-herramienta,Multi-operación,Interfaz de usuario,Arrastrar con un click,front end,lado del cliente
home.merge.title=Unir
home.merge.desc=Unir fácilmente múltiples PDFs en uno
@@ -270,12 +270,12 @@ home.pipeline.title=Secuencia (Avanzado)
home.pipeline.desc=Ejecutar varias tareas a PDFs definiendo una secuencia de comandos
pipeline.tags=automatizar,secuencia,con script,proceso por lotes
home.add-page-numbers.title=Aádir números de página
home.add-page-numbers.desc=Aádir números de página en un documento en una ubicación concreta
home.add-page-numbers.title=Añadir números de página
home.add-page-numbers.desc=Añadir números de página en un documento en una ubicación concreta
add-page-numbers.tags=paginar,etiquetar,organizar,indexar
home.auto-rename.title=Auto renombrar archivo PDF
home.auto-rename.desc=Auto renormbrar un archivo PDF según su encabezamiento detecetado
home.auto-rename.desc=Auto renombrar un archivo PDF según el encabezamiento detectado
auto-rename.tags=auto-detectar,basado en el encabezamiento,organizar,re-etiquetar
home.adjust-contrast.title=Ajustar Color/Contraste
@@ -303,32 +303,32 @@ home.HTMLToPDF.desc=Convierte cualquier archivo HTML o ZIP a PDF
HTMLToPDF.tags=margen,contenido web,transformación,convertir
home.MarkdownToPDF.title=Markdown to PDF
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert
home.MarkdownToPDF.title=Markdown a PDF
home.MarkdownToPDF.desc=Convierte cualquier archivo Markdown a PDF
MarkdownToPDF.tags=margen,contenido web,transformación,convertir
home.getPdfInfo.title=Get ALL Info on PDF
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
getPdfInfo.tags=infomation,data,stats,statistics
home.getPdfInfo.title=Obtener toda la información en PDF
home.getPdfInfo.desc=Obtiene toda la información posible de archivos PDF
getPdfInfo.tags=información,datos,stats,estasticas
home.extractPage.title=Extract page(s)
home.extractPage.desc=Extracts select pages from PDF
extractPage.tags=extract
home.extractPage.title=Extraer página(s)
home.extractPage.desc=Extraer las páginas seleccionadas del PDF
extractPage.tags=extraer
home.PdfToSinglePage.title=PDF to Single Large Page
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
PdfToSinglePage.tags=single page
home.PdfToSinglePage.title=PDF a una sola página
home.PdfToSinglePage.desc=Unir todas las páginas del PDF en una sola página
PdfToSinglePage.tags=página única
home.showJS.title=Show Javascript
home.showJS.desc=Searches and displays any JS injected into a PDF
home.showJS.title=Mostrar Javascript
home.showJS.desc=Busca y muestra cualquier JS contenido en un PDF
showJS.tags=JS
home.autoRedact.title=Auto Redact
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
home.autoRedact.title=Auto Redactar
home.autoRedact.desc=Redactar automáticamente (ocultar) texto en un PDF según el texto introducido
showJS.tags=JS
###########################
@@ -337,59 +337,59 @@ showJS.tags=JS
# #
###########################
#login
login.title=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
login.title=Iniciar sesión
login.signin=Iniciar sesión
login.rememberme=Recordarme
login.invalid=Nombre de usuario o contraseña erróneos.
login.locked=Su cuenta se ha bloqueado.
login.signinTitle=Por favor, inicie sesión
#auto-redact
autoRedact.title=Auto Redact
autoRedact.header=Auto Redact
autoRedact.colorLabel=Colour
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
autoRedact.useRegexLabel=Use Regex
autoRedact.wholeWordSearchLabel=Whole Word Search
autoRedact.customPaddingLabel=Custom Extra Padding
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
autoRedact.submitButton=Submit
autoRedact.title=Auto Redactar
autoRedact.header=Auto Redactar
autoRedact.colorLabel=Color
autoRedact.textsToRedactLabel=Texto para Redactar (separado por líneas)
autoRedact.textsToRedactPlaceholder=por ej. \nConfidencial \nAlto-Secreto
autoRedact.useRegexLabel=Usar Regex
autoRedact.wholeWordSearchLabel=Búsqueda por palabra completa
autoRedact.customPaddingLabel=Extra Padding personalizado
autoRedact.convertPDFToImageLabel=Convertir PDF a imagen-PDF (Utilizado para quitar el texto detrás del cajetín)
autoRedact.submitButton=Enviar
#showJS
showJS.title=Show Javascript
showJS.header=Show Javascript
showJS.downloadJS=Download Javascript
showJS.submit=Show
showJS.title=Mostrar Javascript
showJS.header=Mostrar Javascript
showJS.downloadJS=Descargar Javascript
showJS.submit=Mostrar
#pdfToSinglePage
pdfToSinglePage.title=PDF To Single Page
pdfToSinglePage.header=PDF To Single Page
pdfToSinglePage.submit=Convert To Single Page
pdfToSinglePage.title=PDF a página única
pdfToSinglePage.header=PDF a página única
pdfToSinglePage.submit=Convertir a página única
#pageExtracter
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
pageExtracter.title=Extraer Páginas
pageExtracter.header=Extraer Páginas
pageExtracter.submit=Extraer
#getPdfInfo
getPdfInfo.title=Get Info on PDF
getPdfInfo.header=Get Info on PDF
getPdfInfo.submit=Get Info
getPdfInfo.downloadJson=Download JSON
getPdfInfo.title=Obtener Información del PDF
getPdfInfo.header=Obtener Información del PDF
getPdfInfo.submit=Obtener Información
getPdfInfo.downloadJson=Descargar JSON
#markdown-to-pdf
MarkdownToPDF.title=Markdown To PDF
MarkdownToPDF.header=Markdown To PDF
MarkdownToPDF.submit=Convert
MarkdownToPDF.help=Work in progress
MarkdownToPDF.credit=Uses WeasyPrint
MarkdownToPDF.title=Markdown a PDF
MarkdownToPDF.header=Markdown a PDF
MarkdownToPDF.submit=Convertir
MarkdownToPDF.help=Tarea en proceso
MarkdownToPDF.credit=Usa WeasyPrint
@@ -428,9 +428,9 @@ addPageNumbers.selectText.3=Posición
addPageNumbers.selectText.4=Número de inicio
addPageNumbers.selectText.5=Páginas a numerar
addPageNumbers.selectText.6=Texto personalizado
addPageNumbers.customTextDesc=Custom Text
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
addPageNumbers.customTextDesc=Texto personalizado
addPageNumbers.numberPagesDesc=Qué páginas numerar, por defecto 'todas', también acepta 1-5 o 2,5,9 etc
addPageNumbers.customNumberDesc=Por defecto a {n}, también acepta 'Página {n} de {total}', 'Texto-{n}', '{nombre de archivo}-{n}
addPageNumbers.submit=Añadir Números de Página
@@ -616,8 +616,8 @@ addImage.submit=Añadir imagen
#merge
merge.title=Unir
merge.header=Unir múltiples PDFs (2+)
merge.sortByName=Sort by name
merge.sortByDate=Sort by date
merge.sortByName=Ordenar por nombre
merge.sortByDate=Ordenar por fecha
merge.submit=Unir
@@ -642,7 +642,7 @@ pageRemover.submit=Eliminar Páginas
#rotate
rotate.title=Rotar PDF
rotate.header=Rotar PDF
rotate.selectAngle=Select rotation angle (in multiples of 90 degrees):
rotate.selectAngle=Seleccionar ángulo de rotación (en múltiplos de 90 grados):
rotate.submit=Rotar
@@ -665,7 +665,13 @@ split.submit=Dividir
imageToPDF.title=Imagen a PDF
imageToPDF.header=Imagen a PDF
imageToPDF.submit=Convertir
imageToPDF.selectText.1=Estirar para ajustar
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Rotación automática del PDF
imageToPDF.selectText.3=Lógica de archivos múltiples (únicamente activado si funciona con multiples imágenes)
imageToPDF.selectText.4=Unir en un único archivo PDF
@@ -718,8 +724,8 @@ watermark.selectText.4=Rotación (0-360):
watermark.selectText.5=Ancho (Espacio entre cada marca de agua horizontalmente):
watermark.selectText.6=Alto (Espacio entre cada marca de agua verticalmente):
watermark.selectText.7=Opacidad (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.selectText.8=Tipo de marca de agua:
watermark.selectText.9=Imagen de marca de agua:
watermark.submit=Añadir marca de agua
@@ -762,7 +768,7 @@ changeMetadata.modDate=Fecha de modificación (aaaa/MM/dd HH:mm:ss):
changeMetadata.producer=Productor:
changeMetadata.subject=Asunto:
changeMetadata.title=Título:
changeMetadata.trapped=Trapped:
changeMetadata.trapped=Capturado:
changeMetadata.selectText.4=Otros Metadatos:
changeMetadata.selectText.5=Agregar entrada de metadatos personalizados
changeMetadata.submit=Cambiar

View File

@@ -665,7 +665,13 @@ split.submit=Zatitu
imageToPDF.title=Irudia PDF bihurtu
imageToPDF.header=Irudia PDF bihurtu
imageToPDF.submit=Bihurtu
imageToPDF.selectText.1=Zabaldu doitzeko
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=PDFaren errotazio automatikoa
imageToPDF.selectText.3=Fitxategi askoren logika (gaituta bakarrik zenbait irudirekin ari denean)
imageToPDF.selectText.4=Elkartu PDF bakar batean

View File

@@ -665,7 +665,13 @@ split.submit=Diviser
imageToPDF.title=Image en PDF
imageToPDF.header=Image en PDF
imageToPDF.submit=Convertir
imageToPDF.selectText.1=Étirer pour adapter
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Rotation automatique du PDF
imageToPDF.selectText.3=Logique multi-fichiers (uniquement activée si vous travaillez avec plusieurs images)
imageToPDF.selectText.4=Fusionner en un seul PDF
@@ -749,7 +755,7 @@ removePassword.submit=Supprimer
#changeMetadata
changeMetadata.title=Modifier les métadonnées
changeMetadata.title=Titre
changeMetadata.header=Modifier les métadonnées
changeMetadata.selectText.1=Veuillez modifier les variables que vous souhaitez modifier.
changeMetadata.selectText.2=Supprimer toutes les métadonnées

View File

@@ -665,7 +665,13 @@ split.submit=Dividi
imageToPDF.title=Immagine a PDF
imageToPDF.header=Immagine a PDF
imageToPDF.submit=Converti
imageToPDF.selectText.1=Allarga per riempire
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Ruota automaticamente PDF
imageToPDF.selectText.3=Logica multi-file (funziona solo se ci sono più immagini)
imageToPDF.selectText.4=Unisci in un unico PDF

View File

@@ -665,7 +665,13 @@ split.submit=分割
imageToPDF.title=画像をPDFに変換
imageToPDF.header=画像をPDFに変換
imageToPDF.submit=変換
imageToPDF.selectText.1=フィットするように引き伸ばす
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=PDFの自動回転
imageToPDF.selectText.3=マルチファイルの処理 (複数の画像を操作する場合に有効になります)
imageToPDF.selectText.4=1つのPDFに結合

View File

@@ -665,7 +665,13 @@ split.submit=분할
imageToPDF.title=이미지를 PDF로 변환
imageToPDF.header=이미지를 PDF로 변환
imageToPDF.submit=변환하기
imageToPDF.selectText.1=맞춤 크기로 늘리기
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=PDF 자동 회전
imageToPDF.selectText.3=다중 파일 로직 (여러 이미지로 작업하는 경우에만 활성화됨)
imageToPDF.selectText.4=단일 PDF로 병합

View File

@@ -665,7 +665,13 @@ split.submit=Splitsen
imageToPDF.title=Afbeelding naar PDF
imageToPDF.header=Afbeelding naar PDF
imageToPDF.submit=Omzetten
imageToPDF.selectText.1=Uitrekken om te passen
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=PDF automatisch draaien
imageToPDF.selectText.3=Meervoudige bestandslogica (Alleen ingeschakeld bij werken met meerdere afbeeldingen)
imageToPDF.selectText.4=Voeg samen in één PDF

View File

@@ -665,7 +665,13 @@ split.submit=Podziel
imageToPDF.title=Obraz na PDF
imageToPDF.header=Obraz na PDF
imageToPDF.submit=Konwertuj
imageToPDF.selectText.1=Rozciągnij, aby dopasować
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Automatyczne obracanie PDF
imageToPDF.selectText.3=Logika wielu plików (dostępna tylko w przypadku pracy z wieloma obrazami)
imageToPDF.selectText.4=Połącz w jeden dokument PDF

View File

@@ -665,7 +665,13 @@ split.submit=Dividir
imageToPDF.title=Imagem para PDF
imageToPDF.header=Converter Imagem para PDF
imageToPDF.submit=Converter
imageToPDF.selectText.1=Esticar para Ajustar
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Girar Automaticamente
imageToPDF.selectText.3=Lógica de Vários Arquivos (Ativada apenas ao trabalhar com várias imagens)
imageToPDF.selectText.4=Mesclar em um Único PDF

View File

@@ -665,7 +665,13 @@ split.submit=Împarte
imageToPDF.title=Imagine în PDF
imageToPDF.header=Imagine în PDF
imageToPDF.submit=Convertă
imageToPDF.selectText.1=Redimensionare pentru a se potrivi
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Rotire automată a PDF-ului
imageToPDF.selectText.3=Logica pentru mai multe fișiere (activată numai dacă se lucrează cu mai multe imagini)
imageToPDF.selectText.4=Unifică într-un singur PDF

View File

@@ -665,7 +665,13 @@ split.submit=Разделить
imageToPDF.title=Изображение в PDF
imageToPDF.header=Изображение в PDF
imageToPDF.submit=Конвертировать
imageToPDF.selectText.1=Растянуть, чтобы соответствовать
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Автоматический поворот PDF
imageToPDF.selectText.3=Многофайловая логика (включена только при работе с несколькими изображениями)
imageToPDF.selectText.4=Объединить в один PDF

View File

@@ -665,7 +665,13 @@ split.submit=Dela
imageToPDF.title=Bild till PDF
imageToPDF.header=Bild till PDF
imageToPDF.submit=Konvertera
imageToPDF.selectText.1=Sträck för att passa
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=Rotera PDF automatiskt
imageToPDF.selectText.3=Multifillogik (Endast aktiverad om man arbetar med flera bilder)
imageToPDF.selectText.4=Slå samman till en enda PDF

View File

@@ -665,7 +665,13 @@ split.submit=拆分
imageToPDF.title=图片转PDF
imageToPDF.header=图像转为PDF
imageToPDF.submit=转换
imageToPDF.selectText.1=拉伸至适合的尺寸
##########################
### TODO: Translate ###
##########################
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=自动旋转PDF
imageToPDF.selectText.3=多文件逻辑(仅在处理多个图像时启用)
imageToPDF.selectText.4=合并成一个PDF文件

View File

@@ -21,10 +21,16 @@
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='image/*', inputText=#{imgPrompt})}"></div>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="stretchToFit" id="stretchToFit">
<label class="ms-3" for="stretchToFit" th:text=#{imageToPDF.selectText.1}></label>
</div>
<div class="mb-3">
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>
<select class="form-control" id="fitOption" name="fitOption">
<option value="fillPage" th:text="#{imageToPDF.fillPage}">Fill Page</option>
<option value="fitDocumentToImage" th:text="#{imageToPDF.fitDocumentToImage}">Fit Document to Image</option>
<option value="maintainAspectRatio" th:text="#{imageToPDF.maintainAspectRatio}">Maintain Aspect Ratio</option>
</select>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="autoRotate" id="autoRotate">
<label class="ms-3" for="autoRotate" th:text=#{imageToPDF.selectText.2}></label>

View File

@@ -35,19 +35,19 @@
<div class="mb-3" id="p12Group" style="display: none;">
<label th:text="#{certSign.selectP12}"></label>
<div
th:replace="~{fragments/common :: fileSelector(name='p12', notRequired=true, multiple=false, accept='.p12,.pfx')}"></div>
th:replace="~{fragments/common :: fileSelector(name='p12File', notRequired=true, multiple=false, accept='.p12,.pfx')}"></div>
</div>
<div id="pemGroup" style="display: none;">
<div class="mb-3">
<label th:text="#{certSign.selectKey}"></label>
<div
th:replace="~{fragments/common :: fileSelector(name='key', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
th:replace="~{fragments/common :: fileSelector(name='privateKeyFile', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
</div>
<div class="mb-3">
<label th:text="#{certSign.selectCert}"></label>
<div
th:replace="~{fragments/common :: fileSelector(name='cert', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
th:replace="~{fragments/common :: fileSelector(name='certFile', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
</div>
</div>