Cleanup-conversion-translations (#5906)

Co-authored-by: Anthony Stirling <[email protected]>
This commit is contained in:
ConnorYoh
2026-03-12 20:23:13 +00:00
committed by GitHub
co-authored by Anthony Stirling
parent b68b406a2a
commit 0545c3f997
14 changed files with 68 additions and 57 deletions
@@ -341,7 +341,8 @@ public class EmlProcessingUtils {
} }
private String getFallbackStyles() { private String getFallbackStyles() {
return """ return
"""
/* Minimal fallback - main CSS resource failed to load */ /* Minimal fallback - main CSS resource failed to load */
body { body {
font-family: var(--font-family, Helvetica, sans-serif); font-family: var(--font-family, Helvetica, sans-serif);
@@ -178,7 +178,8 @@ public class ReactRoutingController {
String escapedBaseUrlJs = JavaScriptUtils.javaScriptEscape(baseUrl); String escapedBaseUrlJs = JavaScriptUtils.javaScriptEscape(baseUrl);
String serverUrl = "(window.location.origin + '" + escapedBaseUrlJs + "')"; String serverUrl = "(window.location.origin + '" + escapedBaseUrlJs + "')";
return """ return
"""
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
@@ -237,7 +238,8 @@ public class ReactRoutingController {
String escapedBaseUrlJs = JavaScriptUtils.javaScriptEscape(baseUrl); String escapedBaseUrlJs = JavaScriptUtils.javaScriptEscape(baseUrl);
String serverUrl = "(window.location.origin + '" + escapedBaseUrlJs + "')"; String serverUrl = "(window.location.origin + '" + escapedBaseUrlJs + "')";
return """ return
"""
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
@@ -583,7 +583,8 @@ public class PdfJsonFallbackFontService {
return switch (script) { return switch (script) {
// HAN script is used by both Simplified and Traditional Chinese // HAN script is used by both Simplified and Traditional Chinese
// Default to Simplified (mainland China, 1.4B speakers) as it's more common // Default to Simplified (mainland China, 1.4B speakers) as it's more common
// Traditional Chinese PDFs are detected via font name aliases (MingLiU, PMingLiU, etc.) // Traditional Chinese PDFs are detected via font name aliases (MingLiU, PMingLiU,
// etc.)
case HAN -> FALLBACK_FONT_CJK_ID; case HAN -> FALLBACK_FONT_CJK_ID;
case HIRAGANA, KATAKANA -> FALLBACK_FONT_JP_ID; case HIRAGANA, KATAKANA -> FALLBACK_FONT_JP_ID;
case HANGUL -> FALLBACK_FONT_KR_ID; case HANGUL -> FALLBACK_FONT_KR_ID;
@@ -21,8 +21,7 @@ class ApiEndpointTest {
return postNodeWithParams(description, true, names); return postNodeWithParams(description, true, names);
} }
private JsonNode postNodeWithParams( private JsonNode postNodeWithParams(String description, boolean required, String... names) {
String description, boolean required, String... names) {
ObjectNode post = mapper.createObjectNode(); ObjectNode post = mapper.createObjectNode();
post.put("description", description); post.put("description", description);
ArrayNode params = mapper.createArrayNode(); ArrayNode params = mapper.createArrayNode();
@@ -103,7 +103,9 @@ class LanguageServiceBasicTest {
// Verify filtering by restrictions // Verify filtering by restrictions
assertTrue(supportedLanguages.contains("en_US"), "Allowed language should be included"); assertTrue(supportedLanguages.contains("en_US"), "Allowed language should be included");
assertTrue(supportedLanguages.contains("fr_FR"), "Allowed language should be included"); assertTrue(supportedLanguages.contains("fr_FR"), "Allowed language should be included");
assertFalse(supportedLanguages.contains("en_GB"), "en_GB should NOT be included when not in whitelist"); assertFalse(
supportedLanguages.contains("en_GB"),
"en_GB should NOT be included when not in whitelist");
assertFalse(supportedLanguages.contains("de_DE"), "Restricted language should be excluded"); assertFalse(supportedLanguages.contains("de_DE"), "Restricted language should be excluded");
} }
@@ -84,11 +84,13 @@ class LanguageServiceTest {
// Verify // Verify
assertEquals( assertEquals(
allowedLanguages, allowedLanguages, supportedLanguages, "Should return only whitelisted languages");
supportedLanguages, assertFalse(
"Should return only whitelisted languages"); supportedLanguages.contains("en_GB"),
assertFalse(supportedLanguages.contains("en_GB"), "en_GB should NOT be included when not in whitelist"); "en_GB should NOT be included when not in whitelist");
assertFalse(supportedLanguages.contains("de_DE"), "de_DE should NOT be included when not in whitelist"); assertFalse(
supportedLanguages.contains("de_DE"),
"de_DE should NOT be included when not in whitelist");
} }
@Test @Test
@@ -269,7 +269,8 @@ public class EmailService {
String passwordSection = String passwordSection =
newPassword == null newPassword == null
? "" ? ""
: """ :
"""
<div style=\"background-color: #f8f9fa; border-left: 4px solid #007bff; padding: 15px; margin: 20px 0; border-radius: 4px;\"> <div style=\"background-color: #f8f9fa; border-left: 4px solid #007bff; padding: 15px; margin: 20px 0; border-radius: 4px;\">
<p style=\"margin: 0;\"><strong>Temporary Password:</strong> %s</p> <p style=\"margin: 0;\"><strong>Temporary Password:</strong> %s</p>
</div> </div>
+1 -1
View File
@@ -78,7 +78,7 @@ springBoot {
allprojects { allprojects {
group = 'stirling.software' group = 'stirling.software'
version = '2.7.0' version = '2.7.1'
configurations.configureEach { configurations.configureEach {
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat" exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
+9 -24
View File
@@ -2759,6 +2759,15 @@ webOptions = "Web to PDF Options"
wordDoc = "Word Document" wordDoc = "Word Document"
wordDocExt = "Word Document (.docx)" wordDocExt = "Word Document (.docx)"
zoomLevel = "Zoom Level" zoomLevel = "Zoom Level"
cbrToPdf = "CBR → PDF"
cbzToPdf = "CBZ → PDF"
ebookToPdf = "eBook → PDF"
emlToPdf = "Email → PDF"
fileToPdf = "Office/Document → PDF"
pdfToCbr = "PDF → CBR"
pdfToCbz = "PDF → CBZ"
pdfToEpub = "PDF → EPUB"
svgToPdf = "SVG → PDF"
[convert.ebookOptions] [convert.ebookOptions]
ebookOptions = "eBook to PDF Options" ebookOptions = "eBook to PDF Options"
@@ -5822,30 +5831,6 @@ showTools = "View unavailable tools ▾"
title = "Your Stirling-PDF server is unreachable" title = "Your Stirling-PDF server is unreachable"
toolNotAvailableLocally = "Your Stirling-PDF server is offline and \"{{endpoint}}\" is not available on the local backend." toolNotAvailableLocally = "Your Stirling-PDF server is offline and \"{{endpoint}}\" is not available on the local backend."
[selfHosted.offline.conversionTypes]
cbr-to-pdf = "CBR → PDF"
cbz-to-pdf = "CBZ → PDF"
eml-to-pdf = "Email → PDF"
ebook-to-pdf = "eBook → PDF"
file-to-pdf = "Office/Document → PDF"
html-to-pdf = "HTML → PDF"
img-to-pdf = "Image → PDF"
markdown-to-pdf = "Markdown → PDF"
pdf-to-cbr = "PDF → CBR"
pdf-to-cbz = "PDF → CBZ"
pdf-to-csv = "PDF → CSV"
pdf-to-epub = "PDF → EPUB"
pdf-to-html = "PDF → HTML"
pdf-to-img = "PDF → Image"
pdf-to-markdown = "PDF → Markdown"
pdf-to-pdfa = "PDF → PDF/A"
pdf-to-presentation = "PDF → Presentation"
pdf-to-text = "PDF → Text"
pdf-to-word = "PDF → Word"
pdf-to-xml = "PDF → XML"
pdf-to-xlsx = "PDF → XLSX"
svg-to-pdf = "SVG → PDF"
[session] [session]
expired = "Your session has expired. Please refresh the page and try again." expired = "Your session has expired. Please refresh the page and try again."
refreshPage = "Refresh Page" refreshPage = "Refresh Page"
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
"productName": "Stirling-PDF", "productName": "Stirling-PDF",
"version": "2.6.0", "version": "2.7.1",
"identifier": "stirling.pdf.dev", "identifier": "stirling.pdf.dev",
"build": { "build": {
"frontendDist": "../dist", "frontendDist": "../dist",
@@ -71,6 +71,31 @@ export const ENDPOINT_NAMES = {
'text-editor-pdf': 'text-editor-to-pdf' 'text-editor-pdf': 'text-editor-to-pdf'
} as const; } as const;
/** Maps conversion endpoint → [i18n key, English fallback] for display names */
export const ENDPOINT_I18N: Record<string, [string, string]> = {
'img-to-pdf': ['imageToPDF.header', 'Image → PDF'],
'html-to-pdf': ['HTMLToPDF.header', 'HTML → PDF'],
'markdown-to-pdf': ['MarkdownToPDF.header', 'Markdown → PDF'],
'pdf-to-img': ['pdfToImage.title', 'PDF → Image'],
'pdf-to-word': ['PDFToWord.header', 'PDF → Word'],
'pdf-to-presentation': ['PDFToPresentation.header', 'PDF → Presentation'],
'pdf-to-text': ['PDFToText.header', 'PDF → Text'],
'pdf-to-csv': ['PDFToCSV.header', 'PDF → CSV'],
'pdf-to-xlsx': ['PDFToXLSX.header', 'PDF → Excel'],
'pdf-to-markdown': ['PDFToMarkdown.header', 'PDF → Markdown'],
'pdf-to-html': ['PDFToHTML.header', 'PDF → HTML'],
'pdf-to-xml': ['PDFToXML.header', 'PDF → XML'],
'pdf-to-pdfa': ['pdfToPDFA.header', 'PDF → PDF/A'],
'file-to-pdf': ['convert.fileToPdf', 'Office/Document → PDF'],
'cbr-to-pdf': ['convert.cbrToPdf', 'CBR → PDF'],
'cbz-to-pdf': ['convert.cbzToPdf', 'CBZ → PDF'],
'eml-to-pdf': ['convert.emlToPdf', 'Email → PDF'],
'ebook-to-pdf': ['convert.ebookToPdf', 'eBook → PDF'],
'svg-to-pdf': ['convert.svgToPdf', 'SVG → PDF'],
'pdf-to-cbr': ['convert.pdfToCbr', 'PDF → CBR'],
'pdf-to-cbz': ['convert.pdfToCbz', 'PDF → CBZ'],
'pdf-to-epub': ['convert.pdfToEpub', 'PDF → EPUB'],
};
// Grouped file extensions for dropdowns // Grouped file extensions for dropdowns
export const FROM_FORMAT_OPTIONS = [ export const FROM_FORMAT_OPTIONS = [
@@ -38,7 +38,7 @@ const FREE_LICENSE_INFO: LicenseInfo = {
const BASE_NO_LOGIN_CONFIG: AppConfig = { const BASE_NO_LOGIN_CONFIG: AppConfig = {
enableAnalytics: true, enableAnalytics: true,
appVersion: '2.6.0', appVersion: '2.7.1',
serverCertificateEnabled: false, serverCertificateEnabled: false,
enableAlphaFunctionality: false, enableAlphaFunctionality: false,
serverPort: 8080, serverPort: 8080,
@@ -8,7 +8,7 @@ import { selfHostedServerMonitor, type SelfHostedServerState } from '@app/servic
import { connectionModeService, type ConnectionMode } from '@app/services/connectionModeService'; import { connectionModeService, type ConnectionMode } from '@app/services/connectionModeService';
import { tauriBackendService } from '@app/services/tauriBackendService'; import { tauriBackendService } from '@app/services/tauriBackendService';
import { endpointAvailabilityService } from '@app/services/endpointAvailabilityService'; import { endpointAvailabilityService } from '@app/services/endpointAvailabilityService';
import { EXTENSION_TO_ENDPOINT } from '@app/constants/convertConstants'; import { EXTENSION_TO_ENDPOINT, ENDPOINT_I18N } from '@app/constants/convertConstants';
import { ENDPOINTS as SPLIT_ENDPOINTS } from '@app/constants/splitConstants'; import { ENDPOINTS as SPLIT_ENDPOINTS } from '@app/constants/splitConstants';
import type { ToolId } from '@app/types/toolId'; import type { ToolId } from '@app/types/toolId';
@@ -28,14 +28,6 @@ const SPLIT_ENDPOINT_I18N: Record<string, [string, string]> = {
'split-for-poster-print': ['split.methods.byPoster.name', 'Printable Chunks'], 'split-for-poster-print': ['split.methods.byPoster.name', 'Printable Chunks'],
}; };
/** Conversion endpoint keys that have translations under selfHosted.offline.conversionTypes */
const KNOWN_CONVERSION_ENDPOINTS = new Set([
'file-to-pdf', 'pdf-to-img', 'img-to-pdf', 'svg-to-pdf', 'cbz-to-pdf',
'pdf-to-cbz', 'pdf-to-word', 'pdf-to-presentation', 'pdf-to-text', 'pdf-to-csv',
'pdf-to-xlsx', 'pdf-to-markdown', 'pdf-to-html', 'pdf-to-xml', 'pdf-to-pdfa',
'html-to-pdf', 'markdown-to-pdf', 'eml-to-pdf', 'cbr-to-pdf', 'pdf-to-cbr',
'ebook-to-pdf', 'pdf-to-epub',
]);
/** /**
@@ -136,8 +128,9 @@ export function SelfHostedOfflineBanner() {
} }
const conversionNames = [...unavailableEndpoints] const conversionNames = [...unavailableEndpoints]
.map(ep => { .map(ep => {
const suffix = KNOWN_CONVERSION_ENDPOINTS.has(ep) const i18n = ENDPOINT_I18N[ep];
? t(`selfHosted.offline.conversionTypes.${ep}`, ep) const suffix = i18n
? (i18n[0] ? t(i18n[0], i18n[1]) : i18n[1])
: ep; : ep;
return `${convertPrefix}: ${suffix}`; return `${convertPrefix}: ${suffix}`;
}) })
@@ -48,7 +48,7 @@ const FREE_LICENSE_INFO: LicenseInfo = {
const BASE_NO_LOGIN_CONFIG: AppConfig = { const BASE_NO_LOGIN_CONFIG: AppConfig = {
enableAnalytics: true, enableAnalytics: true,
appVersion: '2.6.0', appVersion: '2.7.1',
serverCertificateEnabled: false, serverCertificateEnabled: false,
enableAlphaFunctionality: false, enableAlphaFunctionality: false,
enableDesktopInstallSlide: true, enableDesktopInstallSlide: true,