From bdd8d2e6d49962285131b41091abacb3f7e59877 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20Sz=C3=BCcs?=
<127139797+balazs-szucs@users.noreply.github.com>
Date: Mon, 17 Nov 2025 15:38:28 +0100
Subject: [PATCH] feat(pdf-conversion): add support for PDF/A-3b, PDF/X formats
improve current PDF/A conversion (#4844)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Description of Changes
TLDR
- Updated `PdfToPdfARequest` to include PDF/X in supported output
formats
- Expanded input handling and model validation for PDF/A and PDF/X
- Added Ghostscript as a preferred backend for PDF/A and PDF/X
conversions
- Implemented PDF/X-specific conversion logic with detailed validation
- Updated UI templates to separate PDF/A and PDF/X format options
- Updated error handling and warnings during conversion processes
This PR replaces the PDF/A conversion system with Ghostscript as the
primary method, which less warning prone output compared to the previous
LibreOffice approach. It also adds PDF/X format support for print
production workflows.
### Better PDF/A Compliance
- Ghostscript produces standards-compliant PDF/A with fewer validation
errors
- Previous LibreOffice method generates files with structural errors and
validation warnings
- Automatic fallback to PDFBox/LibreOffice if Ghostscript unavailable
- Built-in validation using PDFBox Preflight catches issues early
### New PDF/X Support
Print production workflows now supported with PDF/X-1, PDF/X-3, and
PDF/X-4 formats for professional printing requirements.
### More Reliable Output
- Deterministic conversion results
- Better font embedding and subsetting
- Proper ICC profile and color space handling
- Improved resource cleanup prevents memory leaks
### Ghostscript Integration
- `buildGhostscriptCommand()` / `buildGhostscriptCommandX()` -
Constructs CLI arguments
- `convertWithGhostscript()` / `convertWithGhostscriptX()` - Executes
conversion
- `isGhostscriptAvailable()` - Checks installation
- `prepareColorProfiles()` - Sets up ICC profiles
- `createPdfaDefFile()` - Generates PostScript definitions
### Conversion Flow
- `handlePdfAConversion()` - Routes PDF/A with Ghostscript primary,
PDFBox fallback
- `handlePdfXConversion()` - Routes PDF/X using Ghostscript
- `convertWithPdfBoxMethod()` - Refactored fallback method
### Validation
- `validatePdfaOutput()` - Validates using PDFBox Preflight
- `validateAndWarnPdfA()` - Logs warnings instead of failing
- `buildPreflightErrorMessage()` - Formats detailed errors
### Font Handling
Updated `embedMissingFonts()` prevents stream exhaustion by loading font
bytes once and creating fresh InputStreams for multiple load attempts.
### Utilities
- `findUnembeddedFontNames()` - Identifies unembedded fonts
- `deleteQuietly()` - Recursively deletes temp directories
- `sanitizePdfA()` - Removes incompatible elements
- `removeElementsForPdfA()` - Removes Optional Content and transparency
- `mergeAndAddXmpMetadata()` - Handles XMP metadata
- `preProcessHighlights()` - Pre-processes annotations
- Transparency detection: `isTransparencyGroup()`,
`hasTransparentImages()`, `detectTransparentXObjects()`
### PDF/A
- PDF/A-1b: Strict compliance
- PDF/A-2b: Extended features (default)
- PDF/A-3b: Embedded files support
### PDF/X
- PDF/X-1: Standard print exchange
- PDF/X-3: Color-managed with ICC profiles
- PDF/X-4: Transparency support
As mentioned greatest benefit is the new Ghostscript conversion is able
to deliver fewer warning/zero error PDF/A files compared to the
LibreOffice. Sometimes however, both succeed without warnings. Here are
some samples:
There is also some size difference, (not sure why) but generally that
also favors Ghostscript:
### Front-end
---
## Checklist
### General
- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### Translations (if applicable)
- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)
### UI Changes (if applicable)
- [X] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
---------
Signed-off-by: Balázs Szücs
---
.../api/converters/ConvertPDFToPDFA.java | 1489 ++++++++++++++---
.../api/converters/PdfToPdfARequest.java | 7 +-
.../main/resources/messages_ar_AR.properties | 16 +-
.../main/resources/messages_az_AZ.properties | 16 +-
.../main/resources/messages_bg_BG.properties | 16 +-
.../main/resources/messages_bo_CN.properties | 16 +-
.../main/resources/messages_ca_CA.properties | 16 +-
.../main/resources/messages_cs_CZ.properties | 16 +-
.../main/resources/messages_da_DK.properties | 16 +-
.../main/resources/messages_de_DE.properties | 16 +-
.../main/resources/messages_el_GR.properties | 16 +-
.../main/resources/messages_en_GB.properties | 16 +-
.../main/resources/messages_en_US.properties | 16 +-
.../main/resources/messages_es_ES.properties | 16 +-
.../main/resources/messages_eu_ES.properties | 16 +-
.../main/resources/messages_fa_IR.properties | 16 +-
.../main/resources/messages_fr_FR.properties | 16 +-
.../main/resources/messages_ga_IE.properties | 16 +-
.../main/resources/messages_hi_IN.properties | 16 +-
.../main/resources/messages_hr_HR.properties | 16 +-
.../main/resources/messages_hu_HU.properties | 16 +-
.../main/resources/messages_id_ID.properties | 16 +-
.../main/resources/messages_it_IT.properties | 16 +-
.../main/resources/messages_ja_JP.properties | 16 +-
.../main/resources/messages_ko_KR.properties | 16 +-
.../main/resources/messages_ml_IN.properties | 16 +-
.../main/resources/messages_nl_NL.properties | 16 +-
.../main/resources/messages_no_NB.properties | 16 +-
.../main/resources/messages_pl_PL.properties | 16 +-
.../main/resources/messages_pt_BR.properties | 16 +-
.../main/resources/messages_pt_PT.properties | 16 +-
.../main/resources/messages_ro_RO.properties | 16 +-
.../main/resources/messages_ru_RU.properties | 16 +-
.../main/resources/messages_sk_SK.properties | 16 +-
.../main/resources/messages_sl_SI.properties | 16 +-
.../resources/messages_sr_LATN_RS.properties | 16 +-
.../main/resources/messages_sv_SE.properties | 16 +-
.../main/resources/messages_th_TH.properties | 16 +-
.../main/resources/messages_tr_TR.properties | 16 +-
.../main/resources/messages_uk_UA.properties | 16 +-
.../main/resources/messages_vi_VN.properties | 16 +-
.../main/resources/messages_zh_CN.properties | 16 +-
.../main/resources/messages_zh_TW.properties | 16 +-
.../templates/convert/pdf-to-pdfa.html | 12 +-
.../api/converters/ConvertPDFToPDFATest.java | 571 +++++++
45 files changed, 2203 insertions(+), 532 deletions(-)
create mode 100644 app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFATest.java
diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java
index 16e1a65e7d..bdc57a9844 100644
--- a/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java
+++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java
@@ -1,24 +1,18 @@
package stirling.software.SPDF.controller.api.converters;
import java.awt.Color;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.GregorianCalendar;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.Loader;
@@ -26,6 +20,8 @@ import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.io.RandomAccessRead;
+import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
import org.apache.pdfbox.pdfwriter.compress.CompressParameters;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
@@ -47,6 +43,14 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;
import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences;
+import org.apache.pdfbox.preflight.Format;
+import org.apache.pdfbox.preflight.PreflightConfiguration;
+import org.apache.pdfbox.preflight.PreflightDocument;
+import org.apache.pdfbox.preflight.ValidationResult;
+import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.preflight.exception.SyntaxValidationException;
+import org.apache.pdfbox.preflight.exception.ValidationException;
+import org.apache.pdfbox.preflight.parser.PreflightParser;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.AdobePDFSchema;
import org.apache.xmpbox.schema.DublinCoreSchema;
@@ -66,6 +70,7 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.converters.PdfToPdfARequest;
@@ -80,11 +85,389 @@ import stirling.software.common.util.WebResponseUtils;
@Tag(name = "Convert", description = "Convert APIs")
public class ConvertPDFToPDFA {
+ private static final String ICC_RESOURCE_PATH = "/icc/sRGB2014.icc";
+ private static final int PDFA_COMPATIBILITY_POLICY = 1;
+
+ private static void validateAndWarnPdfA(byte[] pdfBytes, PdfaProfile profile, String method) {
+ Path tempPdfPath = null;
+ try {
+ tempPdfPath = Files.createTempFile("validate_", ".pdf");
+
+ try (OutputStream out = Files.newOutputStream(tempPdfPath)) {
+ out.write(pdfBytes);
+ }
+
+ ValidationResult validationResult =
+ performComprehensivePdfAValidation(tempPdfPath, profile);
+
+ if (validationResult.isValid()) {
+ log.info(
+ "PDF/A validation passed for {} using {}",
+ profile.getDisplayName(),
+ method);
+ } else {
+ log.warn(
+ "PDF/A validation warning for {} using {}: {}",
+ profile.getDisplayName(),
+ method,
+ buildComprehensiveValidationMessage(validationResult, profile));
+ }
+ } catch (Exception e) {
+ log.warn(
+ "PDF/A validation warning for {} using {}: {}",
+ profile.getDisplayName(),
+ method,
+ e.getMessage());
+ } finally {
+ if (tempPdfPath != null) {
+ try {
+ Files.deleteIfExists(tempPdfPath);
+ } catch (IOException e) {
+ log.debug("Failed to delete temporary validation file", e);
+ }
+ }
+ }
+ }
+
+ private static ValidationResult performComprehensivePdfAValidation(
+ Path pdfPath, PdfaProfile profile) throws IOException {
+ Optional format = profile.preflightFormat();
+ if (format.isEmpty()) {
+ // For profiles without preflight support, perform basic structure validation
+ return performBasicPdfAValidation(pdfPath, profile);
+ }
+
+ try (RandomAccessRead rar = new RandomAccessReadBufferedFile(pdfPath.toFile())) {
+ PreflightParser parser = new PreflightParser(rar);
+
+ PreflightDocument document = parsePreflightDocument(parser, format.get(), profile);
+ if (document == null) {
+ throw new IOException(
+ "PDF/A preflight returned no document for " + profile.getDisplayName());
+ }
+
+ try (PreflightDocument closeableDocument = document) {
+ return closeableDocument.validate();
+ }
+ } catch (SyntaxValidationException e) {
+ return e.getResult();
+ } catch (ValidationException e) {
+ throw new IOException(
+ "PDF/A preflight validation failed for " + profile.getDisplayName(), e);
+ }
+ }
+
+ private static ValidationResult performBasicPdfAValidation(Path pdfPath, PdfaProfile profile)
+ throws IOException {
+ try (PDDocument doc = Loader.loadPDF(pdfPath.toFile())) {
+ ValidationResult result = new ValidationResult(true);
+
+ float version = doc.getVersion();
+ float expectedVersion = profile.getPart() == 1 ? 1.4f : 1.7f;
+ if (version < expectedVersion) {
+ result.addError(
+ new ValidationError(
+ "PDF_VERSION",
+ "PDF version "
+ + version
+ + " is below required "
+ + expectedVersion
+ + " for "
+ + profile.getDisplayName()));
+ }
+
+ PDDocumentCatalog catalog = doc.getDocumentCatalog();
+ if (catalog.getMetadata() == null) {
+ result.addError(
+ new ValidationError(
+ "MISSING_XMP",
+ "XMP metadata is required for " + profile.getDisplayName()));
+ }
+
+ if (catalog.getOutputIntents().isEmpty()) {
+ result.addError(
+ new ValidationError(
+ "MISSING_OUTPUT_INTENT",
+ "Output intent (ICC profile) is required for "
+ + profile.getDisplayName()));
+ }
+
+ return result;
+ }
+ }
+
+ private static String buildComprehensiveValidationMessage(
+ ValidationResult result, PdfaProfile profile) {
+ if (result == null) {
+ return "PDF/A validation failed for "
+ + profile.getDisplayName()
+ + ": no validation result available";
+ }
+
+ List errors = result.getErrorsList();
+
+ StringBuilder message = new StringBuilder();
+ message.append("PDF/A validation issues for ").append(profile.getDisplayName());
+
+ if (errors != null && !errors.isEmpty()) {
+ message.append(" - ").append(errors.size()).append(" errors");
+ }
+ message.append(":");
+
+ if (errors != null && !errors.isEmpty()) {
+ message.append(" ERRORS: ");
+ message.append(
+ errors.stream()
+ .limit(5)
+ .map(
+ error ->
+ (error.getErrorCode() != null
+ ? error.getErrorCode()
+ : "UNKNOWN")
+ + (error.getDetails() != null
+ ? ": " + error.getDetails()
+ : ""))
+ .collect(Collectors.joining("; ")));
+ }
+
+ return message.toString();
+ }
+
+ private static void deleteQuietly(Path directory) {
+ if (directory == null) {
+ return;
+ }
+ try (Stream stream = Files.walk(directory)) {
+ stream.sorted(Comparator.reverseOrder())
+ .forEach(
+ path -> {
+ try {
+ Files.deleteIfExists(path);
+ } catch (IOException e) {
+ log.warn("Failed to delete temporary file: {}", path, e);
+ }
+ });
+ } catch (IOException e) {
+ log.warn("Failed to clean temporary directory: {}", directory, e);
+ }
+ }
+
+ private static List buildGhostscriptCommand(
+ Path inputPdf,
+ Path outputPdf,
+ ColorProfiles colorProfiles,
+ Path workingDir,
+ PdfaProfile profile,
+ Path pdfaDefFile) {
+
+ List command = new ArrayList<>();
+ command.add("gs");
+ command.add("--permit-file-read=" + workingDir.toAbsolutePath());
+ command.add("--permit-file-read=" + colorProfiles.rgb().toAbsolutePath());
+ command.add("--permit-file-read=" + colorProfiles.gray().toAbsolutePath());
+ command.add("--permit-file-read=" + inputPdf.toAbsolutePath());
+ command.add("--permit-file-read=" + pdfaDefFile.toAbsolutePath());
+ command.add("--permit-file-write=" + workingDir.toAbsolutePath());
+
+ command.add("-dPDFA=" + profile.getPart());
+ command.add("-dPDFACompatibilityPolicy=" + PDFA_COMPATIBILITY_POLICY);
+ command.add("-dCompatibilityLevel=" + profile.getCompatibilityLevel());
+ command.add("-sDEVICE=pdfwrite");
+
+ command.add("-sColorConversionStrategy=RGB");
+ command.add("-dProcessColorModel=/DeviceRGB");
+ command.add("-sOutputICCProfile=" + colorProfiles.rgb().toAbsolutePath());
+ command.add("-sDefaultRGBProfile=" + colorProfiles.rgb().toAbsolutePath());
+ command.add("-sDefaultGrayProfile=" + colorProfiles.gray().toAbsolutePath());
+ command.add("-sDefaultCMYKProfile=" + colorProfiles.rgb().toAbsolutePath());
+
+ // Font handling optimized for PDF/A CIDSet compliance
+ command.add("-dEmbedAllFonts=true");
+ command.add(
+ "-dSubsetFonts=true"); // Enable subsetting to generate proper CIDSet streams for
+ // PDF/A-1
+ command.add("-dCompressFonts=true");
+ command.add("-dNOSUBSTFONTS=false"); // Allow font substitution for problematic fonts
+ command.add("-dNOPAUSE");
+ command.add("-dBATCH");
+ command.add("-dNOOUTERSAVE");
+ command.add("-sOutputFile=" + outputPdf.toAbsolutePath());
+
+ command.add(pdfaDefFile.toAbsolutePath().toString());
+ command.add(inputPdf.toAbsolutePath().toString());
+
+ return command;
+ }
+
+ private static PreflightDocument parsePreflightDocument(
+ PreflightParser parser, Format format, PdfaProfile profile) throws IOException {
+ try {
+ PreflightConfiguration config = PreflightConfiguration.createPdfA1BConfiguration();
+ if (profile.getPart() != 1) {
+ log.debug(
+ "Using PDF/A-1B configuration for PDF/A-{} validation", profile.getPart());
+ }
+
+ return (PreflightDocument) parser.parse(format, config);
+ } catch (SyntaxValidationException e) {
+ throw new IOException(buildComprehensiveValidationMessage(e.getResult(), profile), e);
+ } catch (ClassCastException e) {
+ throw new IOException(
+ "PDF/A preflight did not produce a PreflightDocument for "
+ + profile.getDisplayName(),
+ e);
+ }
+ }
+
+ private static void writeJavaIccProfile(ICC_Profile profile, Path target) throws IOException {
+ try (OutputStream out = Files.newOutputStream(target)) {
+ out.write(profile.getData());
+ }
+ }
+
+ private static Path createPdfaDefFile(
+ Path workingDir, ColorProfiles colorProfiles, PdfaProfile profile) throws IOException {
+ Path pdfaDefFile = workingDir.resolve("PDFA_def.ps");
+
+ String title = "Converted to " + profile.getDisplayName();
+ String rgbProfilePath = colorProfiles.rgb().toAbsolutePath().toString().replace("\\", "/");
+ String pdfaDefContent =
+ String.format(
+ """
+ %% This is a sample prefix file for creating a PDF/A document.
+ %% Feel free to modify entries marked with "Customize".
+
+ %% Define entries in the document Info dictionary.
+ [/Title (%s)
+ /DOCINFO pdfmark
+
+ %% Define an ICC profile.
+ [/_objdef {icc_PDFA} /type /stream /OBJ pdfmark
+ [{icc_PDFA} <<
+ /N 3
+ >> /PUT pdfmark
+ [{icc_PDFA} (%s) (r) file /PUT pdfmark
+
+ %% Define the output intent dictionary.
+ [/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark
+ [{OutputIntent_PDFA} <<
+ /Type /OutputIntent
+ /S /GTS_PDFA1
+ /DestOutputProfile {icc_PDFA}
+ /OutputConditionIdentifier (sRGB IEC61966-2.1)
+ /Info (sRGB IEC61966-2.1)
+ /RegistryName (http://www.color.org)
+ >> /PUT pdfmark
+ [{Catalog} <> /PUT pdfmark
+ """,
+ title, rgbProfilePath);
+
+ Files.writeString(pdfaDefFile, pdfaDefContent);
+ return pdfaDefFile;
+ }
+
+ private static List buildGhostscriptCommandX(
+ Path inputPdf,
+ Path outputPdf,
+ ColorProfiles colorProfiles,
+ Path workingDir,
+ PdfXProfile profile) {
+
+ List command = new ArrayList<>(25);
+ command.add("gs");
+ command.add("--permit-file-read=" + workingDir.toAbsolutePath());
+ command.add("--permit-file-read=" + colorProfiles.rgb().toAbsolutePath());
+ command.add("--permit-file-read=" + colorProfiles.gray().toAbsolutePath());
+ command.add("--permit-file-read=" + inputPdf.toAbsolutePath());
+ command.add("--permit-file-write=" + workingDir.toAbsolutePath());
+ command.add("-dPDFX=" + profile.getPdfxVersion());
+ command.add("-dCompatibilityLevel=" + profile.getCompatibilityLevel());
+ command.add("-sDEVICE=pdfwrite");
+ command.add("-sColorConversionStrategy=RGB");
+ command.add("-dProcessColorModel=/DeviceRGB");
+ command.add("-sOutputICCProfile=" + colorProfiles.rgb().toAbsolutePath());
+ command.add("-sDefaultRGBProfile=" + colorProfiles.rgb().toAbsolutePath());
+ command.add("-sDefaultGrayProfile=" + colorProfiles.gray().toAbsolutePath());
+ command.add("-dEmbedAllFonts=true");
+ command.add("-dSubsetFonts=false"); // Embed complete fonts to avoid incomplete glyphs
+ command.add("-dCompressFonts=true");
+ command.add("-dNOSUBSTFONTS=false"); // Allow font substitution for problematic fonts
+ command.add("-dPDFSETTINGS=/prepress");
+ command.add("-dNOPAUSE");
+ command.add("-dBATCH");
+ command.add("-dNOOUTERSAVE");
+ command.add("-sOutputFile=" + outputPdf.toAbsolutePath());
+ command.add(inputPdf.toAbsolutePath().toString());
+
+ return command;
+ }
+
+ private static void embedMissingFonts(
+ PDDocument loDoc, PDDocument baseDoc, Set missingFonts) throws IOException {
+ List loPages = new ArrayList<>(loDoc.getNumberOfPages());
+ loDoc.getPages().forEach(loPages::add);
+ List basePages = new ArrayList<>(baseDoc.getNumberOfPages());
+ baseDoc.getPages().forEach(basePages::add);
+
+ for (int i = 0; i < loPages.size(); i++) {
+ PDResources loRes = loPages.get(i).getResources();
+ PDResources baseRes = basePages.get(i).getResources();
+
+ for (COSName fontKey : loRes.getFontNames()) {
+ PDFont loFont = loRes.getFont(fontKey);
+ if (loFont == null) continue;
+
+ String psName = loFont.getName();
+ if (!missingFonts.contains(psName)) continue;
+
+ PDFontDescriptor desc = loFont.getFontDescriptor();
+ if (desc == null) continue;
+
+ PDStream fontStream = null;
+ if (desc.getFontFile() != null) {
+ fontStream = desc.getFontFile();
+ } else if (desc.getFontFile2() != null) {
+ fontStream = desc.getFontFile2();
+ } else if (desc.getFontFile3() != null) {
+ fontStream = desc.getFontFile3();
+ }
+ if (fontStream == null) continue;
+
+ // Read the font stream into memory once so we can create fresh
+ // InputStreams for multiple load attempts. This avoids reusing a
+ // consumed stream and allows try-with-resources for each attempt.
+ byte[] fontBytes;
+ try (InputStream in = fontStream.createInputStream()) {
+ fontBytes = in.readAllBytes();
+ }
+
+ PDFont embeddedFont = null;
+ // First try PDType0 (CID) font
+ try (InputStream tryIn = new ByteArrayInputStream(fontBytes)) {
+ embeddedFont = PDType0Font.load(baseDoc, tryIn, false);
+ } catch (IOException e1) {
+ // Fallback to TrueType
+ try (InputStream tryIn2 = new ByteArrayInputStream(fontBytes)) {
+ try {
+ embeddedFont = PDTrueTypeFont.load(baseDoc, tryIn2, null);
+ } catch (IllegalArgumentException | IOException e2) {
+ log.error("Could not embed font {}: {}", psName, e2.getMessage());
+ }
+ }
+ }
+
+ if (embeddedFont != null) {
+ baseRes.put(fontKey, embeddedFont);
+ }
+ }
+ }
+ }
+
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/pdfa")
@Operation(
- summary = "Convert a PDF to a PDF/A",
+ summary = "Convert a PDF to a PDF/A or PDF/X",
description =
- "This endpoint converts a PDF file to a PDF/A file using LibreOffice. PDF/A is a format designed for long-term archiving of digital documents. Input:PDF Output:PDF Type:SISO")
+ "This endpoint converts a PDF file to a PDF/A or PDF/X file using Ghostscript (preferred) or PDFBox/LibreOffice (fallback). PDF/A is a format designed for long-term archiving, while PDF/X is optimized for print production. Input:PDF Output:PDF Type:SISO")
public ResponseEntity pdfToPdfA(@ModelAttribute PdfToPdfARequest request)
throws Exception {
MultipartFile inputFile = request.getFileInput();
@@ -96,7 +479,34 @@ public class ConvertPDFToPDFA {
throw ExceptionUtils.createPdfFileRequiredException();
}
- // Get the original filename without extension
+ // Determine if this is PDF/A or PDF/X conversion
+ boolean isPdfX = outputFormat != null && outputFormat.toLowerCase().startsWith("pdfx");
+
+ if (isPdfX) {
+ return handlePdfXConversion(inputFile, outputFormat);
+ } else {
+ return handlePdfAConversion(inputFile, outputFormat);
+ }
+ }
+
+ private static Set findUnembeddedFontNames(PDDocument doc) throws IOException {
+ Set missing = new HashSet<>(16);
+ for (PDPage page : doc.getPages()) {
+ PDResources res = page.getResources();
+ for (COSName name : res.getFontNames()) {
+ PDFont font = res.getFont(name);
+ if (font != null && !font.isEmbedded()) {
+ missing.add(font.getName());
+ }
+ }
+ }
+ return missing;
+ }
+
+ private ResponseEntity handlePdfXConversion(
+ MultipartFile inputFile, String outputFormat) throws Exception {
+ PdfXProfile profile = PdfXProfile.fromRequest(outputFormat);
+
String originalFileName = Filenames.toSimpleFileName(inputFile.getOriginalFilename());
if (originalFileName == null || originalFileName.trim().isEmpty()) {
originalFileName = "output.pdf";
@@ -106,57 +516,147 @@ public class ConvertPDFToPDFA {
? originalFileName.substring(0, originalFileName.lastIndexOf('.'))
: originalFileName;
- Path tempInputFile = null;
- byte[] fileBytes;
- Path loPdfPath = null; // Used for LibreOffice conversion output
- File preProcessedFile = null;
- int pdfaPart = 2;
+ Path workingDir = Files.createTempDirectory("pdfx_conversion_");
+ Path inputPath = workingDir.resolve("input.pdf");
+ inputFile.transferTo(inputPath);
try {
- // Save uploaded file to temp location
- tempInputFile = Files.createTempFile("input_", ".pdf");
- inputFile.transferTo(tempInputFile);
-
- // Branch conversion based on desired output PDF/A format
- if ("pdfa".equals(outputFormat)) {
- preProcessedFile = tempInputFile.toFile();
- } else {
- pdfaPart = 1;
- preProcessedFile = preProcessHighlights(tempInputFile.toFile());
+ // PDF/X conversion uses Ghostscript (no fallback currently)
+ if (!isGhostscriptAvailable()) {
+ log.error("Ghostscript is required for PDF/X conversion");
+ throw new IOException(
+ "Ghostscript is required for PDF/X conversion but is not available on the system");
}
- Set missingFonts = new HashSet<>();
- boolean needImgs;
- try (PDDocument doc = Loader.loadPDF(preProcessedFile)) {
- missingFonts = findUnembeddedFontNames(doc);
- needImgs = (pdfaPart == 1) && hasTransparentImages(doc);
- if (!missingFonts.isEmpty() || needImgs) {
- // Run LibreOffice conversion to get flattened images and embedded fonts
- loPdfPath = runLibreOfficeConversion(preProcessedFile.toPath(), pdfaPart);
- }
- }
- fileBytes =
- convertToPdfA(
- preProcessedFile.toPath(), loPdfPath, pdfaPart, missingFonts, needImgs);
- String outputFilename = baseFileName + "_PDFA.pdf";
+ log.info("Using Ghostscript for PDF/X conversion to {}", profile.getDisplayName());
+ byte[] converted = convertWithGhostscriptX(inputPath, workingDir, profile);
+ String outputFilename = baseFileName + profile.outputSuffix();
+
+ log.info("PDF/X conversion completed successfully to {}", profile.getDisplayName());
return WebResponseUtils.bytesToWebResponse(
- fileBytes, outputFilename, MediaType.APPLICATION_PDF);
+ converted, outputFilename, MediaType.APPLICATION_PDF);
+ } catch (IOException | InterruptedException e) {
+ log.error("PDF/X conversion failed", e);
+ throw ExceptionUtils.createPdfaConversionFailedException();
} finally {
- // Clean up temporary files
- if (tempInputFile != null) {
- Files.deleteIfExists(tempInputFile);
- }
- if (loPdfPath != null && loPdfPath.getParent() != null) {
- FileUtils.deleteDirectory(loPdfPath.getParent().toFile());
- }
- if (preProcessedFile != null) {
- Files.deleteIfExists(preProcessedFile.toPath());
+ deleteQuietly(workingDir);
+ }
+ }
+
+ private boolean isGhostscriptAvailable() {
+ try {
+ ProcessExecutorResult result =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT)
+ .runCommandWithOutputHandling(Arrays.asList("gs", "--version"));
+ return result.getRc() == 0;
+ } catch (Exception e) {
+ log.debug("Ghostscript availability check failed", e);
+ return false;
+ }
+ }
+
+ private static void fixCidSetIssues(PDDocument document) throws IOException {
+ for (PDPage page : document.getPages()) {
+ PDResources resources = page.getResources();
+ if (resources == null) continue;
+
+ for (COSName fontName : resources.getFontNames()) {
+ try {
+ PDFont font = resources.getFont(fontName);
+ if (font == null) continue;
+
+ PDFontDescriptor descriptor = font.getFontDescriptor();
+ if (descriptor == null) continue;
+
+ COSDictionary fontDict = descriptor.getCOSObject();
+
+ // Remove invalid or incomplete CIDSet entries for PDF/A-1 compliance
+ // PDF/A-1 requires CIDSet to be present and complete for subsetted CIDFonts
+ // For PDF/A-2+, CIDSet is optional but must be complete if present
+ COSBase cidSet = fontDict.getDictionaryObject(COSName.getPDFName("CIDSet"));
+ if (cidSet != null) {
+ // If CIDSet exists but may be invalid, remove it to avoid validation errors
+ // This is safer than trying to fix incomplete CIDSet streams
+ fontDict.removeItem(COSName.getPDFName("CIDSet"));
+ log.debug(
+ "Removed potentially invalid CIDSet from font {}", font.getName());
+ }
+ } catch (Exception e) {
+ log.debug("Error processing CIDSet for font: {}", e.getMessage());
+ }
}
}
}
+ private static void importFlattenedImages(PDDocument loDoc, PDDocument baseDoc)
+ throws IOException {
+ List loPages = new ArrayList<>(loDoc.getNumberOfPages());
+ loDoc.getPages().forEach(loPages::add);
+ List basePages = new ArrayList<>(baseDoc.getNumberOfPages());
+ baseDoc.getPages().forEach(basePages::add);
+
+ for (int i = 0; i < loPages.size(); i++) {
+ PDPage loPage = loPages.get(i);
+ PDPage basePage = basePages.get(i);
+
+ PDResources loRes = loPage.getResources();
+ PDResources baseRes = basePage.getResources();
+ if (loRes == null || baseRes == null) continue;
+
+ Set toReplace = detectTransparentXObjects(basePage);
+
+ for (COSName name : toReplace) {
+ PDXObject loXo = loRes.getXObject(name);
+ if (!(loXo instanceof PDImageXObject img)) continue;
+
+ PDImageXObject newImg = LosslessFactory.createFromImage(baseDoc, img.getImage());
+
+ // replace the resource under the same name
+ baseRes.put(name, newImg);
+ }
+ }
+ }
+
+ private ColorProfiles prepareColorProfiles(Path workingDir) throws IOException {
+ Path rgbProfile = workingDir.resolve("sRGB.icc");
+ copyResourceIcc(rgbProfile);
+
+ Path grayProfile = workingDir.resolve("Gray.icc");
+ try {
+ writeJavaIccProfile(ICC_Profile.getInstance(ColorSpace.CS_GRAY), grayProfile);
+ } catch (IllegalArgumentException e) {
+ log.warn("Falling back to sRGB ICC profile for grayscale defaults", e);
+ Files.copy(rgbProfile, grayProfile, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ return new ColorProfiles(rgbProfile, grayProfile);
+ }
+
+ private static Set detectTransparentXObjects(PDPage page) {
+ Set transparentObjects = new HashSet<>();
+ PDResources res = page.getResources();
+ if (res == null) return transparentObjects;
+
+ for (COSName name : res.getXObjectNames()) {
+ try {
+ PDXObject xo = res.getXObject(name);
+ if (xo instanceof PDImageXObject img) {
+ COSDictionary d = img.getCOSObject();
+ if (d.containsKey(COSName.SMASK)
+ || isTransparencyGroup(d)
+ || d.getBoolean(COSName.INTERPOLATE, false)) {
+ transparentObjects.add(name);
+ }
+ }
+ } catch (IOException ioe) {
+ log.error("Error processing XObject {}: {}", name.getName(), ioe.getMessage());
+ }
+ }
+ return transparentObjects;
+ }
+
/**
* Merge fonts & flattened images from loPdfPath into basePdfPath, then run the standard
* PDFBox/A pipeline.
@@ -189,28 +689,346 @@ public class ConvertPDFToPDFA {
}
}
- private byte[] processWithPDFBox(PDDocument document, int pdfaPart) throws Exception {
+ private byte[] convertWithGhostscript(Path inputPdf, Path workingDir, PdfaProfile profile)
+ throws IOException, InterruptedException {
+ Path outputPdf = workingDir.resolve("gs_output.pdf");
+ ColorProfiles colorProfiles = prepareColorProfiles(workingDir);
+ Path pdfaDefFile = createPdfaDefFile(workingDir, colorProfiles, profile);
+ // Preprocess PDF for PDF/A compliance
+ Path preprocessedPdf = inputPdf;
+
+ // For PDF/A-1, clean CIDSet issues that may cause validation failures
+ if (profile.getPart() == 1) {
+ Path cidSetCleaned = cleanCidSetWithQpdf(inputPdf);
+ if (cidSetCleaned != null) {
+ preprocessedPdf = cidSetCleaned;
+ }
+ }
+
+ // Normalize PDF with qpdf before Ghostscript conversion to ensure proper font program
+ // handling
+ Path normalizedInputPdf = normalizePdfWithQpdf(preprocessedPdf);
+ Path inputForGs = (normalizedInputPdf != null) ? normalizedInputPdf : preprocessedPdf;
+
+ try {
+ List command =
+ buildGhostscriptCommand(
+ inputForGs, outputPdf, colorProfiles, workingDir, profile, pdfaDefFile);
+
+ ProcessExecutorResult result =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT)
+ .runCommandWithOutputHandling(command);
+
+ if (result.getRc() != 0) {
+ throw new IOException("Ghostscript exited with code " + result.getRc());
+ }
+
+ if (!Files.exists(outputPdf)) {
+ throw new IOException("Ghostscript did not produce an output file");
+ }
+
+ return Files.readAllBytes(outputPdf);
+ } finally {
+ // Clean up temporary files
+ if (normalizedInputPdf != null && !normalizedInputPdf.equals(preprocessedPdf)) {
+ try {
+ Files.deleteIfExists(normalizedInputPdf);
+ } catch (IOException e) {
+ log.debug("Failed to delete temporary normalized file", e);
+ }
+ }
+ if (preprocessedPdf != null && !preprocessedPdf.equals(inputPdf)) {
+ try {
+ Files.deleteIfExists(preprocessedPdf);
+ } catch (IOException e) {
+ log.debug("Failed to delete temporary CIDSet cleaned file", e);
+ }
+ }
+ }
+ }
+
+ private static void fixType1FontCharSet(PDDocument document) throws IOException {
+ for (PDPage page : document.getPages()) {
+ PDResources resources = page.getResources();
+ if (resources == null) continue;
+
+ for (COSName fontName : resources.getFontNames()) {
+ try {
+ PDFont font = resources.getFont(fontName);
+ if (font == null) continue;
+
+ String fontNameStr = font.getName();
+ if (fontNameStr == null) continue;
+
+ PDFontDescriptor descriptor = font.getFontDescriptor();
+ if (descriptor == null) continue;
+
+ // Check if this is a Type1 font
+ if (fontNameStr.contains("Type1")
+ || descriptor.getFontFile() != null
+ || (descriptor.getFontFile2() == null
+ && descriptor.getFontFile3() == null)) {
+
+ // Check if CharSet is missing or suspicious
+ String existingCharSet =
+ descriptor.getCOSObject().getString(COSName.CHAR_SET);
+ if (existingCharSet == null || existingCharSet.trim().isEmpty()) {
+
+ // Build a CharSet from commonly used glyphs
+ // For Type1 fonts, include standard PDF glyphs
+ String glyphSet = buildStandardType1GlyphSet();
+ if (!glyphSet.isEmpty()) {
+ descriptor.getCOSObject().setString(COSName.CHAR_SET, glyphSet);
+ log.debug(
+ "Fixed CharSet for Type1 font {} with {} glyphs",
+ fontNameStr,
+ glyphSet.split(" ").length);
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.warn(
+ "Error processing font descriptor for page resource: {}",
+ e.getMessage());
+ }
+ }
+ }
+ }
+
+ private static String buildStandardType1GlyphSet() {
+ Set glyphNames = new LinkedHashSet<>();
+
+ String[] standardGlyphs = {
+ ".notdef",
+ ".null",
+ "nonmarkingreturn",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "exclamdown",
+ "cent",
+ "sterling",
+ "currency",
+ "yen",
+ "brokenbar",
+ "section",
+ "dieresis",
+ "copyright",
+ "ordfeminine",
+ "guillemotleft",
+ "logicalnot",
+ "uni00AD",
+ "registered",
+ "macron",
+ "degree",
+ "plusminus",
+ "twosuperior",
+ "threesuperior",
+ "acute",
+ "mu",
+ "paragraph",
+ "periodcentered",
+ "cedilla",
+ "onesuperior",
+ "ordmasculine",
+ "guillemotright",
+ "onequarter",
+ "onehalf",
+ "threequarters",
+ "questiondown",
+ "Agrave",
+ "Aacute",
+ "Acircumflex",
+ "Atilde",
+ "Adieresis",
+ "Aring",
+ "AE",
+ "Ccedilla",
+ "Egrave",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Igrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Eth",
+ "Ntilde",
+ "Ograve",
+ "Oacute",
+ "Ocircumflex",
+ "Otilde",
+ "Odieresis",
+ "multiply",
+ "Oslash",
+ "Ugrave",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Yacute",
+ "Thorn",
+ "germandbls",
+ "agrave",
+ "aacute",
+ "acircumflex",
+ "atilde",
+ "adieresis",
+ "aring",
+ "ae",
+ "ccedilla",
+ "egrave",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "igrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "eth",
+ "ntilde",
+ "ograve",
+ "oacute",
+ "ocircumflex",
+ "otilde",
+ "odieresis",
+ "divide",
+ "oslash",
+ "ugrave",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "yacute",
+ "thorn",
+ "ydieresis"
+ };
+
+ Collections.addAll(glyphNames, standardGlyphs);
+
+ return String.join(" ", glyphNames);
+ }
+
+ private byte[] processWithPDFBox(PDDocument document, int pdfaPart) throws Exception {
removeElementsForPdfA(document, pdfaPart);
+ document.getDocument().setVersion(pdfaPart == 1 ? 1.4f : 1.7f);
+
mergeAndAddXmpMetadata(document, pdfaPart);
addICCProfileIfNotPresent(document);
- // Mark the document as PDF/A
+ // Fix CIDSet issues for PDF/A compliance
+ if (pdfaPart == 1) {
+ fixCidSetIssues(document);
+ }
+
+ fixType1FontCharSet(document);
+
PDDocumentCatalog catalog = document.getDocumentCatalog();
- catalog.setMetadata(
- document.getDocumentCatalog().getMetadata()); // Ensure metadata is linked
- catalog.setViewerPreferences(
- new PDViewerPreferences(catalog.getCOSObject())); // PDF/A best practice
- document.getDocument().setVersion(pdfaPart == 1 ? 1.4f : 1.7f);
+ catalog.setMetadata(document.getDocumentCatalog().getMetadata());
+
+ PDViewerPreferences viewerPrefs = new PDViewerPreferences(catalog.getCOSObject());
+ viewerPrefs.setDisplayDocTitle(true);
+ catalog.setViewerPreferences(viewerPrefs);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- if (pdfaPart == 1) {
- document.save(baos, CompressParameters.NO_COMPRESSION);
- } else {
- document.save(baos);
- }
+ CompressParameters compressParams =
+ pdfaPart == 1 ? CompressParameters.NO_COMPRESSION : new CompressParameters();
+
+ document.save(baos, compressParams);
+ log.debug("PDF/A-{} document processed with PDFBox", pdfaPart);
return baos.toByteArray();
}
@@ -255,127 +1073,36 @@ public class ConvertPDFToPDFA {
return outputFiles[0].toPath();
}
- private void embedMissingFonts(PDDocument loDoc, PDDocument baseDoc, Set missingFonts)
- throws IOException {
- List loPages = new ArrayList<>();
- loDoc.getPages().forEach(loPages::add);
- List basePages = new ArrayList<>();
- baseDoc.getPages().forEach(basePages::add);
+ private byte[] convertWithGhostscriptX(Path inputPdf, Path workingDir, PdfXProfile profile)
+ throws IOException, InterruptedException {
+ Path outputPdf = workingDir.resolve("gs_output_pdfx.pdf");
+ ColorProfiles colorProfiles = prepareColorProfiles(workingDir);
- for (int i = 0; i < loPages.size(); i++) {
- PDResources loRes = loPages.get(i).getResources();
- PDResources baseRes = basePages.get(i).getResources();
+ List command =
+ buildGhostscriptCommandX(inputPdf, outputPdf, colorProfiles, workingDir, profile);
- for (COSName fontKey : loRes.getFontNames()) {
- PDFont loFont = loRes.getFont(fontKey);
- if (loFont == null) continue;
+ ProcessExecutorResult result =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT)
+ .runCommandWithOutputHandling(command);
- String psName = loFont.getName();
- if (!missingFonts.contains(psName)) continue;
-
- PDFontDescriptor desc = loFont.getFontDescriptor();
- if (desc == null) continue;
-
- PDStream fontStream = null;
- if (desc.getFontFile() != null) {
- fontStream = desc.getFontFile();
- } else if (desc.getFontFile2() != null) {
- fontStream = desc.getFontFile2();
- } else if (desc.getFontFile3() != null) {
- fontStream = desc.getFontFile3();
- }
- if (fontStream == null) continue;
-
- try (InputStream in = fontStream.createInputStream()) {
- PDFont newFont;
- try {
- newFont = PDType0Font.load(baseDoc, in, false);
- } catch (IOException e1) {
- try {
- newFont = PDTrueTypeFont.load(baseDoc, in, null);
- } catch (IOException | IllegalArgumentException e2) {
- log.error("Could not embed font {}: {}", psName, e2.getMessage());
- continue;
- }
- }
- if (newFont != null) {
- baseRes.put(fontKey, newFont);
- }
- }
- }
+ if (result.getRc() != 0) {
+ throw new IOException("Ghostscript exited with code " + result.getRc());
}
+
+ if (!Files.exists(outputPdf)) {
+ throw new IOException("Ghostscript did not produce an output file");
+ }
+
+ return Files.readAllBytes(outputPdf);
}
- private Set findUnembeddedFontNames(PDDocument doc) throws IOException {
- Set missing = new HashSet<>();
- for (PDPage page : doc.getPages()) {
- PDResources res = page.getResources();
- for (COSName name : res.getFontNames()) {
- PDFont font = res.getFont(name);
- if (font != null && !font.isEmbedded()) {
- missing.add(font.getName());
- }
- }
- }
- return missing;
- }
-
- private void importFlattenedImages(PDDocument loDoc, PDDocument baseDoc) throws IOException {
- List loPages = new ArrayList<>();
- loDoc.getPages().forEach(loPages::add);
- List basePages = new ArrayList<>();
- baseDoc.getPages().forEach(basePages::add);
-
- for (int i = 0; i < loPages.size(); i++) {
- PDPage loPage = loPages.get(i);
- PDPage basePage = basePages.get(i);
-
- PDResources loRes = loPage.getResources();
- PDResources baseRes = basePage.getResources();
- Set toReplace = detectTransparentXObjects(basePage);
-
- for (COSName name : toReplace) {
- PDXObject loXo = loRes.getXObject(name);
- if (!(loXo instanceof PDImageXObject img)) continue;
-
- PDImageXObject newImg = LosslessFactory.createFromImage(baseDoc, img.getImage());
-
- // replace the resource under the same name
- baseRes.put(name, newImg);
- }
- }
- }
-
- private Set detectTransparentXObjects(PDPage page) {
- Set transparentObjects = new HashSet<>();
- PDResources res = page.getResources();
- if (res == null) return transparentObjects;
-
- for (COSName name : res.getXObjectNames()) {
- try {
- PDXObject xo = res.getXObject(name);
- if (xo instanceof PDImageXObject img) {
- COSDictionary d = img.getCOSObject();
- if (d.containsKey(COSName.SMASK)
- || isTransparencyGroup(d)
- || d.getBoolean(COSName.INTERPOLATE, false)) {
- transparentObjects.add(name);
- }
- }
- } catch (IOException ioe) {
- log.error("Error processing XObject {}: {}", name.getName(), ioe.getMessage());
- }
- }
- return transparentObjects;
- }
-
- private boolean isTransparencyGroup(COSDictionary dict) {
+ private static boolean isTransparencyGroup(COSDictionary dict) {
COSBase g = dict.getDictionaryObject(COSName.GROUP);
return g instanceof COSDictionary gd
&& COSName.TRANSPARENCY.equals(gd.getCOSName(COSName.S));
}
- private boolean hasTransparentImages(PDDocument doc) {
+ private static boolean hasTransparentImages(PDDocument doc) {
for (PDPage page : doc.getPages()) {
PDResources res = page.getResources();
if (res == null) continue;
@@ -400,10 +1127,9 @@ public class ConvertPDFToPDFA {
return false;
}
- private void sanitizePdfA(COSBase base, PDResources resources, int pdfaPart) {
+ private static void sanitizePdfA(COSBase base, int pdfaPart) {
if (base instanceof COSDictionary dict) {
if (pdfaPart == 1) {
- // Remove transparency-related elements
COSBase group = dict.getDictionaryObject(COSName.GROUP);
if (group instanceof COSDictionary gDict
&& COSName.TRANSPARENCY.equals(gDict.getCOSName(COSName.S))) {
@@ -411,18 +1137,15 @@ public class ConvertPDFToPDFA {
}
dict.removeItem(COSName.SMASK);
- // Transparency blending constants (/CA, /ca) — disallowed in PDF/A-1
dict.removeItem(COSName.CA);
dict.removeItem(COSName.getPDFName("ca"));
}
- // Interpolation (non-deterministic image scaling) — required to be false
if (dict.containsKey(COSName.INTERPOLATE)
&& dict.getBoolean(COSName.INTERPOLATE, true)) {
dict.setBoolean(COSName.INTERPOLATE, false);
}
- // Remove common forbidden features (for PDF/A 1 and 2)
dict.removeItem(COSName.JAVA_SCRIPT);
dict.removeItem(COSName.getPDFName("JS"));
dict.removeItem(COSName.getPDFName("RichMedia"));
@@ -434,23 +1157,20 @@ public class ConvertPDFToPDFA {
dict.removeItem(COSName.EMBEDDED_FILES);
dict.removeItem(COSName.FILESPEC);
- // Recurse through all entries in the dictionary
for (Map.Entry entry : dict.entrySet()) {
- sanitizePdfA(entry.getValue(), resources, pdfaPart);
+ sanitizePdfA(entry.getValue(), pdfaPart);
}
} else if (base instanceof COSArray arr) {
- // Recursively sanitize each item in the array
for (COSBase item : arr) {
- sanitizePdfA(item, resources, pdfaPart);
+ sanitizePdfA(item, pdfaPart);
}
}
}
- private void removeElementsForPdfA(PDDocument doc, int pdfaPart) {
+ private static void removeElementsForPdfA(PDDocument doc, int pdfaPart) {
if (pdfaPart == 1) {
- // Remove Optional Content (Layers) - not allowed in PDF/A-1
doc.getDocumentCatalog().getCOSObject().removeItem(COSName.getPDFName("OCProperties"));
}
@@ -459,18 +1179,16 @@ public class ConvertPDFToPDFA {
page.setAnnotations(Collections.emptyList());
}
PDResources res = page.getResources();
- // Clean page-level dictionary
- sanitizePdfA(page.getCOSObject(), res, pdfaPart);
+ sanitizePdfA(page.getCOSObject(), pdfaPart);
- // sanitize each Form XObject
if (res != null) {
for (COSName name : res.getXObjectNames()) {
try {
PDXObject xo = res.getXObject(name);
if (xo instanceof PDFormXObject form) {
- sanitizePdfA(form.getCOSObject(), res, pdfaPart);
+ sanitizePdfA(form.getCOSObject(), pdfaPart);
} else if (xo instanceof PDImageXObject img) {
- sanitizePdfA(img.getCOSObject(), res, pdfaPart);
+ sanitizePdfA(img.getCOSObject(), pdfaPart);
}
} catch (IOException ioe) {
log.error("Cannot load XObject {}: {}", name.getName(), ioe.getMessage());
@@ -481,11 +1199,10 @@ public class ConvertPDFToPDFA {
}
/** Embbeds the XMP metadata required for PDF/A compliance. */
- private void mergeAndAddXmpMetadata(PDDocument document, int pdfaPart) throws Exception {
+ private static void mergeAndAddXmpMetadata(PDDocument document, int pdfaPart) throws Exception {
PDMetadata existingMetadata = document.getDocumentCatalog().getMetadata();
XMPMetadata xmp;
- // Load existing XMP if available
if (existingMetadata != null) {
try (InputStream xmpStream = existingMetadata.createInputStream()) {
DomXmpParser parser = new DomXmpParser();
@@ -506,7 +1223,6 @@ public class ConvertPDFToPDFA {
String originalCreator = Optional.ofNullable(docInfo.getCreator()).orElse("Unknown");
String originalProducer = Optional.ofNullable(docInfo.getProducer()).orElse("Unknown");
- // Only keep the original creator so it can match xmp creator tool for compliance
DublinCoreSchema dcSchema = xmp.getDublinCoreSchema();
if (dcSchema != null) {
List existingCreators = dcSchema.getCreators();
@@ -547,7 +1263,6 @@ public class ConvertPDFToPDFA {
String originalAuthor = docInfo.getAuthor();
if (originalAuthor != null && !originalAuthor.isBlank()) {
docInfo.setAuthor(null);
- // If the author is set, we keep it in the XMP metadata
if (!originalCreator.equals(originalAuthor)) {
dcSchema.addCreator(originalAuthor);
}
@@ -566,33 +1281,28 @@ public class ConvertPDFToPDFA {
adobePdfSchema.setKeywords(keywords);
}
- // Set creation and modification dates using java.time and convert to GregorianCalendar
Instant nowInstant = Instant.now();
ZonedDateTime nowZdt = ZonedDateTime.ofInstant(nowInstant, ZoneId.of("UTC"));
- GregorianCalendar nowCal = GregorianCalendar.from(nowZdt);
- java.util.Calendar originalCreationDate = docInfo.getCreationDate();
- GregorianCalendar creationCal;
- if (originalCreationDate == null) {
- creationCal = nowCal;
- } else if (originalCreationDate instanceof GregorianCalendar) {
- creationCal = (GregorianCalendar) originalCreationDate;
+ Instant creationInstant;
+ Calendar originalCreationDate = docInfo.getCreationDate();
+ if (originalCreationDate != null) {
+ creationInstant = originalCreationDate.toInstant();
} else {
- // convert other Calendar implementations to GregorianCalendar preserving instant
- creationCal =
- GregorianCalendar.from(
- ZonedDateTime.ofInstant(
- originalCreationDate.toInstant(), ZoneId.of("UTC")));
+ creationInstant = nowInstant;
}
+ ZonedDateTime creationZdt = ZonedDateTime.ofInstant(creationInstant, ZoneId.of("UTC"));
+
+ GregorianCalendar creationCal = GregorianCalendar.from(creationZdt);
+ GregorianCalendar modificationCal = GregorianCalendar.from(nowZdt);
docInfo.setCreationDate(creationCal);
xmpBasicSchema.setCreateDate(creationCal);
- docInfo.setModificationDate(nowCal);
- xmpBasicSchema.setModifyDate(nowCal);
- xmpBasicSchema.setMetadataDate(nowCal);
+ docInfo.setModificationDate(modificationCal);
+ xmpBasicSchema.setModifyDate(modificationCal);
+ xmpBasicSchema.setMetadataDate(modificationCal);
- // Serialize the created metadata so it can be attached to the existent metadata
ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();
new XmpSerializer().serialize(xmp, xmpOut, true);
@@ -601,33 +1311,15 @@ public class ConvertPDFToPDFA {
document.getDocumentCatalog().setMetadata(newMetadata);
}
- private void addICCProfileIfNotPresent(PDDocument document) throws Exception {
- if (document.getDocumentCatalog().getOutputIntents().isEmpty()) {
- try (InputStream colorProfile = getClass().getResourceAsStream("/icc/sRGB2014.icc")) {
- PDOutputIntent outputIntent = new PDOutputIntent(document, colorProfile);
- outputIntent.setInfo("sRGB IEC61966-2.1");
- outputIntent.setOutputCondition("sRGB IEC61966-2.1");
- outputIntent.setOutputConditionIdentifier("sRGB IEC61966-2.1");
- outputIntent.setRegistryName("http://www.color.org");
- document.getDocumentCatalog().addOutputIntent(outputIntent);
- } catch (Exception e) {
- log.error("Failed to load ICC profile: {}", e.getMessage());
- }
- }
- }
-
- private File preProcessHighlights(File inputPdf) throws Exception {
+ private static File preProcessHighlights(File inputPdf) throws Exception {
try (PDDocument document = Loader.loadPDF(inputPdf)) {
for (PDPage page : document.getPages()) {
- // Retrieve the annotations on the page.
List annotations = page.getAnnotations();
for (PDAnnotation annot : annotations) {
- // Process only highlight annotations.
if ("Highlight".equals(annot.getSubtype())
&& annot instanceof PDAnnotationTextMarkup highlight) {
- // Create a new appearance stream with the same bounding box.
float[] colorComponents =
highlight.getColor() != null
? highlight.getColor().getComponents()
@@ -649,8 +1341,6 @@ public class ConvertPDFToPDFA {
cs.setStrokingColor(highlightColor);
cs.setLineWidth(0.05f);
float spacing = 2f;
- // Draw diagonal lines across the highlight area to simulate
- // transparency.
for (int i = 0; i < quadPoints.length; i += 8) {
float minX =
Math.min(
@@ -695,12 +1385,12 @@ public class ConvertPDFToPDFA {
COSDictionary groupDict =
(COSDictionary) pageDict.getDictionaryObject(COSName.GROUP);
- if (groupDict != null) {
- if (COSName.TRANSPARENCY
- .getName()
- .equalsIgnoreCase(groupDict.getNameAsString(COSName.S))) {
- pageDict.removeItem(COSName.GROUP);
- }
+ if (groupDict != null
+ && COSName.TRANSPARENCY
+ .getName()
+ .equalsIgnoreCase(
+ groupDict.getNameAsString(COSName.S))) {
+ pageDict.removeItem(COSName.GROUP);
}
}
}
@@ -712,4 +1402,321 @@ public class ConvertPDFToPDFA {
return preProcessedFile;
}
}
+
+ private ResponseEntity handlePdfAConversion(
+ MultipartFile inputFile, String outputFormat) throws Exception {
+ PdfaProfile profile = PdfaProfile.fromRequest(outputFormat);
+
+ // Get the original filename without extension
+ String originalFileName = Filenames.toSimpleFileName(inputFile.getOriginalFilename());
+ if (originalFileName == null || originalFileName.trim().isEmpty()) {
+ originalFileName = "output.pdf";
+ }
+ String baseFileName =
+ originalFileName.contains(".")
+ ? originalFileName.substring(0, originalFileName.lastIndexOf('.'))
+ : originalFileName;
+
+ Path workingDir = Files.createTempDirectory("pdfa_conversion_");
+ Path inputPath = workingDir.resolve("input.pdf");
+ inputFile.transferTo(inputPath);
+
+ try {
+ byte[] converted;
+
+ // Try Ghostscript first (preferred method)
+ if (isGhostscriptAvailable()) {
+ log.info("Using Ghostscript for PDF/A conversion to {}", profile.getDisplayName());
+ try {
+ converted = convertWithGhostscript(inputPath, workingDir, profile);
+ String outputFilename = baseFileName + profile.outputSuffix();
+
+ validateAndWarnPdfA(converted, profile, "Ghostscript");
+
+ return WebResponseUtils.bytesToWebResponse(
+ converted, outputFilename, MediaType.APPLICATION_PDF);
+ } catch (Exception e) {
+ log.warn(
+ "Ghostscript conversion failed, falling back to PDFBox/LibreOffice method",
+ e);
+ }
+ } else {
+ log.info("Ghostscript not available, using PDFBox/LibreOffice fallback method");
+ }
+
+ converted = convertWithPdfBoxMethod(inputPath, profile);
+ String outputFilename = baseFileName + profile.outputSuffix();
+
+ // Validate with PDFBox preflight and warn if issues found
+ validateAndWarnPdfA(converted, profile, "PDFBox/LibreOffice");
+
+ return WebResponseUtils.bytesToWebResponse(
+ converted, outputFilename, MediaType.APPLICATION_PDF);
+
+ } finally {
+ deleteQuietly(workingDir);
+ }
+ }
+
+ private Path normalizePdfWithQpdf(Path inputPdf) {
+ try {
+ ProcessExecutorResult checkResult =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
+ .runCommandWithOutputHandling(Arrays.asList("qpdf", "--version"));
+
+ if (checkResult.getRc() != 0) {
+ log.debug("QPDF not available");
+ return null;
+ }
+
+ Path normalizedPdf =
+ inputPdf.getParent().resolve("normalized_" + inputPdf.getFileName().toString());
+
+ List command =
+ Arrays.asList(
+ "qpdf",
+ "--normalize-content=y",
+ "--object-streams=preserve",
+ inputPdf.toAbsolutePath().toString(),
+ normalizedPdf.toAbsolutePath().toString());
+
+ ProcessExecutorResult result =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
+ .runCommandWithOutputHandling(command);
+
+ if (result.getRc() == 0 && Files.exists(normalizedPdf)) {
+ log.info("PDF normalized with QPDF to fix font programs and CIDSet issues");
+ return normalizedPdf;
+ }
+ return null;
+
+ } catch (Exception e) {
+ log.debug("QPDF normalization error: {}", e.getMessage());
+ return null;
+ }
+ }
+
+ private Path cleanCidSetWithQpdf(Path inputPdf) {
+ try {
+ ProcessExecutorResult checkResult =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
+ .runCommandWithOutputHandling(Arrays.asList("qpdf", "--version"));
+
+ if (checkResult.getRc() != 0) {
+ log.debug("QPDF not available for CIDSet cleaning");
+ return null;
+ }
+
+ Path cleanedPdf =
+ inputPdf.getParent()
+ .resolve("cidset_cleaned_" + inputPdf.getFileName().toString());
+
+ // Use QPDF to remove problematic CIDSet entries that may be incomplete
+ List command =
+ Arrays.asList(
+ "qpdf",
+ "--remove-unreferenced-resources=yes",
+ "--normalize-content=y",
+ "--object-streams=preserve",
+ inputPdf.toAbsolutePath().toString(),
+ cleanedPdf.toAbsolutePath().toString());
+
+ ProcessExecutorResult result =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
+ .runCommandWithOutputHandling(command);
+
+ if (result.getRc() == 0 && Files.exists(cleanedPdf)) {
+ log.info("PDF CIDSet cleaned with QPDF");
+ return cleanedPdf;
+ }
+ return null;
+
+ } catch (Exception e) {
+ log.debug("QPDF CIDSet cleaning error: {}", e.getMessage());
+ return null;
+ }
+ }
+
+ private byte[] convertWithPdfBoxMethod(Path inputPath, PdfaProfile profile) throws Exception {
+ Path tempInputFile = null;
+ byte[] fileBytes;
+ Path loPdfPath = null;
+ File preProcessedFile = null;
+ int pdfaPart = profile.getPart();
+ Path normalizedPath = null;
+
+ try {
+ tempInputFile = inputPath;
+
+ normalizedPath = normalizePdfWithQpdf(tempInputFile);
+ if (normalizedPath != null) {
+ tempInputFile = normalizedPath;
+ }
+
+ if (pdfaPart == 2 || pdfaPart == 3) {
+ preProcessedFile = tempInputFile.toFile();
+ } else {
+ preProcessedFile = preProcessHighlights(tempInputFile.toFile());
+ }
+
+ Set missingFonts;
+ boolean needImgs;
+ try (PDDocument doc = Loader.loadPDF(preProcessedFile)) {
+ missingFonts = findUnembeddedFontNames(doc);
+ needImgs = (pdfaPart == 1) && hasTransparentImages(doc);
+ if (!missingFonts.isEmpty() || needImgs) {
+ loPdfPath = runLibreOfficeConversion(preProcessedFile.toPath(), pdfaPart);
+ }
+ }
+ fileBytes =
+ convertToPdfA(
+ preProcessedFile.toPath(), loPdfPath, pdfaPart, missingFonts, needImgs);
+
+ return fileBytes;
+
+ } finally {
+ if (loPdfPath != null && loPdfPath.getParent() != null) {
+ FileUtils.deleteDirectory(loPdfPath.getParent().toFile());
+ }
+ if (preProcessedFile != null && !preProcessedFile.equals(tempInputFile.toFile())) {
+ Files.deleteIfExists(preProcessedFile.toPath());
+ }
+ if (normalizedPath != null && !normalizedPath.equals(inputPath)) {
+ Files.deleteIfExists(normalizedPath);
+ }
+ }
+ }
+
+ private void copyResourceIcc(Path target) throws IOException {
+ try (InputStream in = getClass().getResourceAsStream(ICC_RESOURCE_PATH)) {
+ if (in == null) {
+ throw ExceptionUtils.createIllegalArgumentException(
+ "error.resourceNotFound", "Resource not found: {0}", ICC_RESOURCE_PATH);
+ }
+ Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+
+ private void addICCProfileIfNotPresent(PDDocument document) {
+ if (document.getDocumentCatalog().getOutputIntents().isEmpty()) {
+ try (InputStream colorProfile = getClass().getResourceAsStream(ICC_RESOURCE_PATH)) {
+ if (colorProfile == null) {
+ throw ExceptionUtils.createIllegalArgumentException(
+ "error.resourceNotFound", "Resource not found: {0}", ICC_RESOURCE_PATH);
+ }
+ PDOutputIntent outputIntent = new PDOutputIntent(document, colorProfile);
+ // PDF/A compliant output intent settings
+ outputIntent.setInfo("sRGB IEC61966-2.1");
+ outputIntent.setOutputCondition("sRGB IEC61966-2.1");
+ outputIntent.setOutputConditionIdentifier("sRGB IEC61966-2.1");
+ outputIntent.setRegistryName("http://www.color.org");
+ document.getDocumentCatalog().addOutputIntent(outputIntent);
+ log.debug("Added ICC color profile for PDF/A compliance");
+ } catch (Exception e) {
+ log.error("Failed to load ICC profile: {}", e.getMessage());
+ throw new RuntimeException("ICC profile loading failed for PDF/A compliance", e);
+ }
+ }
+ }
+
+ @Getter
+ private enum PdfaProfile {
+ PDF_A_1B(1, "PDF/A-1b", "_PDFA-1b.pdf", "1.4", Format.PDF_A1B, "pdfa-1"),
+ PDF_A_2B(2, "PDF/A-2b", "_PDFA-2b.pdf", "1.7", null, "pdfa", "pdfa-2", "pdfa-2b"),
+ PDF_A_3B(3, "PDF/A-3b", "_PDFA-3b.pdf", "1.7", null, "pdfa-3", "pdfa-3b");
+
+ private final int part;
+ private final String displayName;
+ private final String suffix;
+ private final String compatibilityLevel;
+ private final Format preflightFormat;
+ private final List requestTokens;
+
+ PdfaProfile(
+ int part,
+ String displayName,
+ String suffix,
+ String compatibilityLevel,
+ Format preflightFormat,
+ String... requestTokens) {
+ this.part = part;
+ this.displayName = displayName;
+ this.suffix = suffix;
+ this.compatibilityLevel = compatibilityLevel;
+ this.preflightFormat = preflightFormat;
+ this.requestTokens =
+ Arrays.stream(requestTokens)
+ .map(token -> token.toLowerCase(Locale.ROOT))
+ .toList();
+ }
+
+ static PdfaProfile fromRequest(String requestToken) {
+ if (requestToken == null) {
+ return PDF_A_2B;
+ }
+ String normalized = requestToken.trim().toLowerCase(Locale.ROOT);
+ Optional match =
+ Arrays.stream(values())
+ .filter(profile -> profile.requestTokens.contains(normalized))
+ .findFirst();
+
+ return match.orElse(PDF_A_2B);
+ }
+
+ String outputSuffix() {
+ return suffix;
+ }
+
+ Optional preflightFormat() {
+ return Optional.ofNullable(preflightFormat);
+ }
+ }
+
+ @Getter
+ private enum PdfXProfile {
+ PDF_X_1("PDF/X-1", "_PDFX-1.pdf", "1.3", "2001", "pdfx-1", "pdfx"),
+ PDF_X_3("PDF/X-3", "_PDFX-3.pdf", "1.3", "2003", "pdfx-3"),
+ PDF_X_4("PDF/X-4", "_PDFX-4.pdf", "1.4", "2008", "pdfx-4");
+
+ private final String displayName;
+ private final String suffix;
+ private final String compatibilityLevel;
+ private final String pdfxVersion;
+ private final List requestTokens;
+
+ PdfXProfile(
+ String displayName,
+ String suffix,
+ String compatibilityLevel,
+ String pdfxVersion,
+ String... requestTokens) {
+ this.displayName = displayName;
+ this.suffix = suffix;
+ this.compatibilityLevel = compatibilityLevel;
+ this.pdfxVersion = pdfxVersion;
+ this.requestTokens =
+ Arrays.stream(requestTokens)
+ .map(token -> token.toLowerCase(Locale.ROOT))
+ .toList();
+ }
+
+ static PdfXProfile fromRequest(String requestToken) {
+ if (requestToken == null) {
+ return PDF_X_4;
+ }
+ String normalized = requestToken.trim().toLowerCase(Locale.ROOT);
+ Optional match =
+ Arrays.stream(values())
+ .filter(profile -> profile.requestTokens.contains(normalized))
+ .findFirst();
+
+ return match.orElse(PDF_X_4);
+ }
+
+ String outputSuffix() {
+ return suffix;
+ }
+ }
+
+ private record ColorProfiles(Path rgb, Path gray) {}
}
diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java
index 0553988ca1..4bda52cc79 100644
--- a/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java
+++ b/app/core/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java
@@ -12,8 +12,11 @@ import stirling.software.common.model.api.PDFFile;
public class PdfToPdfARequest extends PDFFile {
@Schema(
- description = "The output PDF/A type",
+ description = "The output format type (PDF/A or PDF/X)",
requiredMode = Schema.RequiredMode.REQUIRED,
- allowableValues = {"pdfa", "pdfa-1"})
+ allowableValues = {
+ "pdfa", "pdfa-1", "pdfa-2", "pdfa-2b", "pdfa-3", "pdfa-3b", "pdfx", "pdfx-1",
+ "pdfx-3", "pdfx-4"
+ })
private String outputFormat;
}
diff --git a/app/core/src/main/resources/messages_ar_AR.properties b/app/core/src/main/resources/messages_ar_AR.properties
index da7b871df3..ae7c673c1b 100644
--- a/app/core/src/main/resources/messages_ar_AR.properties
+++ b/app/core/src/main/resources/messages_ar_AR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=استخراج الصور
home.extractImages.desc=يستخرج جميع الصور من ملف PDF ويحفظها في الرمز البريدي
extractImages.tags=صورة,صورة فوتوغرافية,حفظ,أرشيف,ملف مضغوط,التقاط,انتزاع
-home.pdfToPDFA.title=تحويل ملفات PDF إلى PDF / A
-home.pdfToPDFA.desc=تحويل PDF إلى PDF / A للتخزين طويل المدى
-pdfToPDFA.tags=أرشيف,طويل الأجل,معيار,تحويل,تخزين,حفظ
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=تحويل PDF إلى Word
home.PDFToWord.desc=تحويل PDF إلى تنسيقات Word (DOC و DOCX و ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF إلى PDF/A
-pdfToPDFA.header=PDF إلى PDF/A
-pdfToPDFA.credit=تستخدم هذه الخدمة libreoffice لتحويل PDF/A.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=تحويل
-pdfToPDFA.tip=لا يعمل حاليًا لمدخلات متعددة في وقت واحد
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=تنسيق الإخراج
pdfToPDFA.pdfWithDigitalSignature=يحتوي PDF على توقيع رقمي. سيتم إزالة هذا في الخطوة التالية.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_az_AZ.properties b/app/core/src/main/resources/messages_az_AZ.properties
index b433016edf..77b0b6dcd0 100644
--- a/app/core/src/main/resources/messages_az_AZ.properties
+++ b/app/core/src/main/resources/messages_az_AZ.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Şəkilləri Xaric Et
home.extractImages.desc=PDF-dəki şəkilləri xaric edib onları zip faylında saxlayır
extractImages.tags=şəkil,foto,saxla,arxiv,zip,çək,götür
-home.pdfToPDFA.title=PDF-dən PDF/A-a
-home.pdfToPDFA.desc=PDF faylını uzunmüddətli saxlama üçün PDF/A-a çevir
-pdfToPDFA.tags=arxiv,uzunmüddətli,standard,çevirmə,yaddaş,saxlama
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF-dən Word-ə
home.PDFToWord.desc=PDF-i Word formatlarına çevir (DOC, DOCX və ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF-i PDF/A-ya
-pdfToPDFA.header=PDF-i PDF/A-ya
-pdfToPDFA.credit=Bu Servis PDF/A Çevirmək Üçün libreoffice İşlədir
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Çevir
-pdfToPDFA.tip=Hazırda Birdən Çox Giriş Üçün İşləmir
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Çıxış Formatı
pdfToPDFA.pdfWithDigitalSignature=PDF Rəqəmsal İmza Ehtiva Edir.Bu, növbəti addımda silinəcək.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_bg_BG.properties b/app/core/src/main/resources/messages_bg_BG.properties
index 8f9d911a32..298cd86dd8 100644
--- a/app/core/src/main/resources/messages_bg_BG.properties
+++ b/app/core/src/main/resources/messages_bg_BG.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Извличане на изображения
home.extractImages.desc=Извлича всички изображения от PDF и ги записва в архив
extractImages.tags=изображение,снимка,запазване,архивиране,архив,заснемане,грабване
-home.pdfToPDFA.title=PDF в PDF/A
-home.pdfToPDFA.desc=Конвертирайте PDF в PDF/A за дългосрочно съхранение
-pdfToPDFA.tags=архив,дълготраен,стандартен,преобразуване,съхранение,консервиране
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF в Word
home.PDFToWord.desc=Преобразуване на PDF в Word формати (DOC, DOCX и ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Отключване на PDF формуляри
unlockPDFForms.submit=Премахване
#pdfToPDFA
-pdfToPDFA.title=PDF в PDF/A
-pdfToPDFA.header=PDF в PDF/A
-pdfToPDFA.credit=Тази услуга използва LibreOffice за PDF/A преобразуване.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Преобразуване
-pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Изходен формат
pdfToPDFA.pdfWithDigitalSignature=PDF файлът съдържа цифров подпис. Това ще бъде премахнато в следващата стъпка.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_bo_CN.properties b/app/core/src/main/resources/messages_bo_CN.properties
index 0d006ec9a1..03d90720f6 100644
--- a/app/core/src/main/resources/messages_bo_CN.properties
+++ b/app/core/src/main/resources/messages_bo_CN.properties
@@ -694,9 +694,9 @@ home.extractImages.title=པར་རིས་ཕྱིར་འདོན།
home.extractImages.desc=PDF ནས་པར་རིས་ཚང་མ་ཕྱིར་བཏོན་ནས་ zip ནང་ཉར་ཚགས་བྱེད་པ།
extractImages.tags=པར།,འདྲ་པར།,ཉར་ཚགས།,ཡིག་མཛོད།,zip,འཛིན་པ།,ལེན་པ།
-home.pdfToPDFA.title=PDF ནས་ PDF/A ལ།
-home.pdfToPDFA.desc=PDF ནས་དུས་ཡུན་རིང་པོའི་ཉར་ཚགས་ཆེད་ PDF/A ལ་བསྒྱུར་བ།
-pdfToPDFA.tags=ཡིག་མཛོད།,དུས་ཡུན་རིང་པོ།,ཚད་ལྡན།,བསྒྱུར་བ།,ཉར་ཚགས།,སྲུང་སྐྱོབ།
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF ནས་ Word ལ།
home.PDFToWord.desc=PDF ནས་ Word རྣམ་གཞག་ (DOC, DOCX དང་ ODT) ལ་བསྒྱུར་བ།
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF ནས་ PDF/A ལ།
-pdfToPDFA.header=PDF ནས་ PDF/A ལ།
-pdfToPDFA.credit=ཞབས་ཞུ་འདིས་ PDF/A བསྒྱུར་བའི་ཆེད་དུ་ libreoffice བེད་སྤྱོད་བྱེད་པ།
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=བསྒྱུར་བ།
-pdfToPDFA.tip=ད་ལྟ་ཡིག་ཆ་མང་པོ་དུས་གཅིག་ལ་བསྒྱུར་མི་ཐུབ།
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=ཕྱིར་འདོན་རྣམ་གཞག
pdfToPDFA.pdfWithDigitalSignature=PDF འདིར་ཨང་ཀིའི་མིང་རྟགས་ཡོད། འདི་རྗེས་མའི་རིམ་པར་སུབ་ངེས་ཡིན།
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ca_CA.properties b/app/core/src/main/resources/messages_ca_CA.properties
index 3192b6b944..c491f7de96 100644
--- a/app/core/src/main/resources/messages_ca_CA.properties
+++ b/app/core/src/main/resources/messages_ca_CA.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extreu Imatges
home.extractImages.desc=Extreu les imatges del PDF i desa-les en un arxiu zip
extractImages.tags=imatge,foto,desa,arxiva,zip,captura,agafa
-home.pdfToPDFA.title=PDF a PDF/A
-home.pdfToPDFA.desc=Converteix PDF a PDF/A per a l'emmagatzematge a llarg termini.
-pdfToPDFA.tags=arxiu,llarg termini,estàndard,conversió,emmagatzematge,preservació
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF a Word
home.PDFToWord.desc=Converteix PDF a formats de Word (DOC, DOCX i ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF a PDF/A
-pdfToPDFA.header=PDF a PDF/A
-pdfToPDFA.credit=Utilitza libreoffice per a la conversió a PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Converteix
-pdfToPDFA.tip=Actualment no funciona per a múltiples entrades al mateix temps
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Format de sortida
pdfToPDFA.pdfWithDigitalSignature=El PDF conté una signatura digital. Aquesta serà eliminada en el següent pas.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_cs_CZ.properties b/app/core/src/main/resources/messages_cs_CZ.properties
index d67f49966f..5d210a404e 100644
--- a/app/core/src/main/resources/messages_cs_CZ.properties
+++ b/app/core/src/main/resources/messages_cs_CZ.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extrahovat obrázky
home.extractImages.desc=Extrahuje všechny obrázky z PDF a uloží je do zipu
extractImages.tags=obrázek,fotka,uložit,archiv,zip,zachytit,získat
-home.pdfToPDFA.title=PDF na PDF/A
-home.pdfToPDFA.desc=Převést PDF na PDF/A pro dlouhodobé uchovávání
-pdfToPDFA.tags=archiv,dlouhodobý,standard,převod,úložiště,uchování
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF na Word
home.PDFToWord.desc=Převést PDF na formáty Word (DOC, DOCX a ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF na PDF/A
-pdfToPDFA.header=PDF na PDF/A
-pdfToPDFA.credit=Tato služba používá libreoffice pro konverzi do PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Převést
-pdfToPDFA.tip=Momentálně nefunguje pro více vstupů najednou
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Výstupní formát
pdfToPDFA.pdfWithDigitalSignature=PDF obsahuje digitální podpis, který bude v dalším kroku odstraněn.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_da_DK.properties b/app/core/src/main/resources/messages_da_DK.properties
index d2ad107252..d04108c89a 100644
--- a/app/core/src/main/resources/messages_da_DK.properties
+++ b/app/core/src/main/resources/messages_da_DK.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Udtræk Billeder
home.extractImages.desc=Udtrækker alle billeder fra en PDF og gemmer dem som zip
extractImages.tags=billede,foto,gem,arkiv,zip,fang,grib
-home.pdfToPDFA.title=PDF til PDF/A
-home.pdfToPDFA.desc=Konvertér PDF til PDF/A for langtidsopbevaring
-pdfToPDFA.tags=arkiv,langtids,standard,konvertering,opbevaring,bevaring
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF til Word
home.PDFToWord.desc=Konvertér PDF til Word-formater (DOC, DOCX og ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF Til PDF/A
-pdfToPDFA.header=PDF Til PDF/A
-pdfToPDFA.credit=Denne tjeneste bruger libreoffice til PDF/A-konvertering
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konvertér
-pdfToPDFA.tip=Fungerer i øjeblikket ikke for flere input på én gang
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Outputformat
pdfToPDFA.pdfWithDigitalSignature=PDF'en indeholder en digital signatur. Dette vil blive fjernet i næste trin.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_de_DE.properties b/app/core/src/main/resources/messages_de_DE.properties
index 9625d89357..f5476f64ca 100644
--- a/app/core/src/main/resources/messages_de_DE.properties
+++ b/app/core/src/main/resources/messages_de_DE.properties
@@ -698,9 +698,9 @@ home.extractImages.title=Bilder extrahieren
home.extractImages.desc=Extrahiert alle Bilder aus einer PDF-Datei und speichert sie als Zip-Archiv
extractImages.tags=bild,foto,speichern,archivieren,zippen,erfassen,greifen
-home.pdfToPDFA.title=PDF zu PDF/A konvertieren
-home.pdfToPDFA.desc=PDF zu PDF/A für Langzeitarchivierung konvertieren
-pdfToPDFA.tags=archiv,langfristig,standard,konvertierung,speicherung,aufbewahrung
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF zu Word
home.PDFToWord.desc=PDF in Word-Formate konvertieren (DOC, DOCX und ODT)
@@ -1634,13 +1634,15 @@ unlockPDFForms.header=Schreibgeschützte PDF-Formfelder entfernen
unlockPDFForms.submit=Entfernen
#pdfToPDFA
-pdfToPDFA.title=PDF zu PDF/A
-pdfToPDFA.header=PDF zu PDF/A
-pdfToPDFA.credit=Dieser Dienst verwendet libreoffice für die PDF/A-Konvertierung
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konvertieren
-pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Ausgabeformat
pdfToPDFA.pdfWithDigitalSignature=Das PDF enthält eine digitale Signatur. Sie wird im nächsten Schritt entfernt.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_el_GR.properties b/app/core/src/main/resources/messages_el_GR.properties
index bb8732c6d5..f2802a143b 100644
--- a/app/core/src/main/resources/messages_el_GR.properties
+++ b/app/core/src/main/resources/messages_el_GR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Εξαγωγή εικόνων
home.extractImages.desc=Εξαγωγή όλων των εικόνων από PDF και αποθήκευση σε zip
extractImages.tags=εικόνα,φωτογραφία,αποθήκευση,αρχείο,zip,σύλληψη,λήψη
-home.pdfToPDFA.title=PDF σε PDF/A
-home.pdfToPDFA.desc=Μετατροπή PDF σε PDF/A για μακροχρόνια αποθήκευση
-pdfToPDFA.tags=αρχείο,μακροχρόνιο,πρότυπο,μετατροπή,αποθήκευση,διατήρηση
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF σε Word
home.PDFToWord.desc=Μετατροπή PDF σε μορφές Word (DOC, DOCX και ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF σε PDF/A
-pdfToPDFA.header=PDF σε PDF/A
-pdfToPDFA.credit=Αυτή η υπηρεσία χρησιμοποιεί libreoffice για μετατροπή PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Μετατροπή
-pdfToPDFA.tip=Προς το παρόν δεν λειτουργεί για πολλαπλές εισόδους ταυτόχρονα
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Μορφή εξόδου
pdfToPDFA.pdfWithDigitalSignature=Το PDF περιέχει ψηφιακή υπογραφή. Αυτή θα αφαιρεθεί στο επόμενο βήμα.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_en_GB.properties b/app/core/src/main/resources/messages_en_GB.properties
index dc4dbe96e8..202a641762 100644
--- a/app/core/src/main/resources/messages_en_GB.properties
+++ b/app/core/src/main/resources/messages_en_GB.properties
@@ -698,9 +698,9 @@ home.extractImages.title=Extract Images
home.extractImages.desc=Extracts all images from a PDF and saves them to zip
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=PDF to PDF/A
-home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage
-pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF to Word
home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
@@ -1635,13 +1635,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF To PDF/A
-pdfToPDFA.header=PDF To PDF/A
-pdfToPDFA.credit=This service uses LibreOffice for PDF/A conversion
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Convert
-pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_en_US.properties b/app/core/src/main/resources/messages_en_US.properties
index 287955226e..16d3b398c0 100644
--- a/app/core/src/main/resources/messages_en_US.properties
+++ b/app/core/src/main/resources/messages_en_US.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extract Images
home.extractImages.desc=Extracts all images from a PDF and saves them to zip
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=PDF to PDF/A
-home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage
-pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF to Word
home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF To PDF/A
-pdfToPDFA.header=PDF To PDF/A
-pdfToPDFA.credit=This service uses libreoffice for PDF/A conversion
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Convert
-pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_es_ES.properties b/app/core/src/main/resources/messages_es_ES.properties
index 2cb9bd53ff..2b1d38efa0 100644
--- a/app/core/src/main/resources/messages_es_ES.properties
+++ b/app/core/src/main/resources/messages_es_ES.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extraer imágenes
home.extractImages.desc=Extraer todas las imágenes de un PDF y guardarlas en ZIP
extractImages.tags=imagen,fotografía,guardar,archivo,zip,capturar,coger
-home.pdfToPDFA.title=Convertir PDF a PDF/A
-home.pdfToPDFA.desc=Convertir PDF a PDF/A para almacenamiento a largo plazo
-pdfToPDFA.tags=archivo,largo plazo,estándar,conversión,almacenamiento,conservación
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF a Word
home.PDFToWord.desc=Convertir formatos PDF a Word (DOC, DOCX y ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Desbloquear lso formlarios del PDF
unlockPDFForms.submit=Eliminar
#pdfToPDFA
-pdfToPDFA.title=PDF a PDF/A
-pdfToPDFA.header=PDF a PDF/A
-pdfToPDFA.credit=Este servicio usa LibreOffice para la conversión a PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Convertir
-pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Formato de salida
pdfToPDFA.pdfWithDigitalSignature=El PDF contiene una firma digital. Ésta se eliminará en el siguiente paso.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_eu_ES.properties b/app/core/src/main/resources/messages_eu_ES.properties
index 6ea71e3fe7..b402a2dcfc 100644
--- a/app/core/src/main/resources/messages_eu_ES.properties
+++ b/app/core/src/main/resources/messages_eu_ES.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Atera irudiak
home.extractImages.desc=Atera irudi guztiak PDF batetik eta ZIPen gorde
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=PDFa PDF/A bihurtu
-home.pdfToPDFA.desc=PDFa PDF/A bihurtu luzaro biltegiratzeko
-pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDFa Word Bihurtu
home.PDFToWord.desc=PDF formatuak Word bihurtu (DOC, DOCX y ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDFa PDF/A bihurtu
-pdfToPDFA.header=PDFa PDF/A bihurtu
-pdfToPDFA.credit=Zerbitzu honek libreoffice erabiltzen du PDFak PDF/A bihurtzeko
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Bihurtu
-pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_fa_IR.properties b/app/core/src/main/resources/messages_fa_IR.properties
index 96be599108..af0ad6376f 100644
--- a/app/core/src/main/resources/messages_fa_IR.properties
+++ b/app/core/src/main/resources/messages_fa_IR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=استخراج تصاویر
home.extractImages.desc=استخراج تمام تصاویر از یک PDF و ذخیره آنها به صورت فایل زیپ
extractImages.tags=عکس،عکس،ذخیره،آرشیو،زیپ،گرفتن،برداشتن
-home.pdfToPDFA.title=PDF به PDF/A
-home.pdfToPDFA.desc=تبدیل PDF به PDF/A برای ذخیرهسازی بلندمدت
-pdfToPDFA.tags=آرشیو،ذخیرهسازی بلندمدت،استاندارد،تبدیل،ذخیرهسازی،حفظ
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF به ورد
home.PDFToWord.desc=تبدیل PDF به فرمتهای ورد (DOC، DOCX و ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF به PDF/A
-pdfToPDFA.header=PDF به PDF/A
-pdfToPDFA.credit=این سرویس از libreoffice برای تبدیل PDF/A استفاده میکند
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=تبدیل
-pdfToPDFA.tip=در حال حاضر برای چندین ورودی به طور همزمان کار نمیکند
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=فرمت خروجی
pdfToPDFA.pdfWithDigitalSignature=PDF حاوی یک امضای دیجیتال است. این در مرحله بعد حذف خواهد شد.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_fr_FR.properties b/app/core/src/main/resources/messages_fr_FR.properties
index 64e624dc45..910ef14040 100644
--- a/app/core/src/main/resources/messages_fr_FR.properties
+++ b/app/core/src/main/resources/messages_fr_FR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extraire les images
home.extractImages.desc=Extrayez toutes les images d'un PDF et enregistrez-les dans un ZIP.
extractImages.tags=image,photo,sauvegarder,archiver,zip,capturer,grab
-home.pdfToPDFA.title=PDF en PDF/A
-home.pdfToPDFA.desc=Convertir un PDF en PDF/A pour un stockage à long terme.
-pdfToPDFA.tags=convertion,archive,long-term,standard,conversion,storage,préservation,preservation
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF en Word
home.PDFToWord.desc=Convertissez un PDF en Word (DOC, DOCX ou ODT).
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Déverrouiller les formulaires PDF
unlockPDFForms.submit=Supprimer
#pdfToPDFA
-pdfToPDFA.title=PDF en PDF/A
-pdfToPDFA.header=PDF en PDF/A
-pdfToPDFA.credit=Ce service utilise LibreOffice pour la conversion en PDF/A.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Convertir
-pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Format de sortie
pdfToPDFA.pdfWithDigitalSignature=Le PDF contient une signature numérique. Elle sera supprimée dans l'étape suivante.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ga_IE.properties b/app/core/src/main/resources/messages_ga_IE.properties
index fb6f548fb2..ac788c9163 100644
--- a/app/core/src/main/resources/messages_ga_IE.properties
+++ b/app/core/src/main/resources/messages_ga_IE.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Sliocht Íomhánna
home.extractImages.desc=Sliochtann sé gach íomhá ó PDF agus sábhálann sé iad a zip
extractImages.tags=pictiúr, grianghraf, shábháil, cartlann, zip, gabháil, grab
-home.pdfToPDFA.title=PDF go PDF/A
-home.pdfToPDFA.desc=Tiontaigh PDF go PDF/A le haghaidh stórála fadtéarmach
-pdfToPDFA.tags=cartlann, fadtéarmach, caighdeánach, comhshó, stóráil, caomhnú
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF a thiontú go Word
home.PDFToWord.desc=Tiontaigh PDF go formáidí Word (DOC, DOCX agus ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF Go PDF/A
-pdfToPDFA.header=PDF Go PDF/A
-pdfToPDFA.credit=Úsáideann an tseirbhís seo libreoffice chun PDF/A a thiontú
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Tiontaigh
-pdfToPDFA.tip=Faoi láthair ní oibríonn sé le haghaidh ionchuir iolracha ag an am céanna
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Formáid aschuir
pdfToPDFA.pdfWithDigitalSignature=Tá síniú digiteach ar an PDF. Bainfear é seo sa chéad chéim eile.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_hi_IN.properties b/app/core/src/main/resources/messages_hi_IN.properties
index 44f9793b2b..ea52bc9076 100644
--- a/app/core/src/main/resources/messages_hi_IN.properties
+++ b/app/core/src/main/resources/messages_hi_IN.properties
@@ -694,9 +694,9 @@ home.extractImages.title=छवियां निकालें
home.extractImages.desc=PDF से सभी छवियों को निकालें और उन्हें ज़िप में सहेजें
extractImages.tags=चित्र,फोटो,सहेजें,संग्रह,ज़िप,कैप्चर,ग्रैब
-home.pdfToPDFA.title=PDF से PDF/A
-home.pdfToPDFA.desc=लंबी अवधि के भंडारण के लिए PDF को PDF/A में बदलें
-pdfToPDFA.tags=संग्रह,लंबी अवधि,मानक,रूपांतरण,भंडारण,संरक्षण
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF से Word
home.PDFToWord.desc=PDF को Word प्रारूपों में बदलें (DOC, DOCX और ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF से PDF/A
-pdfToPDFA.header=PDF से PDF/A
-pdfToPDFA.credit=यह सेवा PDF/A रूपांतरण के लिए libreoffice का उपयोग करती है
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=बदलें
-pdfToPDFA.tip=वर्तमान में एक बार में कई इनपुट के लिए काम नहीं करता
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=आउटपुट प्रारूप
pdfToPDFA.pdfWithDigitalSignature=PDF में एक डिजिटल हस्ताक्षर है। यह अगले चरण में हटा दिया जाएगा।
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_hr_HR.properties b/app/core/src/main/resources/messages_hr_HR.properties
index 6166c8e998..31aaf855bf 100644
--- a/app/core/src/main/resources/messages_hr_HR.properties
+++ b/app/core/src/main/resources/messages_hr_HR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Izdvoji slike
home.extractImages.desc=Izdvaja sve slike iz PDF-a i sprema ih u zip arhivu
extractImages.tags=slika,fotografija,spremi,arhiva,zip,uhvati,zgrabi
-home.pdfToPDFA.title=PDF u PDF/A
-home.pdfToPDFA.desc=Pretvorite PDF u PDF/A za dugoročnu pohranu
-pdfToPDFA.tags=arhiva,dugoročno,standard,pretvorba,pohrana,očuvanje
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF u Word
home.PDFToWord.desc=Pretvorite PDF u Word formate (DOC, DOCX i ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Otključaj PDF obrasce
unlockPDFForms.submit=Ukloni
#pdfToPDFA
-pdfToPDFA.title=PDF u PDF/A
-pdfToPDFA.header=PDF u PDF/A
-pdfToPDFA.credit=Ova usluga koristi LibreOffice za PDF/A pretvorbu
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Pretvori
-pdfToPDFA.tip=Trenutno ne radi za više unosa odjednom
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Izlazni format
pdfToPDFA.pdfWithDigitalSignature=PDF sadrži digitalni potpis. On će biti uklonjen u sljedećem koraku.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_hu_HU.properties b/app/core/src/main/resources/messages_hu_HU.properties
index e977a122cf..37628de5ff 100644
--- a/app/core/src/main/resources/messages_hu_HU.properties
+++ b/app/core/src/main/resources/messages_hu_HU.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Képek kinyerése
home.extractImages.desc=Minden kép kinyerése a PDF-ből és mentése ZIP fájlba
extractImages.tags=kép,fotó,mentés,archívum,tömörítés,kinyerés,gyűjtés
-home.pdfToPDFA.title=PDF konvertálása PDF/A formátumba
-home.pdfToPDFA.desc=PDF konvertálása PDF/A formátumba hosszú távú tároláshoz
-pdfToPDFA.tags=archívum,hosszú távú,szabvány,konvertálás,tárolás,megőrzés
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF konvertálása Word formátumba
home.PDFToWord.desc=PDF konvertálása Word formátumokba (DOC, DOCX és ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=PDF űrlapok feloldása
unlockPDFForms.submit=Eltávolítás
#pdfToPDFA
-pdfToPDFA.title=PDF konvertálása PDF/A formátumba
-pdfToPDFA.header=PDF konvertálása PDF/A formátumba
-pdfToPDFA.credit=Ez a szolgáltatás a libreoffice használatával végzi a PDF/A konverziót
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konvertálás
-pdfToPDFA.tip=Jelenleg nem támogatja a több fájl egyidejű feldolgozását
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Kimeneti formátum
pdfToPDFA.pdfWithDigitalSignature=A PDF digitális aláírást tartalmaz. Ez a következő lépésben eltávolításra kerül.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_id_ID.properties b/app/core/src/main/resources/messages_id_ID.properties
index 8a0d3726e1..aa9ff13781 100644
--- a/app/core/src/main/resources/messages_id_ID.properties
+++ b/app/core/src/main/resources/messages_id_ID.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Ekstrak Gambar
home.extractImages.desc=Mengekstrak semua gambar dari PDF dan menyimpannya ke zip
extractImages.tags=gambar, foto, simpan, arsip, zip, tangkap, ambil
-home.pdfToPDFA.title=PDF ke PDF/A
-home.pdfToPDFA.desc=Konversi PDF ke PDF/A untuk penyimpanan jangka panjang
-pdfToPDFA.tags=arsip, jangka panjang, standar, konversi, penyimpanan, pelestarian
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF ke Word
home.PDFToWord.desc=Mengonversi format PDF ke Word (DOC, DOCX, dan ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF Ke PDF/A
-pdfToPDFA.header=PDF ke PDF/A
-pdfToPDFA.credit=Layanan ini menggunakan libreoffice untuk konversi PDF/A.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konversi
-pdfToPDFA.tip=Saat ini tidak dapat digunakan untuk beberapa input sekaligus
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Format keluaran
pdfToPDFA.pdfWithDigitalSignature=PDF ini mengandung tanda tangan digital. Ini akan dihapus pada langkah berikutnya.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_it_IT.properties b/app/core/src/main/resources/messages_it_IT.properties
index 76434bb6cc..0fafd17122 100644
--- a/app/core/src/main/resources/messages_it_IT.properties
+++ b/app/core/src/main/resources/messages_it_IT.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Estrai immagini
home.extractImages.desc=Estrai tutte le immagini da un PDF e salvale come zip.
extractImages.tags=immagine,foto,salva,archivio,zip,catturare,prendere
-home.pdfToPDFA.title=Converti in PDF/A
-home.pdfToPDFA.desc=Converti un PDF nel formato PDF/A per archiviazione a lungo termine.
-pdfToPDFA.tags=archivio,a lungo termine,standard,conversione,archiviazione,conservazione
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=Da PDF a Word
home.PDFToWord.desc=Converti un PDF nei formati Word (DOC, DOCX e ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Sbloccare i moduli PDF
unlockPDFForms.submit=Rimuovi
#pdfToPDFA
-pdfToPDFA.title=Da PDF a PDF/A
-pdfToPDFA.header=Da PDF a PDF/A
-pdfToPDFA.credit=Questo servizio utilizza libreoffice per la conversione in PDF/A.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Converti
-pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Formato di output
pdfToPDFA.pdfWithDigitalSignature=Il PDF contiene una firma digitale. Questo verrà rimosso nel passaggio successivo.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ja_JP.properties b/app/core/src/main/resources/messages_ja_JP.properties
index 85605c0e5f..50c2cc7c1a 100644
--- a/app/core/src/main/resources/messages_ja_JP.properties
+++ b/app/core/src/main/resources/messages_ja_JP.properties
@@ -694,9 +694,9 @@ home.extractImages.title=画像の抽出
home.extractImages.desc=PDFからすべての画像を抽出してzipで保存します。
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=PDFをPDF/Aに変換
-home.pdfToPDFA.desc=長期保存のためにPDFをPDF/Aに変換。
-pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDFをWordに変換
home.PDFToWord.desc=PDFをWord形式に変換します。 (DOC, DOCX および ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=PDFフォームのロックを解除
unlockPDFForms.submit=削除
#pdfToPDFA
-pdfToPDFA.title=PDFをPDF/Aに変換
-pdfToPDFA.header=PDFをPDF/Aに変換
-pdfToPDFA.credit=本サービスはPDF/Aの変換にlibreofficeを使用しています。
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=変換
-pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=出力形式
pdfToPDFA.pdfWithDigitalSignature=PDFにはデジタル署名が含まれています。これは次の手順で削除されます。
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ko_KR.properties b/app/core/src/main/resources/messages_ko_KR.properties
index cbe2904151..9053777776 100644
--- a/app/core/src/main/resources/messages_ko_KR.properties
+++ b/app/core/src/main/resources/messages_ko_KR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=이미지 추출
home.extractImages.desc=PDF에서 모든 이미지를 추출하여 zip으로 저장
extractImages.tags=사진,저장,아카이브,zip,캡처,가져오기
-home.pdfToPDFA.title=PDF를 PDF/A로
-home.pdfToPDFA.desc=장기 보관을 위해 PDF를 PDF/A로 변환
-pdfToPDFA.tags=아카이브,장기,표준,변환,저장,보존
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF를 Word로
home.PDFToWord.desc=PDF를 Word 형식으로 변환 (DOC, DOCX 및 ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF를 PDF/A로
-pdfToPDFA.header=PDF를 PDF/A로
-pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 libreoffice를 사용합니다
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=변환
-pdfToPDFA.tip=현재 여러 입력을 한 번에 처리할 수 없습니다
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=출력 형식
pdfToPDFA.pdfWithDigitalSignature=PDF에 디지털 서명이 포함되어 있습니다. 다음 단계에서 제거됩니다.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ml_IN.properties b/app/core/src/main/resources/messages_ml_IN.properties
index f22b73eb71..62153ed736 100644
--- a/app/core/src/main/resources/messages_ml_IN.properties
+++ b/app/core/src/main/resources/messages_ml_IN.properties
@@ -694,9 +694,9 @@ home.extractImages.title=ചിത്രങ്ങൾ വേർതിരിച്
home.extractImages.desc=ഒരു PDF-ൽ നിന്ന് എല്ലാ ചിത്രങ്ങളും വേർതിരിച്ചെടുത്ത് സിപ്പിലേക്ക് സംരക്ഷിക്കുന്നു
extractImages.tags=ചിത്രം,ഫോട്ടോ,സംരക്ഷിക്കുക,ആർക്കൈവ്,സിപ്പ്,പിടിച്ചെടുക്കുക,നേടുക
-home.pdfToPDFA.title=PDF PDF/A-ലേക്ക്
-home.pdfToPDFA.desc=ദീർഘകാല സംഭരണത്തിനായി PDF PDF/A-ലേക്ക് മാറ്റുക
-pdfToPDFA.tags=ആർക്കൈവ്,ദീർഘകാല,മാനദണ്ഡം,പരിവർത്തനം,സംഭരണം,സംരക്ഷണം
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF വേഡിലേക്ക്
home.PDFToWord.desc=PDF വേഡ് ഫോർമാറ്റുകളിലേക്ക് (DOC, DOCX, ODT) മാറ്റുക
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=PDF ഫോമുകൾ അൺലോക്ക് ചെയ
unlockPDFForms.submit=നീക്കം ചെയ്യുക
#pdfToPDFA
-pdfToPDFA.title=PDF PDF/A-ലേക്ക്
-pdfToPDFA.header=PDF PDF/A-ലേക്ക്
-pdfToPDFA.credit=ഈ സേവനം PDF/A പരിവർത്തനത്തിനായി libreoffice ഉപയോഗിക്കുന്നു
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=പരിവർത്തനം ചെയ്യുക
-pdfToPDFA.tip=നിലവിൽ ഒരേസമയം ഒന്നിലധികം ഇൻപുട്ടുകൾക്കായി പ്രവർത്തിക്കുന്നില്ല
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=ഔട്ട്പുട്ട് ഫോർമാറ്റ്
pdfToPDFA.pdfWithDigitalSignature=PDF-ൽ ഒരു ഡിജിറ്റൽ ഒപ്പ് അടങ്ങിയിരിക്കുന്നു. അടുത്ത ഘട്ടത്തിൽ ഇത് നീക്കം ചെയ്യപ്പെടും.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_nl_NL.properties b/app/core/src/main/resources/messages_nl_NL.properties
index ec8e921661..3004d6fb99 100644
--- a/app/core/src/main/resources/messages_nl_NL.properties
+++ b/app/core/src/main/resources/messages_nl_NL.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Afbeeldingen extraheren
home.extractImages.desc=Extraheert alle afbeeldingen uit een PDF en slaat ze op in een zip
extractImages.tags=foto,opslaan,archief,zip,vastleggen,plukken
-home.pdfToPDFA.title=PDF naar PDF/A
-home.pdfToPDFA.desc=Converteer PDF naar PDF/A voor toekomstbestendige opslag
-pdfToPDFA.tags=archief,langdurig,standaard,conversie,opslag,bewaring
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF naar Word
home.PDFToWord.desc=Converteer PDF naar Word-formaten (DOC, DOCX en ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=PDF-formulieren ontgrendelen
unlockPDFForms.submit=Verwijderen
#pdfToPDFA
-pdfToPDFA.title=PDF naar PDF/A
-pdfToPDFA.header=PDF naar PDF/A
-pdfToPDFA.credit=Deze functie gebruikt libreoffice voor PDF/A-conversie
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Converteren
-pdfToPDFA.tip=Werkt momenteel niet voor meerdere inputs tegelijkertijd.
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Uitvoerindeling
pdfToPDFA.pdfWithDigitalSignature=Dit PDF bestand bevat een digitale handtekening. Deze wordt in de volgende stap verwijderd.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_no_NB.properties b/app/core/src/main/resources/messages_no_NB.properties
index 5aaaa82225..11a688dd68 100644
--- a/app/core/src/main/resources/messages_no_NB.properties
+++ b/app/core/src/main/resources/messages_no_NB.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Ekstraher Bilder
home.extractImages.desc=Ekstraherer alle bilder fra en PDF og lagrer dem som zip
extractImages.tags=bilde,foto,lagre,arkiv,zip,fangst,hent
-home.pdfToPDFA.title=PDF til PDF/A
-home.pdfToPDFA.desc=Konverter PDF til PDF/A for langtidslagring
-pdfToPDFA.tags=arkiv,langtidslagring,standard,konvertering,lagring,bevaring
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF til Word
home.PDFToWord.desc=Konverter PDF til Word formater (DOC, DOCX og ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF til PDF/A
-pdfToPDFA.header=PDF til PDF/A
-pdfToPDFA.credit=Denne tjenesten bruker libreoffice for PDF/A-konvertering
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konverter
-pdfToPDFA.tip=Fungere for øyeblikket ikke for flere innganger samtidig
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Utdataformat
pdfToPDFA.pdfWithDigitalSignature=PDFen inneholder en digital signatur. Denne vil bli fjernet i neste steg.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_pl_PL.properties b/app/core/src/main/resources/messages_pl_PL.properties
index 34154aeaab..7040a7dd2d 100644
--- a/app/core/src/main/resources/messages_pl_PL.properties
+++ b/app/core/src/main/resources/messages_pl_PL.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Wyodrębnij obrazy
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
extractImages.tags=obraz, zdjęcie, zapisz, archiwum, zip, przechwyć, złap
-home.pdfToPDFA.title=PDF na PDF/A
-home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
-pdfToPDFA.tags=archiwum, długoterminowe, standardowe, konwersja, przechowywanie, konserwacja
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF na Word
home.PDFToWord.desc=Konwertuj dokument PDF na formaty Word (DOC, DOCX i ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Odblokuj formularze PDF
unlockPDFForms.submit=Usuń blokadę
#pdfToPDFA
-pdfToPDFA.title=PDF na PDF/A
-pdfToPDFA.header=PDF na PDF/A
-pdfToPDFA.credit=Ta usługa używa libreoffice do konwersji PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konwertuj
-pdfToPDFA.tip=Tylko jeden plik na raz
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Format wyjściowy:
pdfToPDFA.pdfWithDigitalSignature=Dokument zawiera podpis cyfrowy, nie zostanie on wczytany.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_pt_BR.properties b/app/core/src/main/resources/messages_pt_BR.properties
index 708ee6338e..18d4264bbc 100644
--- a/app/core/src/main/resources/messages_pt_BR.properties
+++ b/app/core/src/main/resources/messages_pt_BR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extrair Imagens
home.extractImages.desc=Extrair as imagens de um PDF e salvá-las em um arquivo compactado.
extractImages.tags=imagem,foto,salvar,arquivo,zip,captura,coleta
-home.pdfToPDFA.title=PDF para PDF/A
-home.pdfToPDFA.desc=Converter o PDF para o formato PDF/A, voltado a armazenamento a longo prazo.
-pdfToPDFA.tags=arquivo,longo prazo,padrão,conversão,armazenamento,preservação
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF para Word
home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT).
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Desbloquear Formulários do PDF
unlockPDFForms.submit=Remover
#pdfToPDFA
-pdfToPDFA.title=PDF para PDF/A
-pdfToPDFA.header=PDF para PDF/A
-pdfToPDFA.credit=Este serviço usa o LibreOffice para conversão para PDF/A.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Converter
-pdfToPDFA.tip=Atenção, atualmente não funciona para múltiplas entradas ao mesmo tempo.
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Formato de saída:
pdfToPDFA.pdfWithDigitalSignature=O PDF contém uma assinatura digital. Isso será removido na próxima etapa.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_pt_PT.properties b/app/core/src/main/resources/messages_pt_PT.properties
index 039fbf7156..70a15922e8 100644
--- a/app/core/src/main/resources/messages_pt_PT.properties
+++ b/app/core/src/main/resources/messages_pt_PT.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extrair Imagens
home.extractImages.desc=Extrai todas as imagens de um PDF e guarda-as num zip
extractImages.tags=imagem,foto,guardar,arquivo,zip,capturar,extrair
-home.pdfToPDFA.title=PDF para PDF/A
-home.pdfToPDFA.desc=Converter PDF para PDF/A para armazenamento a longo prazo
-pdfToPDFA.tags=arquivo,longo prazo,padrão,conversão,armazenamento,preservação
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF para Word
home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Desbloquear Formulários do PDF
unlockPDFForms.submit=Remover
#pdfToPDFA
-pdfToPDFA.title=PDF Para PDF/A
-pdfToPDFA.header=PDF Para PDF/A
-pdfToPDFA.credit=Este serviço usa libreoffice para conversão PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Converter
-pdfToPDFA.tip=Atualmente não funciona para múltiplas entradas de uma só vez
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Formato de saída
pdfToPDFA.pdfWithDigitalSignature=O PDF contém uma assinatura digital. Esta será removida no próximo passo.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ro_RO.properties b/app/core/src/main/resources/messages_ro_RO.properties
index 606b153807..942edc0bdb 100644
--- a/app/core/src/main/resources/messages_ro_RO.properties
+++ b/app/core/src/main/resources/messages_ro_RO.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extrage Imagini
home.extractImages.desc=Extrage toate imaginile dintr-un PDF și le salvează într-un fișier zip.
extractImages.tags=poză,fotografie,salvează,arhivă,zip,captură,extrage
-home.pdfToPDFA.title=PDF în PDF/A
-home.pdfToPDFA.desc=Convertește un document PDF în format PDF/A pentru stocare pe termen lung.
-pdfToPDFA.tags=arhivă,termen-lung,standard,conversie,stocare,conservare
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF în Word
home.PDFToWord.desc=Convertește un document PDF în formate Word (DOC, DOCX și ODT).
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF către PDF/A
-pdfToPDFA.header=PDF către PDF/A
-pdfToPDFA.credit=Acest serviciu utilizează libreoffice pentru conversia în PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Convertește
-pdfToPDFA.tip=În prezent nu funcționează pentru mai multe intrări simultan
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Format de ieșire
pdfToPDFA.pdfWithDigitalSignature=PDF-ul conține o semnătură digitală. Aceasta va fi eliminată în pasul următor.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_ru_RU.properties b/app/core/src/main/resources/messages_ru_RU.properties
index eb6e636688..1031f81e3b 100644
--- a/app/core/src/main/resources/messages_ru_RU.properties
+++ b/app/core/src/main/resources/messages_ru_RU.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Извлечь изображения
home.extractImages.desc=Извлекает все изображения из PDF и сохраняет их в zip-архив
extractImages.tags=картинка,фото,сохранение,архив,zip,захват,извлечение
-home.pdfToPDFA.title=PDF в PDF/A
-home.pdfToPDFA.desc=Преобразование PDF в PDF/A для долгосрочного хранения
-pdfToPDFA.tags=архив,долгосрочный,стандарт,конвертация,хранение,сохранение
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF в Word
home.PDFToWord.desc=Преобразование PDF в форматы Word (DOC, DOCX и ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Разблокировать PDF-формы
unlockPDFForms.submit=Удалить
#pdfToPDFA
-pdfToPDFA.title=PDF в PDF/A
-pdfToPDFA.header=PDF в PDF/A
-pdfToPDFA.credit=Этот сервис использует libreoffice для преобразования в PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Преобразовать
-pdfToPDFA.tip=В настоящее время не работает с несколькими входными файлами одновременно
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Формат вывода
pdfToPDFA.pdfWithDigitalSignature=PDF содержит цифровую подпись. Она будет удалена на следующем шаге.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_sk_SK.properties b/app/core/src/main/resources/messages_sk_SK.properties
index 34499c9a9a..4cdc4f718f 100644
--- a/app/core/src/main/resources/messages_sk_SK.properties
+++ b/app/core/src/main/resources/messages_sk_SK.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extrahovať obrázky
home.extractImages.desc=Extrahuje všetky obrázky z PDF a uloží ich do zipu
extractImages.tags=obrázok,fotografia,uložiť,archív,zip,zachytiť,chytiť
-home.pdfToPDFA.title=PDF na PDF/A
-home.pdfToPDFA.desc=Konvertujte PDF na PDF/A pre dlhodobé uchovávanie
-pdfToPDFA.tags=archív,dĺhodobé,štandard,konverzia,uchovanie
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF na Word
home.PDFToWord.desc=Konvertujte PDF na formáty Word (DOC, DOCX a ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF na PDF/A
-pdfToPDFA.header=PDF na PDF/A
-pdfToPDFA.credit=Táto služba používa libreoffice na konverziu PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konvertovať
-pdfToPDFA.tip=Momentálne nefunguje pre viacero vstupov naraz
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Výstupný formát
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_sl_SI.properties b/app/core/src/main/resources/messages_sl_SI.properties
index 0d42cad53e..3afcc362fe 100644
--- a/app/core/src/main/resources/messages_sl_SI.properties
+++ b/app/core/src/main/resources/messages_sl_SI.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Izvleči slike
home.extractImages.desc=Izvleče vse slike iz PDF-ja in jih shrani v zip
extractImages.tags=slika,fotografija,shrani,arhiv,zip,zajemi,zgrabi
-home.pdfToPDFA.title=PDF v PDF/A
-home.pdfToPDFA.desc=Pretvori PDF v PDF/A za dolgoročno shranjevanje
-pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF v Word
home.PDFToWord.desc=Pretvori PDF v format Word (DOC, DOCX in ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF v PDF/A
-pdfToPDFA.header=PDF v PDF/A
-pdfToPDFA.credit=Ta storitev uporablja libreoffice za pretvorbo PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Pretvori
-pdfToPDFA.tip=Trenutno ne deluje za več vnosov hkrati
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Izhodna oblika
pdfToPDFA.pdfWithDigitalSignature=PDF vsebuje digitalni podpis. To bo odstranjeno v naslednjem koraku.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_sr_LATN_RS.properties b/app/core/src/main/resources/messages_sr_LATN_RS.properties
index 25ee4bf0b6..ac6882e1dd 100644
--- a/app/core/src/main/resources/messages_sr_LATN_RS.properties
+++ b/app/core/src/main/resources/messages_sr_LATN_RS.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Izvuci slike
home.extractImages.desc=Izvlačenje svih slika iz PDF-a i kompresovanje u zip format
extractImages.tags=slika,foto,sačuvaj,arhiva,zip,zahvati,uhvati
-home.pdfToPDFA.title=PDF u PDF/A
-home.pdfToPDFA.desc=Konvertovanje PDF u PDF/A za dugoročno čuvanje
-pdfToPDFA.tags=arhiva,dugoročno,standard,konverzija,čuvanje,čuvanje
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF u Word
home.PDFToWord.desc=Konvertovanje PDF u Word formate (DOC, DOCX i ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Otključaj PDF obrazac
unlockPDFForms.submit=Otključaj
#pdfToPDFA
-pdfToPDFA.title=PDF u PDF/A
-pdfToPDFA.header=PDF u PDF/A
-pdfToPDFA.credit=Ova usluga koristi LibreOffice za konverziju u PDF/A format.
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konvertuj
-pdfToPDFA.tip=Trenutno nije podržano za više unosa istovremeno
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Izlazni format:
pdfToPDFA.pdfWithDigitalSignature=PDF sadrži digitalni potpis. Biće uklonjen u sledećem koraku.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_sv_SE.properties b/app/core/src/main/resources/messages_sv_SE.properties
index a56dfa02c5..2a02cb4a90 100644
--- a/app/core/src/main/resources/messages_sv_SE.properties
+++ b/app/core/src/main/resources/messages_sv_SE.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Extrahera bilder
home.extractImages.desc=Extraherar alla bilder från en PDF och sparar dem till zip
extractImages.tags=bild,foto,spara,arkiv,zip,fånga,ta
-home.pdfToPDFA.title=PDF till PDF/A
-home.pdfToPDFA.desc=Konvertera PDF till PDF/A för långtidslagring
-pdfToPDFA.tags=arkiv,långtids,standard,konvertering,lagring,bevarande
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF till Word
home.PDFToWord.desc=Konvertera PDF till Word-format (DOC, DOCX och ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF till PDF/A
-pdfToPDFA.header=PDF till PDF/A
-pdfToPDFA.credit=Denna tjänst använder libreoffice för PDF/A-konvertering
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Konvertera
-pdfToPDFA.tip=Fungerar för närvarande inte för flera inmatningar samtidigt
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Utdataformat
pdfToPDFA.pdfWithDigitalSignature=PDF:en innehåller en digital signatur. Denna kommer att tas bort i nästa steg.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_th_TH.properties b/app/core/src/main/resources/messages_th_TH.properties
index 0c7fafe645..bfe7b3e757 100644
--- a/app/core/src/main/resources/messages_th_TH.properties
+++ b/app/core/src/main/resources/messages_th_TH.properties
@@ -694,9 +694,9 @@ home.extractImages.title=แยกรูปภาพ
home.extractImages.desc=แยกรูปภาพทั้งหมดจาก PDF และบันทึกในรูปแบบ zip
extractImages.tags=รูปภาพ, ภาพ, บันทึก, เก็บถาวร, zip, จับ, รับ
-home.pdfToPDFA.title=PDF เป็น PDF/A
-home.pdfToPDFA.desc=แปลง PDF เป็น PDF/A สำหรับการจัดเก็บระยะยาว
-pdfToPDFA.tags=การจัดเก็บ, ระยะยาว, มาตรฐาน, การแปลง, การเก็บรักษา
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF เป็น Word
home.PDFToWord.desc=แปลง PDF เป็นรูปแบบ Word (DOC, DOCX และ ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF เป็น PDF/A
-pdfToPDFA.header=PDF เป็น PDF/A
-pdfToPDFA.credit=บริการนี้ใช้ libreoffice สำหรับการแปลง PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=แปลง
-pdfToPDFA.tip=ปัจจุบันไม่ทำงานสำหรับการป้อนข้อมูลหลายรายการพร้อมกัน
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=รูปแบบผลลัพธ์
pdfToPDFA.pdfWithDigitalSignature=PDF มีลายเซ็นดิจิทัล ซึ่งจะถูกลบในขั้นตอนถัดไป
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_tr_TR.properties b/app/core/src/main/resources/messages_tr_TR.properties
index ee77757588..f6410a94fa 100644
--- a/app/core/src/main/resources/messages_tr_TR.properties
+++ b/app/core/src/main/resources/messages_tr_TR.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Resimleri Çıkar
home.extractImages.desc=Bir PDF'ten tüm resimleri çıkarır ve bunları zip olarak kaydeder.
extractImages.tags=fotoğraf,resim,kaydet,arşiv,zip,yakala,al
-home.pdfToPDFA.title=PDF'den PDF/A'ya
-home.pdfToPDFA.desc=PDF'yi uzun vadeli saklama için PDF/A'ya dönüştürün
-pdfToPDFA.tags=arşiv,uzun vadeli,standart,dönüşüm,saklama,koruma
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF'den Word'e
home.PDFToWord.desc=PDF'yi Word formatlarına dönüştürün (DOC, DOCX ve ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=PDF Formlarının Kilidini Aç
unlockPDFForms.submit=Kaldır
#pdfToPDFA
-pdfToPDFA.title=PDF'den PDF/A'ya
-pdfToPDFA.header=PDF'den PDF/A'ya
-pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için libreoffice kullanır
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Dönüştür
-pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Çıkış formatı
pdfToPDFA.pdfWithDigitalSignature=PDF dijital imza içeriyor. Bu bir sonraki adımda kaldırılacak.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_uk_UA.properties b/app/core/src/main/resources/messages_uk_UA.properties
index da59001a2f..8ed1ab8d57 100644
--- a/app/core/src/main/resources/messages_uk_UA.properties
+++ b/app/core/src/main/resources/messages_uk_UA.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Витягнути зображення
home.extractImages.desc=Витягує всі зображення з PDF і зберігає їх у zip
extractImages.tags=зображення,фото,збереження,архів,zip,захоплення,захоплення
-home.pdfToPDFA.title=PDF в PDF/A
-home.pdfToPDFA.desc=Перетворення PDF в PDF/A для довготривалого зберігання
-pdfToPDFA.tags=архів,довгостроковий,стандартний,конверсія,зберігання,консервація
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF в Word
home.PDFToWord.desc=Перетворення PDF в формати Word (DOC, DOCX та ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF в PDF/A
-pdfToPDFA.header=PDF в PDF/A
-pdfToPDFA.credit=Цей сервіс використовує libreoffice для перетворення у формат PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Конвертувати
-pdfToPDFA.tip=Наразі не працює для кількох вхідних файлів одночасно
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Вихідний формат
pdfToPDFA.pdfWithDigitalSignature=Цей PDF документ має цифровий підпис. Цей підпис буде видалений у наступному кроці.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_vi_VN.properties b/app/core/src/main/resources/messages_vi_VN.properties
index 75aaf6b27a..e7bff3af6f 100644
--- a/app/core/src/main/resources/messages_vi_VN.properties
+++ b/app/core/src/main/resources/messages_vi_VN.properties
@@ -694,9 +694,9 @@ home.extractImages.title=Trích xuất hình ảnh
home.extractImages.desc=Trích xuất tất cả hình ảnh từ PDF và lưu chúng vào tệp zip
extractImages.tags=hình ảnh,ảnh,lưu,lưu trữ,zip,chụp,lấy
-home.pdfToPDFA.title=PDF sang PDF/A
-home.pdfToPDFA.desc=Chuyển đổi PDF sang PDF/A để lưu trữ lâu dài
-pdfToPDFA.tags=lưu trữ,dài hạn,tiêu chuẩn,chuyển đổi,lưu trữ,bảo quản
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF sang Word
home.PDFToWord.desc=Chuyển đổi PDF sang các định dạng Word (DOC, DOCX và ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=Unlock PDF Forms
unlockPDFForms.submit=Remove
#pdfToPDFA
-pdfToPDFA.title=PDF sang PDF/A
-pdfToPDFA.header=PDF sang PDF/A
-pdfToPDFA.credit=Dịch vụ này sử dụng libreoffice để chuyển đổi PDF/A
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=Chuyển đổi
-pdfToPDFA.tip=Hiện tại không hoạt động với nhiều đầu vào cùng lúc
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=Định dạng đầu ra
pdfToPDFA.pdfWithDigitalSignature=PDF chứa chữ ký số. Điều này sẽ bị xóa trong bước tiếp theo.
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_zh_CN.properties b/app/core/src/main/resources/messages_zh_CN.properties
index cd6596b3c9..67bd12e804 100644
--- a/app/core/src/main/resources/messages_zh_CN.properties
+++ b/app/core/src/main/resources/messages_zh_CN.properties
@@ -694,9 +694,9 @@ home.extractImages.title=提取图像
home.extractImages.desc=从 PDF 中提取所有图像并保存到压缩包中。
extractImages.tags=图片、照片、保存、归档、压缩包、截取、抓取
-home.pdfToPDFA.title=PDF 转 PDF/A
-home.pdfToPDFA.desc=将 PDF 转换为 PDF/A 以进行长期保存。
-pdfToPDFA.tags=归档、长期、标准、转换、存储、保存
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF 转 Word
home.PDFToWord.desc=将PDF转换为Word格式(DOC、DOCX和ODT)。
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=解锁 PDF 表单
unlockPDFForms.submit=移除
#pdfToPDFA
-pdfToPDFA.title=PDF 转 PDF/A
-pdfToPDFA.header=将 PDF 转换为 PDF/A
-pdfToPDFA.credit=此服务使用 libreoffice 进行 PDF/A 转换
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=转换
-pdfToPDFA.tip=目前不支持上传多个
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=输出格式
pdfToPDFA.pdfWithDigitalSignature=该PDF包含数字签名,下一步将移除该签名。
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/messages_zh_TW.properties b/app/core/src/main/resources/messages_zh_TW.properties
index 4e3384a554..5d8fc66df8 100644
--- a/app/core/src/main/resources/messages_zh_TW.properties
+++ b/app/core/src/main/resources/messages_zh_TW.properties
@@ -694,9 +694,9 @@ home.extractImages.title=提取圖片
home.extractImages.desc=從 PDF 中提取所有圖片並將它們儲存到壓縮檔中
extractImages.tags=圖片,照片,儲存,存檔,壓縮檔,捕獲,抓取
-home.pdfToPDFA.title=PDF 轉 PDF/A
-home.pdfToPDFA.desc=將 PDF 轉換為長期儲存的 PDF/A
-pdfToPDFA.tags=存檔,長期,標準,轉換,儲存,保存
+home.pdfToPDFA.title=PDF to PDF/A & PDF/X
+home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage or PDF/X for print production
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation,print,pdf-x
home.PDFToWord.title=PDF 轉 Word
home.PDFToWord.desc=將 PDF 轉換為 Word 格式(DOC、DOCX 和 ODT)
@@ -1619,13 +1619,15 @@ unlockPDFForms.header=解鎖 PDF 表單
unlockPDFForms.submit=移除
#pdfToPDFA
-pdfToPDFA.title=PDF 轉 PDF/A
-pdfToPDFA.header=PDF 轉 PDF/A
-pdfToPDFA.credit=此服務使用 LibreOffice 進行 PDF/A 轉換
+pdfToPDFA.title=PDF to PDF/A or PDF/X
+pdfToPDFA.header=PDF to PDF/A or PDF/X
+pdfToPDFA.credit=This service uses Ghostscript (preferred) or LibreOffice for PDF/A conversion, and Ghostscript for PDF/X conversion
pdfToPDFA.submit=轉換
-pdfToPDFA.tip=目前不支援上傳多個檔案
+pdfToPDFA.tip=Convert PDF to PDF/A (long-term archiving) or PDF/X (print production)
pdfToPDFA.outputFormat=輸出格式
pdfToPDFA.pdfWithDigitalSignature=此 PDF 的憑證簽章將在下一步被移除
+pdfToPDFA.pdfaFormats=PDF/A Formats (Long-term Archiving)
+pdfToPDFA.pdfxFormats=PDF/X Formats (Print Production)
#PDFToWord
diff --git a/app/core/src/main/resources/templates/convert/pdf-to-pdfa.html b/app/core/src/main/resources/templates/convert/pdf-to-pdfa.html
index 33c07acb9d..5b44ff5b62 100644
--- a/app/core/src/main/resources/templates/convert/pdf-to-pdfa.html
+++ b/app/core/src/main/resources/templates/convert/pdf-to-pdfa.html
@@ -23,8 +23,16 @@