Compare commits

...

14 Commits

Author SHA1 Message Date
dependabot[bot] de208f4f65
Bump org.springdoc:springdoc-openapi-starter-webmvc-ui
Bumps [org.springdoc:springdoc-openapi-starter-webmvc-ui](https://github.com/springdoc/springdoc-openapi) from 2.2.0 to 2.5.0.
- [Release notes](https://github.com/springdoc/springdoc-openapi/releases)
- [Changelog](https://github.com/springdoc/springdoc-openapi/blob/main/CHANGELOG.md)
- [Commits](https://github.com/springdoc/springdoc-openapi/compare/v2.2.0...v2.5.0)

---
updated-dependencies:
- dependency-name: org.springdoc:springdoc-openapi-starter-webmvc-ui
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-27 10:04:49 +00:00
github-actions[bot] 4fea8d10f8
💾 Update Version (#1130)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-27 11:04:28 +01:00
Anthony Stirling 8c9d6f7b66
Custom HTML support #355 (#1129)
* test

* settings

* version
2024-04-27 11:03:57 +01:00
Anthony Stirling 30444fc9bb
commit (#1128)
* commit

* formatting
2024-04-26 23:27:40 +01:00
Han 70349d642b
Update messages_tr_TR.properties (#1126)
* Update messages_tr_TR.properties

* Update messages_tr_TR.properties
2024-04-26 19:37:09 +01:00
albanobattistella afaec64afd
Update messages_it_IT.properties (#1120) 2024-04-24 21:57:56 +01:00
github-actions[bot] 2a9fdff605
📝 Update README: Translation Progress Table (#1119)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-24 19:59:53 +01:00
Anthony Stirling 34c7ee46a0 lang adds 2024-04-24 19:59:01 +01:00
phfuh 5ee702f364
PDF to PDF/A language files (#1118)
* Update messages_en_GB.properties

* Update messages_en_US.properties

* Update messages_de_DE.properties
2024-04-24 19:56:35 +01:00
Ludy 1b5d21a22e
Bugfix: Login page shows wrong selected country flag/language (#1117)
Closes #1116
2024-04-24 09:10:16 +01:00
Anthony Stirling c3e5157dee
Delete CNAME 2024-04-23 22:35:21 +01:00
Anthony Stirling 6d859e4c25
Create CNAME 2024-04-23 22:34:29 +01:00
diemade 95a9aca5b5
Update CONTRIBUTING.md (#1115)
adding a chapter on how to edit Docs
2024-04-23 22:32:12 +01:00
github-actions[bot] 4c8f582c56
💾 Update Version (#1108)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-21 23:08:06 +01:00
41 changed files with 227 additions and 49 deletions

View File

@ -27,6 +27,10 @@ Please make sure your Pull Request adheres to the following guidelines:
If you would like to add or modify a translation, please see [How to add new languages to Stirling-PDF](HowToAddNewLanguage.md). Also, please create a Pull Request so others can use it!
## Docs
Documentation for Stirling-PDF is handled in a seperate repository. Please see [Docs repository](https://github.com/Stirling-Tools/Stirling-Tools.github.io) or use "edit this page"-button at the bottom of each page at [https://stirlingtools.com/docs/](https://stirlingtools.com/docs/).
## Fixing Bugs or Adding a New Feature
First, make sure you've read the section [Pull Requests](#pull-requests).

View File

@ -182,12 +182,12 @@ Stirling PDF currently supports 27!
| Basque (Euskara) (eu_ES) | ![75%](https://geps.dev/progress/75) |
| Japanese (日本語) (ja_JP) | ![93%](https://geps.dev/progress/93) |
| Dutch (Nederlands) (nl_NL) | ![91%](https://geps.dev/progress/91) |
| Greek (Ελληνικά) (el_GR) | ![92%](https://geps.dev/progress/92) |
| Greek (Ελληνικά) (el_GR) | ![91%](https://geps.dev/progress/91) |
| Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![87%](https://geps.dev/progress/87) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![86%](https://geps.dev/progress/86) |
| Hindi (हिंदी) (hi_IN) | ![87%](https://geps.dev/progress/87) |
| Hungarian (Magyar) (hu_HU) | ![86%](https://geps.dev/progress/86) |
| Bulgarian (Български) (bg_BG) | ![82%](https://geps.dev/progress/82) |
| Bulgarian (Български) (bg_BG) | ![81%](https://geps.dev/progress/81) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![88%](https://geps.dev/progress/88) |
| Ukrainian (Українська) (uk_UA) | ![93%](https://geps.dev/progress/93) |
@ -201,7 +201,7 @@ Stirling PDF allows easy customization of the app.
Includes things like
- Custom application name
- Custom slogans, icons, images, and even custom HTML (via file overrides)
- Custom slogans, icons, HTML, images CSS etc (via file overrides)
There are two options for this, either using the generated settings file ``settings.yml``
This file is located in the ``/configs`` directory and follows standard YAML formatting
@ -229,6 +229,7 @@ system:
customStaticFilePath: '/customFiles/static/' # Directory path for custom static files
showUpdate: true # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
#ui:
# appName: exampleAppName # Application's visible name

View File

@ -12,7 +12,7 @@ plugins {
import com.github.jk1.license.render.*
group = 'stirling.software'
version = '0.23.0'
version = '0.23.1'
sourceCompatibility = '17'
repositories {
@ -128,7 +128,7 @@ dependencies {
// implementation 'com.twelvemonkeys.imageio:imageio-xwd:3.10.1'
implementation 'commons-io:commons-io:2.15.1'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
//general PDF

View File

@ -1,5 +1,5 @@
apiVersion: v2
appVersion: 0.22.8
appVersion: 0.23.1
description: locally hosted web application that allows you to perform various operations
on PDF files
home: https://github.com/Stirling-Tools/Stirling-PDF

View File

@ -7,18 +7,34 @@ import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.spring6.SpringTemplateEngine;
import stirling.software.SPDF.model.ApplicationProperties;
@Configuration
@Lazy
public class AppConfig {
@Autowired ApplicationProperties applicationProperties;
@Bean
@ConditionalOnProperty(
name = "system.customHTMLFiles",
havingValue = "true",
matchIfMissing = false)
public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(new FileFallbackTemplateResolver(resourceLoader));
return templateEngine;
}
@Bean(name = "loginEnabled")
public boolean loginEnabled() {
return applicationProperties.getSecurity().getEnableLogin();

View File

@ -0,0 +1,48 @@
package stirling.software.SPDF.config;
import java.io.IOException;
import java.util.Map;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
import org.thymeleaf.templateresource.FileTemplateResource;
import org.thymeleaf.templateresource.ITemplateResource;
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
private final ResourceLoader resourceLoader;
public FileFallbackTemplateResolver(ResourceLoader resourceLoader) {
super();
this.resourceLoader = resourceLoader;
setSuffix(".html");
}
// Note this does not work in local IDE, Prod jar only.
@Override
protected ITemplateResource computeTemplateResource(
IEngineConfiguration configuration,
String ownerTemplate,
String template,
String resourceName,
String characterEncoding,
Map<String, Object> templateResolutionAttributes) {
Resource resource =
resourceLoader.getResource("file:./customFiles/templates/" + resourceName);
try {
if (resource.exists() && resource.isReadable()) {
return new FileTemplateResource(resource.getFile().getPath(), characterEncoding);
}
} catch (IOException e) {
}
return new ClassLoaderTemplateResource(
Thread.currentThread().getContextClassLoader(),
"classpath:/templates/" + resourceName,
characterEncoding);
}
}

View File

@ -1,10 +1,14 @@
package stirling.software.SPDF.controller.api.misc;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
@ -33,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -47,12 +52,13 @@ public class FakeScanControllerWIP {
private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
//TODO
//@PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
//@Operation(
// summary = "Repair a PDF file",
// description =
// "This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response.")
// TODO finish
@PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
@Hidden
@Operation(
summary = "Repair a PDF file",
description =
"This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response.")
public ResponseEntity<byte[]> fakeScan(@ModelAttribute PDFFile request) throws IOException {
MultipartFile inputFile = request.getFileInput();
@ -91,18 +97,19 @@ public class FakeScanControllerWIP {
public BufferedImage processImage(BufferedImage image) {
// Rotation
image = rotate(image);
// image = softenEdges(image, 5);
image = applyGaussianBlur(image, 0.5);
addGaussianNoise(image, 0.25);
image = linearStretch(image);
image = softenEdges(image, 50);
image = rotate(image, 1);
image = applyGaussianBlur(image, 0.5);
addGaussianNoise(image, 0.5);
image = linearStretch(image);
addDustAndHairs(image, 3);
return image;
}
private BufferedImage rotate(BufferedImage image) {
private BufferedImage rotate(BufferedImage image, double rotation) {
double rotationRequired = Math.toRadians(1.0);
double rotationRequired = Math.toRadians(rotation);
double locationX = image.getWidth() / 2;
double locationY = image.getHeight() / 2;
AffineTransform tx =
@ -144,39 +151,106 @@ public class FakeScanControllerWIP {
BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(image, 0, 0, null);
g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(
new GradientPaint(
0, 0, new Color(0, 0, 0, 1f), 0, featherRadius, new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, width, featherRadius); // top edge
// Top edge
g2.setPaint(
new GradientPaint(
0,
height - featherRadius,
0,
new Color(0, 0, 0, 1f),
0,
featherRadius * 2,
new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, width, featherRadius);
// Bottom edge
g2.setPaint(
new GradientPaint(
0,
height - featherRadius * 2,
new Color(0, 0, 0, 0f),
0,
height,
new Color(0, 0, 0, 1f)));
g2.fillRect(0, height - featherRadius, width, featherRadius); // bottom edge
g2.fillRect(0, height - featherRadius, width, featherRadius);
// Left edge
g2.setPaint(
new GradientPaint(
0, 0, new Color(0, 0, 0, 1f), featherRadius, 0, new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, featherRadius, height); // left edge
0,
0,
new Color(0, 0, 0, 1f),
featherRadius * 2,
0,
new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, featherRadius, height);
// Right edge
g2.setPaint(
new GradientPaint(
width - featherRadius,
width - featherRadius * 2,
0,
new Color(0, 0, 0, 0f),
width,
0,
new Color(0, 0, 0, 1f)));
g2.fillRect(width - featherRadius, 0, featherRadius, height); // right edge
g2.fillRect(width - featherRadius, 0, featherRadius, height);
g2.dispose();
return output;
}
private void addDustAndHairs(BufferedImage image, float intensity) {
int width = image.getWidth();
int height = image.getHeight();
Graphics2D g2d = image.createGraphics();
Random random = new SecureRandom();
// Set rendering hints for better quality
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Calculate the number of artifacts based on intensity
int numSpots = (int) (intensity * 10);
int numHairs = (int) (intensity * 20);
// Add spots with more variable sizes
g2d.setColor(new Color(100, 100, 100, 50)); // Semi-transparent gray
for (int i = 0; i < numSpots; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int ovalSize = 1 + random.nextInt(3); // Base size + variable component
if (random.nextFloat() > 0.9) {
// 10% chance to get a larger spot
ovalSize += random.nextInt(3);
}
g2d.fill(new Ellipse2D.Double(x, y, ovalSize, ovalSize));
}
// Add hairs
g2d.setStroke(new BasicStroke(0.5f)); // Thin stroke for hairs
g2d.setColor(new Color(80, 80, 80, 40)); // Slightly lighter and more transparent
for (int i = 0; i < numHairs; i++) {
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = x1 + random.nextInt(20) - 10; // Random length and direction
int y2 = y1 + random.nextInt(20) - 10;
Path2D.Double hair = new Path2D.Double();
hair.moveTo(x1, y1);
hair.curveTo(x1, y1, (x1 + x2) / 2, (y1 + y2) / 2, x2, y2);
g2d.draw(hair);
}
g2d.dispose();
}
private void addGaussianNoise(BufferedImage image, double strength) {
Random rand = new SecureRandom();
int width = image.getWidth();

View File

@ -20,12 +20,10 @@ import org.apache.pdfbox.printing.PDFPageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.PrintFileRequest;
@ -35,12 +33,13 @@ import stirling.software.SPDF.model.api.misc.PrintFileRequest;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class PrintFileController {
//TODO
//@PostMapping(value = "/print-file", consumes = "multipart/form-data")
//@Operation(
// TODO
// @PostMapping(value = "/print-file", consumes = "multipart/form-data")
// @Operation(
// summary = "Prints PDF/Image file to a set printer",
// description =
// "Input of PDF or Image along with a printer name/URL/IP to match against to send it to (Fire and forget) Input:Any Output:N/A Type:SISO")
// "Input of PDF or Image along with a printer name/URL/IP to match against to
// send it to (Fire and forget) Input:Any Output:N/A Type:SISO")
public ResponseEntity<String> printFile(@ModelAttribute PrintFileRequest request)
throws IOException {
MultipartFile file = request.getFileInput();

View File

@ -212,6 +212,15 @@ public class ApplicationProperties {
private Integer maxFileSize;
private boolean showUpdate;
private Boolean showUpdateOnlyAdmin;
private boolean customHTMLFiles;
public boolean isCustomHTMLFiles() {
return customHTMLFiles;
}
public void setCustomHTMLFiles(boolean customHTMLFiles) {
this.customHTMLFiles = customHTMLFiles;
}
public boolean getShowUpdateOnlyAdmin() {
return showUpdateOnlyAdmin;

View File

@ -342,8 +342,6 @@ public class PdfUtils {
boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4;
System.out.println(fitOption);
if (autoRotate && imageIsLandscape) {
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
}

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF إلى PDF / A
pdfToPDFA.credit=تستخدم هذه الخدمة OCRmyPDF لتحويل PDF / A.
pdfToPDFA.submit=تحويل
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF към PDF/A
pdfToPDFA.credit=Тази услуга използва OCRmyPDF за PDF/A преобразуване.
pdfToPDFA.submit=Преобразуване
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Utilitza OCRmyPDF per la conversió a PDF/A
pdfToPDFA.submit=Converteix
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF zu PDF/A
pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung
pdfToPDFA.submit=Konvertieren
pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
pdfToPDFA.outputFormat=Ausgabeformat
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF σε PDF/A
pdfToPDFA.credit=Αυτή η υπηρεσία χρησιμοποιεί OCRmyPDF για PDF/A μετατροπή
pdfToPDFA.submit=Μετατροπή
pdfToPDFA.tip=Προς το παρόν δεν λειτουργεί για πολλαπλές εισόδους ταυτόχρονα
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A
pdfToPDFA.submit=Convertir
pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDFa PDF/A bihurtu
pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko
pdfToPDFA.submit=Bihurtu
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF en PDF/A
pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion en PDF/A.
pdfToPDFA.submit=Convertir
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF से PDF/A में
pdfToPDFA.credit=इस सेवा में PDF/A परिवर्तन के लिए OCRmyPDF का उपयोग किया जाता है।
pdfToPDFA.submit=परिवर्तित करें
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF >> PDF/A
pdfToPDFA.credit=Ez a szolgáltatás az OCRmyPDF-t használja a PDF/A konverzióhoz
pdfToPDFA.submit=Konvertálás
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF ke PDF/A
pdfToPDFA.credit=Layanan ini menggunakan OCRmyPDF untuk konversi PDF/A.
pdfToPDFA.submit=Konversi
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -646,7 +646,7 @@ removeBlanks.submit=Rimuovi
#removeAnnotations
removeAnnotations.title=Rimuovi Annotazioni
removeAnnotations.header=Remuovi Annotazioni
removeAnnotations.header=Rimuovi Annotazioni
removeAnnotations.submit=Rimuovi
@ -941,6 +941,7 @@ pdfToPDFA.header=Da PDF a PDF/A
pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A.
pdfToPDFA.submit=Converti
pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDFをPDF/Aに変換
pdfToPDFA.credit=本サービスはPDF/Aの変換にOCRmyPDFを使用しています。
pdfToPDFA.submit=変換
pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF 문서를 PDF/A로 변환
pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 OCRmyPDF 문서를 사용합니다.
pdfToPDFA.submit=변환
pdfToPDFA.tip=현재 한 번에 여러 입력에 대해 작동하지 않습니다.
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF naar PDF/A
pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
pdfToPDFA.submit=Converteren
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF na PDF/A
pdfToPDFA.credit=Ta usługa używa OCRmyPDF do konwersji PDF/A
pdfToPDFA.submit=Konwertuj
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF para PDF/A
pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
pdfToPDFA.submit=Converter
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF para PDF/A
pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
pdfToPDFA.submit=Converter
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF către PDF/A
pdfToPDFA.credit=Acest serviciu utilizează OCRmyPDF pentru conversia în PDF/A
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF в PDF/A
pdfToPDFA.credit=Этот сервис использует OCRmyPDF для преобразования PDF/A
pdfToPDFA.submit=Конвертировать
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF u PDF/A
pdfToPDFA.credit=Ova usluga koristi OCRmyPDF za konverziju u PDF/A format
pdfToPDFA.submit=Konvertuj
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF till PDF/A
pdfToPDFA.credit=Denna tjänst använder OCRmyPDF för PDF/A-konvertering
pdfToPDFA.submit=Konvertera
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -66,7 +66,7 @@ seeDockerHub=Docker Hub'a bakın
visitGithub=Github Deposunu Ziyaret Edin
donate=Bağış Yapın
color=Renk
sponsor=Sponsor
sponsor=Bağış
@ -112,7 +112,7 @@ navbar.settings=Ayarlar
#############
settings.title=Ayarlar
settings.update=Güncelleme mevcut
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.updateAvailable={0} mevcut kurulu sürümdür. Yeni bir sürüm ({1}) mevcuttur.
settings.appVersion=Uygulama Sürümü:
settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için):
settings.downloadOption.1=Aynı pencerede aç
@ -666,7 +666,7 @@ BookToPDF.submit=Dönüştür
#PDFToBook
PDFToBook.title=PDF'den Kitaba
PDFToBook.header=PDF'den Kitaba
PDFToBook.selectText.1=Format
PDFToBook.selectText.1=Format biçimi
PDFToBook.credit=Kalibre Kullanır
PDFToBook.submit=Dönüştür
@ -941,6 +941,7 @@ pdfToPDFA.header=PDF'den PDF/A'ya
pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır
pdfToPDFA.submit=Dönüştür
pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
pdfToPDFA.outputFormat=Çıkış formatı
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF в PDF/A
pdfToPDFA.credit=Цей сервіс використовує OCRmyPDF для перетворення у формат PDF/A
pdfToPDFA.submit=Конвертувати
pdfToPDFA.tip=Наразі не працює для кількох вхідних файлів одночасно
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF转换为PDF/A
pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换
pdfToPDFA.submit=转换
pdfToPDFA.tip=目前不支持上传多个
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -941,6 +941,7 @@ pdfToPDFA.header=PDF 轉 PDF/A
pdfToPDFA.credit=此服務使用 OCRmyPDF 進行 PDF/A 轉換
pdfToPDFA.submit=轉換
pdfToPDFA.tip=目前不支援上傳多個
pdfToPDFA.outputFormat=Output format
#PDFToWord

View File

@ -14,7 +14,8 @@ system:
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: true # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # Enable to have files placed in /customFiles/templates override the existing template html files
#ui:
# appName: exampleAppName # Application's visible name
# homeDescription: I am a description # Short description or tagline shown on homepage.

View File

@ -17,20 +17,20 @@
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto flex-nowrap">
<li class="nav-item">
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('multi-tool')}">
<a class="nav-link" href="#" th:href="@{multi-tool}" th:classappend="${currentPage}=='multi-tool' ? 'active' : ''" th:title="#{home.multiTool.desc}">
<img class="icon" src="images/tools.svg" alt="icon">
<span class="icon-text" th:text="#{home.multiTool.title}"></span>
</a>
</li>
<li class="nav-item nav-item-separator"></li>
<li class="nav-item">
<li th:if="${@endpointConfiguration.isEndpointEnabled('multi-tool')}" class="nav-item nav-item-separator"></li>
<li th:if="${@endpointConfiguration.isEndpointEnabled('pipeline')}" class="nav-item">
<a class="nav-link" href="#" th:href="@{pipeline}" th:classappend="${currentPage}=='pipeline' ? 'active' : ''" th:title="#{home.pipeline.desc}">
<img class="icon" src="images/pipeline.svg" alt="icon">
<span class="icon-text" th:text="#{home.pipeline.title}"></span>
</a>
</li>
<li class="nav-item nav-item-separator"></li>
<li th:if="${@endpointConfiguration.isEndpointEnabled('pipeline')}" class="nav-item nav-item-separator"></li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' OR ${currentPage}=='auto-split-pdf' OR ${currentPage}=='extract-page' OR ${currentPage}=='pdf-to-single-page' ? 'active' : ''">
<a class="nav-link dropdown-toggle" id="navbarDropdown-1" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img class="icon" src="images/file-earmark-pdf.svg" alt="icon">
@ -211,7 +211,7 @@
<span id="zipThresholdValue" class="ms-2"></span>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input"id="boredWaiting" th:title="#{settings.bored.help}">
<input type="checkbox" class="form-check-input" id="boredWaiting" th:title="#{settings.bored.help}">
<label class="form-check-label" for="boredWaiting" th:text="#{bored}"></label>
</div>
<div class="mb-3 form-check">

View File

@ -52,7 +52,7 @@
document.addEventListener('DOMContentLoaded', function() {
const defaultLocale = document.documentElement.getAttribute('language') || 'en_GB';
const defaultLocale = document.documentElement.getAttribute('data-language') || 'en_GB';
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
const currentURL = new URL(window.location.href);