From f2f4bd52302ee8c018076afcc89cf1b362c9c684 Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:48:29 +0000 Subject: [PATCH 01/56] Bug/v2/signature fixes (#5104) Co-authored-by: Dario Ghunney Ware Co-authored-by: James Brunton --- .../SPDF/service/SharedSignatureService.java | 6 +- .../controller/api/SignatureController.java | 103 ++++++++++++++++- .../proprietary/service/SignatureService.java | 109 ++++++++++++++++-- docker/frontend/nginx.conf | 4 +- docker/unified/nginx.conf | 4 +- .../tools/sign/SavedSignaturesSection.tsx | 34 +++--- .../components/tools/sign/SignSettings.tsx | 19 ++- .../hooks/tools/sign/useSavedSignatures.ts | 37 ++++-- .../core/services/signatureStorageService.ts | 38 +++--- 9 files changed, 280 insertions(+), 74 deletions(-) diff --git a/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java b/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java index 6c349581d..7043118a4 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java @@ -179,7 +179,7 @@ public class SharedSignatureService { StandardOpenOption.TRUNCATE_EXISTING); // Store reference to image file - response.setDataUrl("/api/v1/general/sign/" + imageFileName); + response.setDataUrl("/api/v1/general/signatures/" + imageFileName); } log.info("Saved signature {} for user {}", request.getId(), username); @@ -207,7 +207,7 @@ public class SharedSignatureService { sig.setLabel(id); // Use ID as label sig.setType("image"); // Default type sig.setScope("personal"); - sig.setDataUrl("/api/v1/general/sign/" + fileName); + sig.setDataUrl("/api/v1/general/signatures/" + fileName); sig.setCreatedAt( Files.getLastModifiedTime(path).toMillis()); sig.setUpdatedAt( @@ -238,7 +238,7 @@ public class SharedSignatureService { sig.setLabel(id); // Use ID as label sig.setType("image"); // Default type sig.setScope("shared"); - sig.setDataUrl("/api/v1/general/sign/" + fileName); + sig.setDataUrl("/api/v1/general/signatures/" + fileName); sig.setCreatedAt( Files.getLastModifiedTime(path).toMillis()); sig.setUpdatedAt( diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java index f42b23a97..a073c2137 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java @@ -1,7 +1,12 @@ package stirling.software.proprietary.controller.api; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; +import java.util.Map; +import java.util.stream.Stream; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -18,6 +23,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.common.annotations.api.UserApi; +import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.proprietary.model.api.signature.SavedSignatureRequest; import stirling.software.proprietary.model.api.signature.SavedSignatureResponse; import stirling.software.proprietary.security.service.UserService; @@ -38,6 +44,7 @@ public class SignatureController { private final SignatureService signatureService; private final UserService userService; + private static final String ALL_USERS_FOLDER = "ALL_USERS"; /** * Save a new signature for the authenticated user. Enforces storage limits and authentication @@ -84,19 +91,105 @@ public class SignatureController { } /** - * Delete a signature owned by the authenticated user. Users can only delete their own personal - * signatures, not shared ones. + * Update a signature label. Users can update labels for their own personal signatures and for + * shared signatures. + */ + @PostMapping("/{signatureId}/label") + @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") + public ResponseEntity updateSignatureLabel( + @PathVariable String signatureId, @RequestBody Map body) { + try { + String username = userService.getCurrentUsername(); + String newLabel = body.get("label"); + + if (newLabel == null || newLabel.trim().isEmpty()) { + log.warn("Invalid label update request"); + return ResponseEntity.badRequest().build(); + } + + signatureService.updateSignatureLabel(username, signatureId, newLabel); + log.info("User {} updated label for signature {}", username, signatureId); + return ResponseEntity.noContent().build(); + } catch (IOException e) { + log.warn("Failed to update signature label: {}", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + } + + /** + * Delete a signature owned by the authenticated user. Users can delete their own personal + * signatures. Admins can also delete shared signatures. */ @DeleteMapping("/{signatureId}") + @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") public ResponseEntity deleteSignature(@PathVariable String signatureId) { try { String username = userService.getCurrentUsername(); - signatureService.deleteSignature(username, signatureId); - log.info("User {} deleted signature {}", username, signatureId); - return ResponseEntity.noContent().build(); + boolean isAdmin = userService.isCurrentUserAdmin(); + + // Validate filename to prevent path traversal + if (signatureId.contains("..") + || signatureId.contains("/") + || signatureId.contains("\\")) { + log.warn("Invalid signature ID: {}", signatureId); + return ResponseEntity.badRequest().build(); + } + + // Try to delete from personal folder first + try { + signatureService.deleteSignature(username, signatureId); + log.info("User {} deleted personal signature {}", username, signatureId); + return ResponseEntity.noContent().build(); + } catch (IOException e) { + // If not found in personal folder, check if it's in shared folder + if (isAdmin) { + // Admin can delete from shared folder + if (deleteFromSharedFolder(signatureId)) { + log.info("Admin {} deleted shared signature {}", username, signatureId); + return ResponseEntity.noContent().build(); + } + } + // If not admin or not found in shared folder either, return 404 + throw e; + } } catch (IOException e) { log.warn("Failed to delete signature {} for user: {}", signatureId, e.getMessage()); return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } } + + /** + * Delete a signature from the shared (ALL_USERS) folder. Only admins should call this method. + */ + private boolean deleteFromSharedFolder(String signatureId) throws IOException { + String signatureBasePath = InstallationPathConfig.getSignaturesPath(); + Path sharedFolder = Paths.get(signatureBasePath, ALL_USERS_FOLDER); + boolean deleted = false; + + if (Files.exists(sharedFolder)) { + try (Stream stream = Files.list(sharedFolder)) { + List matchingFiles = + stream.filter( + path -> + path.getFileName() + .toString() + .startsWith(signatureId + ".")) + .toList(); + for (Path file : matchingFiles) { + Files.delete(file); + deleted = true; + log.info("Deleted shared signature file: {}", file); + } + } + + // Also delete metadata file if it exists + Path metadataPath = sharedFolder.resolve(signatureId + ".json"); + if (Files.exists(metadataPath)) { + Files.delete(metadataPath); + log.info("Deleted shared signature metadata: {}", metadataPath); + } + } + + return deleted; + } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java index 6f849ebfe..63ee28512 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java @@ -2,6 +2,7 @@ package stirling.software.proprietary.service; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -13,6 +14,8 @@ import java.util.stream.Stream; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.databind.ObjectMapper; + import lombok.extern.slf4j.Slf4j; import stirling.software.common.configuration.InstallationPathConfig; @@ -31,6 +34,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { private final String SIGNATURE_BASE_PATH; private final String ALL_USERS_FOLDER = "ALL_USERS"; + private final ObjectMapper objectMapper = new ObjectMapper(); // Storage limits per user private static final int MAX_SIGNATURES_PER_USER = 20; @@ -88,6 +92,14 @@ public class SignatureService implements PersonalSignatureServiceInterface { response.setCreatedAt(timestamp); response.setUpdatedAt(timestamp); + // Copy text signature properties if present + if ("text".equals(request.getType())) { + response.setSignerName(request.getSignerName()); + response.setFontFamily(request.getFontFamily()); + response.setFontSize(request.getFontSize()); + response.setTextColor(request.getTextColor()); + } + // Extract and save image data String dataUrl = request.getDataUrl(); if (dataUrl != null && dataUrl.startsWith("data:image/")) { @@ -133,6 +145,19 @@ public class SignatureService implements PersonalSignatureServiceInterface { response.setDataUrl("/api/v1/general/signatures/" + imageFileName); } + // Save metadata JSON file + String metadataFileName = request.getId() + ".json"; + Path metadataPath = targetFolder.resolve(metadataFileName); + verifyPathWithinDirectory(metadataPath, targetFolder); + + String metadataJson = objectMapper.writeValueAsString(response); + Files.writeString( + metadataPath, + metadataJson, + StandardCharsets.UTF_8, + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + log.info("Saved signature {} for user {} (scope: {})", request.getId(), username, scope); return response; } @@ -179,6 +204,13 @@ public class SignatureService implements PersonalSignatureServiceInterface { log.info("Deleted signature file: {}", file); } } + + // Also delete metadata file if it exists + Path metadataPath = personalFolder.resolve(signatureId + ".json"); + if (Files.exists(metadataPath)) { + Files.delete(metadataPath); + log.info("Deleted signature metadata: {}", metadataPath); + } } if (!deleted) { @@ -186,6 +218,50 @@ public class SignatureService implements PersonalSignatureServiceInterface { } } + /** Update a signature label. */ + public void updateSignatureLabel(String username, String signatureId, String newLabel) + throws IOException { + validateFileName(signatureId); + + // Try personal folder first + Path personalFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path metadataPath = personalFolder.resolve(signatureId + ".json"); + + if (Files.exists(metadataPath)) { + updateMetadataLabel(metadataPath, newLabel); + log.info("Updated label for personal signature {} (user: {})", signatureId, username); + return; + } + + // If not found in personal, try shared folder + Path sharedFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path sharedMetadataPath = sharedFolder.resolve(signatureId + ".json"); + + if (Files.exists(sharedMetadataPath)) { + updateMetadataLabel(sharedMetadataPath, newLabel); + log.info("Updated label for shared signature {}", signatureId); + return; + } + + throw new FileNotFoundException("Signature metadata not found"); + } + + private void updateMetadataLabel(Path metadataPath, String newLabel) throws IOException { + String metadataJson = Files.readString(metadataPath, StandardCharsets.UTF_8); + SavedSignatureResponse sig = + objectMapper.readValue(metadataJson, SavedSignatureResponse.class); + sig.setLabel(newLabel); + sig.setUpdatedAt(System.currentTimeMillis()); + + String updatedJson = objectMapper.writeValueAsString(sig); + Files.writeString( + metadataPath, + updatedJson, + StandardCharsets.UTF_8, + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + } + // Private helper methods private void enforceStorageLimits(String username, String dataUrlToAdd) throws IOException { @@ -245,16 +321,31 @@ public class SignatureService implements PersonalSignatureServiceInterface { String fileName = path.getFileName().toString(); String id = fileName.substring(0, fileName.lastIndexOf('.')); - SavedSignatureResponse sig = new SavedSignatureResponse(); - sig.setId(id); - sig.setLabel(id); - sig.setType("image"); - sig.setScope(scope); - sig.setCreatedAt(Files.getLastModifiedTime(path).toMillis()); - sig.setUpdatedAt(Files.getLastModifiedTime(path).toMillis()); + // Try to load metadata from JSON file + Path metadataPath = folder.resolve(id + ".json"); + SavedSignatureResponse sig; - // Set unified URL path (works for both personal and shared) - sig.setDataUrl("/api/v1/general/signatures/" + fileName); + if (Files.exists(metadataPath)) { + // Load from metadata file + String metadataJson = + Files.readString( + metadataPath, StandardCharsets.UTF_8); + sig = + objectMapper.readValue( + metadataJson, SavedSignatureResponse.class); + } else { + // Fallback for old signatures without metadata + sig = new SavedSignatureResponse(); + sig.setId(id); + sig.setLabel(id); + sig.setType("image"); + sig.setScope(scope); + sig.setCreatedAt( + Files.getLastModifiedTime(path).toMillis()); + sig.setUpdatedAt( + Files.getLastModifiedTime(path).toMillis()); + sig.setDataUrl("/api/v1/general/signatures/" + fileName); + } signatures.add(sig); } catch (IOException e) { diff --git a/docker/frontend/nginx.conf b/docker/frontend/nginx.conf index 3be5ec900..ef74321ef 100644 --- a/docker/frontend/nginx.conf +++ b/docker/frontend/nginx.conf @@ -103,8 +103,8 @@ http { add_header Cache-Control "public, immutable"; } - # Cache static assets - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + # Cache static assets (but not API endpoints) + location ~* ^(?!/api/).*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } diff --git a/docker/unified/nginx.conf b/docker/unified/nginx.conf index 1e47b8619..cbd5fee81 100644 --- a/docker/unified/nginx.conf +++ b/docker/unified/nginx.conf @@ -106,8 +106,8 @@ http { add_header Cache-Control "public, immutable"; } - # Cache static assets - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + # Cache static assets (but not API endpoints) + location ~* ^(?!/api/).*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } diff --git a/frontend/src/core/components/tools/sign/SavedSignaturesSection.tsx b/frontend/src/core/components/tools/sign/SavedSignaturesSection.tsx index c2e8ca8f1..95a8a7e77 100644 --- a/frontend/src/core/components/tools/sign/SavedSignaturesSection.tsx +++ b/frontend/src/core/components/tools/sign/SavedSignaturesSection.tsx @@ -2,14 +2,16 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ActionIcon, Alert, Badge, Box, Card, Group, Stack, Text, TextInput, Tooltip } from '@mantine/core'; import { LocalIcon } from '@app/components/shared/LocalIcon'; -import { MAX_SAVED_SIGNATURES, SavedSignature, SavedSignatureType } from '@app/hooks/tools/sign/useSavedSignatures'; +import { SavedSignature, SavedSignatureType } from '@app/hooks/tools/sign/useSavedSignatures'; import type { StorageType } from '@app/services/signatureStorageService'; interface SavedSignaturesSectionProps { signatures: SavedSignature[]; disabled?: boolean; isAtCapacity: boolean; + maxLimit: number; storageType?: StorageType | null; + isAdmin?: boolean; onUseSignature: (signature: SavedSignature) => void; onDeleteSignature: (signature: SavedSignature) => void; onRenameSignature: (id: string, label: string) => void; @@ -26,7 +28,9 @@ export const SavedSignaturesSection = ({ signatures, disabled = false, isAtCapacity, + maxLimit, storageType: _storageType, + isAdmin = false, onUseSignature, onDeleteSignature, onRenameSignature, @@ -155,7 +159,7 @@ export const SavedSignaturesSection = ({ {translate( 'saved.emptyDescription', 'Draw, upload, or type a signature above, then use "Save to library" to keep up to {{max}} favourites ready to use.', - { max: MAX_SAVED_SIGNATURES } + { max: maxLimit } )} @@ -216,7 +220,7 @@ export const SavedSignaturesSection = ({ {translate('saved.limitDescription', 'Remove a saved signature before adding new ones (max {{max}}).', { - max: MAX_SAVED_SIGNATURES, + max: maxLimit, })} @@ -365,17 +369,19 @@ export const SavedSignaturesSection = ({ > - - onDeleteSignature(activeSharedSignature)} - disabled={disabled} - > - - - + {isAdmin && ( + + onDeleteSignature(activeSharedSignature)} + disabled={disabled} + > + + + + )} {renderPreview(activeSharedSignature)} diff --git a/frontend/src/core/components/tools/sign/SignSettings.tsx b/frontend/src/core/components/tools/sign/SignSettings.tsx index 6fb3238f8..233b87373 100644 --- a/frontend/src/core/components/tools/sign/SignSettings.tsx +++ b/frontend/src/core/components/tools/sign/SignSettings.tsx @@ -14,7 +14,7 @@ import { ImageUploader } from "@app/components/annotation/shared/ImageUploader"; import { TextInputWithFont } from "@app/components/annotation/shared/TextInputWithFont"; import { ColorPicker } from "@app/components/annotation/shared/ColorPicker"; import { LocalIcon } from "@app/components/shared/LocalIcon"; -import { useSavedSignatures, SavedSignature, SavedSignaturePayload, SavedSignatureType, MAX_SAVED_SIGNATURES, AddSignatureResult } from '@app/hooks/tools/sign/useSavedSignatures'; +import { useSavedSignatures, SavedSignature, SavedSignaturePayload, SavedSignatureType, AddSignatureResult } from '@app/hooks/tools/sign/useSavedSignatures'; import { SavedSignaturesSection } from '@app/components/tools/sign/SavedSignaturesSection'; import { buildSignaturePreview } from '@app/utils/signaturePreview'; @@ -96,11 +96,13 @@ const SignSettings = ({ const { savedSignatures, isAtCapacity: isSavedSignatureLimitReached, + maxLimit, addSignature, removeSignature, updateSignatureLabel, byTypeCounts, storageType, + isAdmin, } = useSavedSignatures(); const [signatureSource, setSignatureSource] = useState(() => { const paramSource = parameters.signatureType as SignatureSource; @@ -246,16 +248,19 @@ const SignSettings = ({ (signature: SavedSignature) => { setPlacementManuallyPaused(false); + // Use the data URL directly (already converted to base64 when loaded) + const dataUrlToUse = signature.dataUrl; + if (signature.type === 'canvas') { if (parameters.signatureType !== 'canvas') { onParameterChange('signatureType', 'canvas'); } - setCanvasSignatureData(signature.dataUrl); + setCanvasSignatureData(dataUrlToUse); } else if (signature.type === 'image') { if (parameters.signatureType !== 'image') { onParameterChange('signatureType', 'image'); } - setImageSignatureData(signature.dataUrl); + setImageSignatureData(dataUrlToUse); } else if (signature.type === 'text') { if (parameters.signatureType !== 'text') { onParameterChange('signatureType', 'text'); @@ -269,7 +274,7 @@ const SignSettings = ({ const savedKey = signature.type === 'text' ? buildTextSignatureKey(signature.signerName, signature.fontSize, signature.fontFamily, signature.textColor) - : signature.dataUrl; + : dataUrlToUse; setLastSavedKeyForType(signature.type, savedKey); const activate = () => onActivateSignaturePlacement?.(); @@ -326,8 +331,8 @@ const SignSettings = ({ } else if (isSaved) { tooltipMessage = translate('saved.noChanges', 'Current signature is already saved.'); } else if (isSavedSignatureLimitReached) { - tooltipMessage = translate('saved.limitDescription', 'Remove a saved signature before adding new ones (max {{max}}).', { - max: MAX_SAVED_SIGNATURES, + tooltipMessage = translate('saved.limitDescription', 'You have reached the maximum limit of {{max}} saved signatures. Remove a saved signature before adding new ones.', { + max: maxLimit, }); } @@ -791,7 +796,9 @@ const SignSettings = ({ signatures={savedSignatures} disabled={disabled} isAtCapacity={isSavedSignatureLimitReached} + maxLimit={maxLimit} storageType={storageType} + isAdmin={isAdmin} onUseSignature={handleUseSavedSignature} onDeleteSignature={handleDeleteSavedSignature} onRenameSignature={handleRenameSavedSignature} diff --git a/frontend/src/core/hooks/tools/sign/useSavedSignatures.ts b/frontend/src/core/hooks/tools/sign/useSavedSignatures.ts index 655038a3f..b878dcd0d 100644 --- a/frontend/src/core/hooks/tools/sign/useSavedSignatures.ts +++ b/frontend/src/core/hooks/tools/sign/useSavedSignatures.ts @@ -1,7 +1,9 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { signatureStorageService, type StorageType } from '@app/services/signatureStorageService'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; -export const MAX_SAVED_SIGNATURES = 10; +export const MAX_SAVED_SIGNATURES_BACKEND = 20; // Backend limit per user +export const MAX_SAVED_SIGNATURES_LOCALSTORAGE = 10; // LocalStorage limit export type SavedSignatureType = 'canvas' | 'image' | 'text'; export type SignatureScope = 'personal' | 'shared' | 'localStorage'; @@ -49,6 +51,8 @@ export const useSavedSignatures = () => { const [savedSignatures, setSavedSignatures] = useState([]); const [storageType, setStorageType] = useState(null); const [isLoading, setIsLoading] = useState(true); + const { config } = useAppConfig(); + const isAdmin = config?.isAdmin ?? false; // Load signatures and detect storage type on mount useEffect(() => { @@ -97,7 +101,9 @@ export const useSavedSignatures = () => { return () => window.removeEventListener('storage', syncFromStorage); }, [storageType]); - const isAtCapacity = savedSignatures.length >= MAX_SAVED_SIGNATURES; + // Different limits for backend vs localStorage + const maxLimit = storageType === 'backend' ? MAX_SAVED_SIGNATURES_BACKEND : MAX_SAVED_SIGNATURES_LOCALSTORAGE; + const isAtCapacity = savedSignatures.length >= maxLimit; const addSignature = useCallback( async (payload: SavedSignaturePayload, label?: string, scope?: SignatureScope): Promise => { @@ -108,7 +114,7 @@ export const useSavedSignatures = () => { return { success: false, reason: 'invalid' }; } - if (savedSignatures.length >= MAX_SAVED_SIGNATURES) { + if (isAtCapacity) { return { success: false, reason: 'limit' }; } @@ -146,17 +152,24 @@ export const useSavedSignatures = () => { const updateSignatureLabel = useCallback(async (id: string, nextLabel: string) => { try { await signatureStorageService.updateSignatureLabel(id, nextLabel); - setSavedSignatures(prev => - prev.map(entry => - entry.id === id - ? { ...entry, label: nextLabel.trim() || entry.label || 'Signature', updatedAt: Date.now() } - : entry - ) - ); + // Reload signatures to get updated data from backend + if (storageType === 'backend') { + const signatures = await signatureStorageService.loadSignatures(); + setSavedSignatures(signatures); + } else { + // For localStorage, update in place + setSavedSignatures(prev => + prev.map(entry => + entry.id === id + ? { ...entry, label: nextLabel.trim() || entry.label || 'Signature', updatedAt: Date.now() } + : entry + ) + ); + } } catch (error) { console.error('[useSavedSignatures] Failed to update signature label:', error); } - }, []); + }, [storageType]); const replaceSignature = useCallback( async (id: string, payload: SavedSignaturePayload) => { @@ -201,6 +214,7 @@ export const useSavedSignatures = () => { return { savedSignatures, isAtCapacity, + maxLimit, addSignature, removeSignature, updateSignatureLabel, @@ -209,6 +223,7 @@ export const useSavedSignatures = () => { byTypeCounts, storageType, isLoading, + isAdmin, }; }; diff --git a/frontend/src/core/services/signatureStorageService.ts b/frontend/src/core/services/signatureStorageService.ts index 365a0cbc6..63dabe909 100644 --- a/frontend/src/core/services/signatureStorageService.ts +++ b/frontend/src/core/services/signatureStorageService.ts @@ -14,7 +14,6 @@ interface SignatureStorageCapabilities { class SignatureStorageService { private capabilities: SignatureStorageCapabilities | null = null; private detectionPromise: Promise | null = null; - private blobUrls: Set = new Set(); /** * Detect if backend supports signature storage API @@ -83,9 +82,6 @@ class SignatureStorageService { * Load all signatures */ async loadSignatures(): Promise { - // Clean up old blob URLs before loading new ones - this.cleanup(); - const capabilities = await this.detectCapabilities(); if (capabilities.supportsBackend) { @@ -130,9 +126,7 @@ class SignatureStorageService { const capabilities = await this.detectCapabilities(); if (capabilities.supportsBackend) { - // Backend only stores images - labels not supported for backend signatures - console.log('[SignatureStorage] Label updates not supported for backend signatures'); - return; + await this._updateLabelInBackend(id, label); } else { this._updateLabelInLocalStorage(id, label); } @@ -144,7 +138,7 @@ class SignatureStorageService { const response = await apiClient.get('/api/v1/proprietary/signatures'); const signatures = response.data; - // Fetch image data for each signature and convert to blob URLs + // Fetch image data for each signature and convert to data URLs const signaturePromises = signatures.map(async (sig) => { if (sig.dataUrl && sig.dataUrl.startsWith('/api/v1/general/signatures/')) { try { @@ -153,14 +147,20 @@ class SignatureStorageService { responseType: 'arraybuffer', }); - // Convert to blob URL + // Convert to data URL (base64) for both display and use const blob = new Blob([imageResponse.data], { type: imageResponse.headers['content-type'] || 'image/png', }); - const blobUrl = URL.createObjectURL(blob); - this.blobUrls.add(blobUrl); - return { ...sig, dataUrl: blobUrl }; + const dataUrl = await new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result as string); + reader.onerror = reject; + reader.readAsDataURL(blob); + }); + + // Use data URL for everything - more reliable than blob URLs + return { ...sig, dataUrl }; } catch (error) { console.error(`[SignatureStorage] Failed to load image for ${sig.id}:`, error); return sig; // Return original if image fetch fails @@ -184,6 +184,10 @@ class SignatureStorageService { await apiClient.delete(`/api/v1/proprietary/signatures/${id}`); } + private async _updateLabelInBackend(id: string, label: string): Promise { + await apiClient.post(`/api/v1/proprietary/signatures/${id}/label`, { label }); + } + // LocalStorage methods private readonly STORAGE_KEY = 'stirling:saved-signatures:v1'; @@ -267,16 +271,6 @@ class SignatureStorageService { return { migrated, failed }; } - - /** - * Clean up blob URLs to prevent memory leaks - */ - cleanup(): void { - this.blobUrls.forEach(url => { - URL.revokeObjectURL(url); - }); - this.blobUrls.clear(); - } } export const signatureStorageService = new SignatureStorageService(); From 8e2f9546a5b666171fbe401eba0c06653dbe0767 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 2 Dec 2025 23:38:19 +0000 Subject: [PATCH 02/56] fixes for automate (#5127) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .../web/ReactRoutingController.java | 36 ++++++++++++++++--- frontend/src/core/utils/automationExecutor.ts | 4 +-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java index db0d95a36..424621b8a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java @@ -4,6 +4,8 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import jakarta.annotation.PostConstruct; + import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.http.MediaType; @@ -19,9 +21,25 @@ public class ReactRoutingController { @Value("${server.servlet.context-path:/}") private String contextPath; - @GetMapping(value = {"/", "/index.html"}, produces = MediaType.TEXT_HTML_VALUE) - public ResponseEntity serveIndexHtml(HttpServletRequest request) - throws IOException { + private String cachedIndexHtml; + private boolean indexHtmlExists = false; + + @PostConstruct + public void init() { + // Only cache if index.html exists (production builds) + ClassPathResource resource = new ClassPathResource("static/index.html"); + if (resource.exists()) { + try { + this.cachedIndexHtml = processIndexHtml(); + this.indexHtmlExists = true; + } catch (IOException e) { + // Failed to cache, will process on each request + this.indexHtmlExists = false; + } + } + } + + private String processIndexHtml() throws IOException { ClassPathResource resource = new ClassPathResource("static/index.html"); try (InputStream inputStream = resource.getInputStream()) { @@ -41,10 +59,20 @@ public class ReactRoutingController { ""; html = html.replace("", contextPathScript + ""); - return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(html); + return html; } } + @GetMapping(value = {"/", "/index.html"}, produces = MediaType.TEXT_HTML_VALUE) + public ResponseEntity serveIndexHtml(HttpServletRequest request) + throws IOException { + if (indexHtmlExists && cachedIndexHtml != null) { + return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(cachedIndexHtml); + } + // Fallback: process on each request (dev mode or cache failed) + return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(processIndexHtml()); + } + @GetMapping( "/{path:^(?!api|static|robots\\.txt|favicon\\.ico|manifest.*\\.json|pipeline|pdfjs|pdfjs-legacy|fonts|images|files|css|js|assets|locales|modern-logo|classic-logo|Login|og_images|samples)[^\\.]*$}") public ResponseEntity forwardRootPaths(HttpServletRequest request) diff --git a/frontend/src/core/utils/automationExecutor.ts b/frontend/src/core/utils/automationExecutor.ts index 760a86d7b..6f1234f81 100644 --- a/frontend/src/core/utils/automationExecutor.ts +++ b/frontend/src/core/utils/automationExecutor.ts @@ -1,4 +1,4 @@ -import axios from 'axios'; +import apiClient from '@app/services/apiClient'; import { ToolRegistry } from '@app/data/toolsTaxonomy'; import { ToolId } from '@app/types/toolId'; import { AUTOMATION_CONSTANTS } from '@app/constants/automation'; @@ -58,7 +58,7 @@ const executeApiRequest = async ( filePrefix: string, preserveBackendFilename?: boolean ): Promise => { - const response = await axios.post(endpoint, formData, { + const response = await apiClient.post(endpoint, formData, { responseType: 'blob', timeout: AUTOMATION_CONSTANTS.OPERATION_TIMEOUT }); From 88c5fb46adb3c28e5e55ccd15452e6bb16d56481 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 2 Dec 2025 23:39:27 +0000 Subject: [PATCH 03/56] Bump version from 2.0.2 to 2.0.3 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b85c2d413..1738c1ef7 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ repositories { allprojects { group = 'stirling.software' - version = '2.0.2' + version = '2.0.3' configurations.configureEach { exclude group: 'commons-logging', module: 'commons-logging' From f72538d30f63db0025e89b271b7ca88d67e6e8c5 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:11:05 +0000 Subject: [PATCH 04/56] Add files via upload --- images/home-light.png | Bin 99907 -> 57696 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/home-light.png b/images/home-light.png index af30a3d3713fbb93e44868abd4266fb3fce507fa..4c2f29b3085fc2babb615f80a159be828d345dde 100644 GIT binary patch literal 57696 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 literal 99907 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 BC3gS- From 65a3eeca761d8e38636184b4b0ba7c6fff865039 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:57:00 +0000 Subject: [PATCH 05/56] Toml (#5115) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .github/scripts/check_language_properties.py | 403 ------------------ ...anguage_json.py => check_language_toml.py} | 68 +-- .../{check_properties.yml => check_toml.yml} | 82 ++-- .github/workflows/sync_files.yml | 122 ------ .github/workflows/sync_files_v2.yml | 38 +- ADDING_TOOLS.md | 6 +- devGuide/HowToAddNewLanguage.md | 67 ++- .../public/locales/ar-AR/translation.toml | 62 ++- .../public/locales/az-AZ/translation.toml | 66 ++- .../public/locales/bg-BG/translation.toml | 60 ++- .../public/locales/ca-CA/translation.toml | 62 ++- .../public/locales/cs-CZ/translation.toml | 72 +++- .../public/locales/da-DK/translation.toml | 80 +++- .../public/locales/de-DE/translation.toml | 80 +++- .../public/locales/el-GR/translation.toml | 84 +++- .../public/locales/es-ES/translation.toml | 72 +++- .../public/locales/eu-ES/translation.toml | 88 +++- .../public/locales/fa-IR/translation.toml | 62 ++- .../public/locales/fr-FR/translation.toml | 72 +++- .../public/locales/ga-IE/translation.toml | 76 +++- .../public/locales/hi-IN/translation.toml | 92 +++- .../public/locales/hr-HR/translation.toml | 62 ++- .../public/locales/hu-HU/translation.toml | 60 ++- .../public/locales/id-ID/translation.toml | 84 +++- .../public/locales/it-IT/translation.toml | 78 +++- .../public/locales/ja-JP/translation.toml | 98 ++++- .../public/locales/ko-KR/translation.toml | 70 ++- .../public/locales/ml-ML/translation.toml | 88 +++- .../public/locales/nl-NL/translation.toml | 70 ++- .../public/locales/no-NB/translation.toml | 68 ++- .../public/locales/pl-PL/translation.toml | 68 ++- .../public/locales/pt-BR/translation.toml | 78 +++- .../public/locales/pt-PT/translation.toml | 78 +++- .../public/locales/ro-RO/translation.toml | 70 ++- .../public/locales/ru-RU/translation.toml | 66 ++- .../public/locales/sk-SK/translation.toml | 76 +++- .../public/locales/sl-SI/translation.toml | 60 ++- .../locales/sr-LATN-RS/translation.toml | 66 ++- .../public/locales/sv-SE/translation.toml | 62 ++- .../public/locales/th-TH/translation.toml | 98 ++++- .../public/locales/tr-TR/translation.toml | 60 ++- .../public/locales/uk-UA/translation.toml | 68 ++- .../public/locales/vi-VN/translation.toml | 74 +++- .../public/locales/zh-BO/translation.toml | 60 ++- .../public/locales/zh-CN/translation.toml | 64 ++- .../public/locales/zh-TW/translation.toml | 68 ++- scripts/convert_properties_to_json.py | 113 ----- scripts/counter_translation.py | 219 ---------- ...lation_v2.py => counter_translation_v3.py} | 32 +- scripts/translations/README.md | 27 +- scripts/translations/ai_translation_helper.py | 89 ++-- scripts/translations/auto_translate.py | 43 +- scripts/translations/batch_translator.py | 6 +- scripts/translations/bulk_auto_translate.py | 305 +++++++++++++ scripts/translations/compact_translator.py | 70 +-- scripts/translations/json_validator.py | 259 ----------- ...{json_beautifier.py => toml_beautifier.py} | 68 +-- scripts/translations/toml_validator.py | 198 +++++++++ scripts/translations/translation_analyzer.py | 87 ++-- scripts/translations/translation_merger.py | 91 ++-- .../translations/validate_json_structure.py | 58 +-- scripts/translations/validate_placeholders.py | 26 +- 62 files changed, 3352 insertions(+), 1947 deletions(-) delete mode 100644 .github/scripts/check_language_properties.py rename .github/scripts/{check_language_json.py => check_language_toml.py} (84%) rename .github/workflows/{check_properties.yml => check_toml.yml} (77%) delete mode 100644 .github/workflows/sync_files.yml delete mode 100644 scripts/convert_properties_to_json.py delete mode 100644 scripts/counter_translation.py rename scripts/{counter_translation_v2.py => counter_translation_v3.py} (91%) create mode 100644 scripts/translations/bulk_auto_translate.py delete mode 100644 scripts/translations/json_validator.py rename scripts/translations/{json_beautifier.py => toml_beautifier.py} (86%) create mode 100644 scripts/translations/toml_validator.py diff --git a/.github/scripts/check_language_properties.py b/.github/scripts/check_language_properties.py deleted file mode 100644 index a77c378a6..000000000 --- a/.github/scripts/check_language_properties.py +++ /dev/null @@ -1,403 +0,0 @@ -""" -Author: Ludy87 -Description: This script processes .properties files for localization checks. It compares translation files in a branch with -a reference file to ensure consistency. The script performs two main checks: -1. Verifies that the number of lines (including comments and empty lines) in the translation files matches the reference file. -2. Ensures that all keys in the translation files are present in the reference file and vice versa. - -The script also provides functionality to update the translation files to match the reference file by adding missing keys and -adjusting the format. - -Usage: - python check_language_properties.py --reference-file --branch [--actor ] [--files ] -""" -# Sample for Windows: -# python .github/scripts/check_language_properties.py --reference-file src\main\resources\messages_en_GB.properties --branch "" --files src\main\resources\messages_de_DE.properties src\main\resources\messages_uk_UA.properties - -import copy -import glob -import os -import argparse -import re - - -def find_duplicate_keys(file_path): - """ - Identifies duplicate keys in a .properties file. - :param file_path: Path to the .properties file. - :return: List of tuples (key, first_occurrence_line, duplicate_line). - """ - keys = {} - duplicates = [] - - with open(file_path, "r", encoding="utf-8") as file: - for line_number, line in enumerate(file, start=1): - stripped_line = line.strip() - - # Skip empty lines and comments - if not stripped_line or stripped_line.startswith("#"): - continue - - # Split the line into key and value - if "=" in stripped_line: - key, _ = stripped_line.split("=", 1) - key = key.strip() - - # Check if the key already exists - if key in keys: - duplicates.append((key, keys[key], line_number)) - else: - keys[key] = line_number - - return duplicates - - -# Maximum size for properties files (e.g., 200 KB) -MAX_FILE_SIZE = 200 * 1024 - - -def parse_properties_file(file_path): - """ - Parses a .properties file and returns a structured list of its contents. - :param file_path: Path to the .properties file. - :return: List of dictionaries representing each line in the file. - """ - properties_list = [] - with open(file_path, "r", encoding="utf-8") as file: - for line_number, line in enumerate(file, start=1): - stripped_line = line.strip() - - # Handle empty lines - if not stripped_line: - properties_list.append( - {"line_number": line_number, "type": "empty", "content": ""} - ) - continue - - # Handle comments - if stripped_line.startswith("#"): - properties_list.append( - { - "line_number": line_number, - "type": "comment", - "content": stripped_line, - } - ) - continue - - # Handle key-value pairs - match = re.match(r"^([^=]+)=(.*)$", line) - if match: - key, value = match.groups() - properties_list.append( - { - "line_number": line_number, - "type": "entry", - "key": key.strip(), - "value": value.strip(), - } - ) - - return properties_list - - -def write_json_file(file_path, updated_properties): - """ - Writes updated properties back to the file in their original format. - :param file_path: Path to the .properties file. - :param updated_properties: List of updated properties to write. - """ - updated_lines = {entry["line_number"]: entry for entry in updated_properties} - - # Sort lines by their numbers and retain comments and empty lines - all_lines = sorted(set(updated_lines.keys())) - - original_format = [] - for line in all_lines: - if line in updated_lines: - entry = updated_lines[line] - else: - entry = None - ref_entry = updated_lines[line] - if ref_entry["type"] in ["comment", "empty"]: - original_format.append(ref_entry) - elif entry is None: - # Add missing entries from the reference file - original_format.append(ref_entry) - elif entry["type"] == "entry": - # Replace entries with those from the current JSON - original_format.append(entry) - - # Write the updated content back to the file - with open(file_path, "w", encoding="utf-8", newline="\n") as file: - for entry in original_format: - if entry["type"] == "comment": - file.write(f"{entry['content']}\n") - elif entry["type"] == "empty": - file.write(f"{entry['content']}\n") - elif entry["type"] == "entry": - file.write(f"{entry['key']}={entry['value']}\n") - - -def update_missing_keys(reference_file, file_list, branch=""): - """ - Updates missing keys in the translation files based on the reference file. - :param reference_file: Path to the reference .properties file. - :param file_list: List of translation files to update. - :param branch: Branch where the files are located. - """ - reference_properties = parse_properties_file(reference_file) - for file_path in file_list: - basename_current_file = os.path.basename(os.path.join(branch, file_path)) - if ( - basename_current_file == os.path.basename(reference_file) - or not file_path.endswith(".properties") - or not basename_current_file.startswith("messages_") - ): - continue - - current_properties = parse_properties_file(os.path.join(branch, file_path)) - updated_properties = [] - for ref_entry in reference_properties: - ref_entry_copy = copy.deepcopy(ref_entry) - for current_entry in current_properties: - if current_entry["type"] == "entry": - if ref_entry_copy["type"] != "entry": - continue - if ref_entry_copy["key"].lower() == current_entry["key"].lower(): - ref_entry_copy["value"] = current_entry["value"] - updated_properties.append(ref_entry_copy) - write_json_file(os.path.join(branch, file_path), updated_properties) - - -def check_for_missing_keys(reference_file, file_list, branch): - update_missing_keys(reference_file, file_list, branch) - - -def read_properties(file_path): - if os.path.isfile(file_path) and os.path.exists(file_path): - with open(file_path, "r", encoding="utf-8") as file: - return file.read().splitlines() - return [""] - - -def check_for_differences(reference_file, file_list, branch, actor): - reference_branch = reference_file.split("/")[0] - basename_reference_file = os.path.basename(reference_file) - - report = [] - report.append(f"#### 🔄 Reference Branch: `{reference_branch}`") - reference_lines = read_properties(reference_file) - has_differences = False - - only_reference_file = True - - file_arr = file_list - - if len(file_list) == 1: - file_arr = file_list[0].split() - base_dir = os.path.abspath( - os.path.join(os.getcwd(), "app", "core", "src", "main", "resources") - ) - - for file_path in file_arr: - file_normpath = os.path.normpath(file_path) - absolute_path = os.path.abspath(file_normpath) - # Verify that file is within the expected directory - if not absolute_path.startswith(base_dir): - raise ValueError(f"Unsafe file found: {file_normpath}") - # Verify file size before processing - if os.path.getsize(os.path.join(branch, file_normpath)) > MAX_FILE_SIZE: - raise ValueError( - f"The file {file_normpath} is too large and could pose a security risk." - ) - - basename_current_file = os.path.basename(os.path.join(branch, file_normpath)) - if ( - basename_current_file == basename_reference_file - or ( - # only local windows command - not file_normpath.startswith( - os.path.join( - "", "app", "core", "src", "main", "resources", "messages_" - ) - ) - and not file_normpath.startswith( - os.path.join( - os.getcwd(), - "app", - "core", - "src", - "main", - "resources", - "messages_", - ) - ) - ) - or not file_normpath.endswith(".properties") - or not basename_current_file.startswith("messages_") - ): - continue - only_reference_file = False - report.append(f"#### 📃 **File Check:** `{basename_current_file}`") - current_lines = read_properties(os.path.join(branch, file_path)) - reference_line_count = len(reference_lines) - current_line_count = len(current_lines) - - if reference_line_count != current_line_count: - report.append("") - report.append("1. **Test Status:** ❌ **_Failed_**") - report.append(" - **Issue:**") - has_differences = True - if reference_line_count > current_line_count: - report.append( - f" - **_Mismatched line count_**: {reference_line_count} (reference) vs {current_line_count} (current). Comments, empty lines, or translation strings are missing." - ) - elif reference_line_count < current_line_count: - report.append( - f" - **_Too many lines_**: {reference_line_count} (reference) vs {current_line_count} (current). Please verify if there is an additional line that needs to be removed." - ) - else: - report.append("1. **Test Status:** ✅ **_Passed_**") - - # Check for missing or extra keys - current_keys = [] - reference_keys = [] - for line in current_lines: - if not line.startswith("#") and line != "" and "=" in line: - key, _ = line.split("=", 1) - current_keys.append(key) - for line in reference_lines: - if not line.startswith("#") and line != "" and "=" in line: - key, _ = line.split("=", 1) - reference_keys.append(key) - - current_keys_set = set(current_keys) - reference_keys_set = set(reference_keys) - missing_keys = current_keys_set.difference(reference_keys_set) - extra_keys = reference_keys_set.difference(current_keys_set) - missing_keys_list = list(missing_keys) - extra_keys_list = list(extra_keys) - - if missing_keys_list or extra_keys_list: - has_differences = True - missing_keys_str = "`, `".join(missing_keys_list) - extra_keys_str = "`, `".join(extra_keys_list) - report.append("2. **Test Status:** ❌ **_Failed_**") - report.append(" - **Issue:**") - if missing_keys_list: - spaces_keys_list = [] - for key in missing_keys_list: - if " " in key: - spaces_keys_list.append(key) - if spaces_keys_list: - spaces_keys_str = "`, `".join(spaces_keys_list) - report.append( - f" - **_Keys containing unnecessary spaces_**: `{spaces_keys_str}`!" - ) - report.append( - f" - **_Extra keys in `{basename_current_file}`_**: `{missing_keys_str}` that are not present in **_`{basename_reference_file}`_**." - ) - if extra_keys_list: - report.append( - f" - **_Missing keys in `{basename_reference_file}`_**: `{extra_keys_str}` that are not present in **_`{basename_current_file}`_**." - ) - else: - report.append("2. **Test Status:** ✅ **_Passed_**") - - if find_duplicate_keys(os.path.join(branch, file_normpath)): - has_differences = True - output = "\n".join( - [ - f" - `{key}`: first at line {first}, duplicate at `line {duplicate}`" - for key, first, duplicate in find_duplicate_keys( - os.path.join(branch, file_normpath) - ) - ] - ) - report.append("3. **Test Status:** ❌ **_Failed_**") - report.append(" - **Issue:**") - report.append(" - duplicate entries were found:") - report.append(output) - else: - report.append("3. **Test Status:** ✅ **_Passed_**") - - report.append("") - report.append("---") - report.append("") - if has_differences: - report.append("## ❌ Overall Check Status: **_Failed_**") - report.append("") - report.append( - f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/core/src/main/resources/messages_en_GB.properties)" - ) - else: - report.append("## ✅ Overall Check Status: **_Success_**") - report.append("") - report.append( - f"Thanks @{actor} for your help in keeping the translations up to date." - ) - - if not only_reference_file: - print("\n".join(report)) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Find missing keys") - parser.add_argument( - "--actor", - required=False, - help="Actor from PR.", - ) - parser.add_argument( - "--reference-file", - required=True, - help="Path to the reference file.", - ) - parser.add_argument( - "--branch", - type=str, - required=True, - help="Branch name.", - ) - parser.add_argument( - "--check-file", - type=str, - required=False, - help="List of changed files, separated by spaces.", - ) - parser.add_argument( - "--files", - nargs="+", - required=False, - help="List of changed files, separated by spaces.", - ) - args = parser.parse_args() - - # Sanitize --actor input to avoid injection attacks - if args.actor: - args.actor = re.sub(r"[^a-zA-Z0-9_\\-]", "", args.actor) - - # Sanitize --branch input to avoid injection attacks - if args.branch: - args.branch = re.sub(r"[^a-zA-Z0-9\\-]", "", args.branch) - - file_list = args.files - if file_list is None: - if args.check_file: - file_list = [args.check_file] - else: - file_list = glob.glob( - os.path.join( - os.getcwd(), - "app", - "core", - "src", - "main", - "resources", - "messages_*.properties", - ) - ) - update_missing_keys(args.reference_file, file_list) - else: - check_for_differences(args.reference_file, file_list, args.branch, args.actor) diff --git a/.github/scripts/check_language_json.py b/.github/scripts/check_language_toml.py similarity index 84% rename from .github/scripts/check_language_json.py rename to .github/scripts/check_language_toml.py index 3921bdaa5..494f90962 100644 --- a/.github/scripts/check_language_json.py +++ b/.github/scripts/check_language_toml.py @@ -1,6 +1,6 @@ """ Author: Ludy87 -Description: This script processes JSON translation files for localization checks. It compares translation files in a branch with +Description: This script processes TOML translation files for localization checks. It compares translation files in a branch with a reference file to ensure consistency. The script performs two main checks: 1. Verifies that the number of translation keys in the translation files matches the reference file. 2. Ensures that all keys in the translation files are present in the reference file and vice versa. @@ -9,10 +9,10 @@ The script also provides functionality to update the translation files to match adjusting the format. Usage: - python check_language_json.py --reference-file --branch [--actor ] [--files ] + python check_language_toml.py --reference-file --branch [--actor ] [--files ] """ # Sample for Windows: -# python .github/scripts/check_language_json.py --reference-file frontend/public/locales/en-GB/translation.json --branch "" --files frontend/public/locales/de-DE/translation.json frontend/public/locales/fr-FR/translation.json +# python .github/scripts/check_language_toml.py --reference-file frontend/public/locales/en-GB/translation.toml --branch "" --files frontend/public/locales/de-DE/translation.toml frontend/public/locales/fr-FR/translation.toml import copy import glob @@ -20,12 +20,14 @@ import os import argparse import re import json +import tomllib # Python 3.11+ (stdlib) +import tomli_w # For writing TOML files def find_duplicate_keys(file_path, keys=None, prefix=""): """ - Identifies duplicate keys in a JSON file (including nested keys). - :param file_path: Path to the JSON file. + Identifies duplicate keys in a TOML file (including nested keys). + :param file_path: Path to the TOML file. :param keys: Dictionary to track keys (used for recursion). :param prefix: Prefix for nested keys. :return: List of tuples (key, first_occurrence_path, duplicate_path). @@ -35,8 +37,9 @@ def find_duplicate_keys(file_path, keys=None, prefix=""): duplicates = [] - with open(file_path, "r", encoding="utf-8") as file: - data = json.load(file) + # Load TOML file + with open(file_path, 'rb') as file: + data = tomllib.load(file) def process_dict(obj, current_prefix=""): for key, value in obj.items(): @@ -54,18 +57,18 @@ def find_duplicate_keys(file_path, keys=None, prefix=""): return duplicates -# Maximum size for JSON files (e.g., 500 KB) +# Maximum size for TOML files (e.g., 500 KB) MAX_FILE_SIZE = 500 * 1024 -def parse_json_file(file_path): +def parse_toml_file(file_path): """ - Parses a JSON translation file and returns a flat dictionary of all keys. - :param file_path: Path to the JSON file. + Parses a TOML translation file and returns a flat dictionary of all keys. + :param file_path: Path to the TOML file. :return: Dictionary with flattened keys. """ - with open(file_path, "r", encoding="utf-8") as file: - data = json.load(file) + with open(file_path, 'rb') as file: + data = tomllib.load(file) def flatten_dict(d, parent_key="", sep="."): items = {} @@ -99,38 +102,37 @@ def unflatten_dict(d, sep="."): return result -def write_json_file(file_path, updated_properties): +def write_toml_file(file_path, updated_properties): """ - Writes updated properties back to the JSON file. - :param file_path: Path to the JSON file. + Writes updated properties back to the TOML file. + :param file_path: Path to the TOML file. :param updated_properties: Dictionary of updated properties to write. """ nested_data = unflatten_dict(updated_properties) - with open(file_path, "w", encoding="utf-8", newline="\n") as file: - json.dump(nested_data, file, ensure_ascii=False, indent=2) - file.write("\n") # Add trailing newline + with open(file_path, "wb") as file: + tomli_w.dump(nested_data, file) def update_missing_keys(reference_file, file_list, branch=""): """ Updates missing keys in the translation files based on the reference file. - :param reference_file: Path to the reference JSON file. + :param reference_file: Path to the reference TOML file. :param file_list: List of translation files to update. :param branch: Branch where the files are located. """ - reference_properties = parse_json_file(reference_file) + reference_properties = parse_toml_file(reference_file) for file_path in file_list: basename_current_file = os.path.basename(os.path.join(branch, file_path)) if ( basename_current_file == os.path.basename(reference_file) - or not file_path.endswith(".json") + or not file_path.endswith(".toml") or not os.path.dirname(file_path).endswith("locales") ): continue - current_properties = parse_json_file(os.path.join(branch, file_path)) + current_properties = parse_toml_file(os.path.join(branch, file_path)) updated_properties = {} for ref_key, ref_value in reference_properties.items(): @@ -141,16 +143,16 @@ def update_missing_keys(reference_file, file_list, branch=""): # Add missing key with reference value updated_properties[ref_key] = ref_value - write_json_file(os.path.join(branch, file_path), updated_properties) + write_toml_file(os.path.join(branch, file_path), updated_properties) def check_for_missing_keys(reference_file, file_list, branch): update_missing_keys(reference_file, file_list, branch) -def read_json_keys(file_path): +def read_toml_keys(file_path): if os.path.isfile(file_path) and os.path.exists(file_path): - return parse_json_file(file_path) + return parse_toml_file(file_path) return {} @@ -160,7 +162,7 @@ def check_for_differences(reference_file, file_list, branch, actor): report = [] report.append(f"#### 🔄 Reference Branch: `{reference_branch}`") - reference_keys = read_json_keys(reference_file) + reference_keys = read_toml_keys(reference_file) has_differences = False only_reference_file = True @@ -197,12 +199,12 @@ def check_for_differences(reference_file, file_list, branch, actor): ): continue - if not file_normpath.endswith(".json") or basename_current_file != "translation.json": + if not file_normpath.endswith(".toml") or basename_current_file != "translation.toml": continue only_reference_file = False report.append(f"#### 📃 **File Check:** `{locale_dir}/{basename_current_file}`") - current_keys = read_json_keys(os.path.join(branch, file_path)) + current_keys = read_toml_keys(os.path.join(branch, file_path)) reference_key_count = len(reference_keys) current_key_count = len(current_keys) @@ -272,7 +274,7 @@ def check_for_differences(reference_file, file_list, branch, actor): report.append("## ❌ Overall Check Status: **_Failed_**") report.append("") report.append( - f"@{actor} please check your translation if it conforms to the standard. Follow the format of [en-GB/translation.json](https://github.com/Stirling-Tools/Stirling-PDF/blob/V2/frontend/public/locales/en-GB/translation.json)" + f"@{actor} please check your translation if it conforms to the standard. Follow the format of [en-GB/translation.toml](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/public/locales/en-GB/translation.toml)" ) else: report.append("## ✅ Overall Check Status: **_Success_**") @@ -286,7 +288,7 @@ def check_for_differences(reference_file, file_list, branch, actor): if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Find missing keys") + parser = argparse.ArgumentParser(description="Find missing keys in TOML translation files") parser.add_argument( "--actor", required=False, @@ -337,9 +339,9 @@ if __name__ == "__main__": "public", "locales", "*", - "translation.json", + "translation.toml", ) ) update_missing_keys(args.reference_file, file_list) else: - check_for_differences(args.reference_file, file_list, args.branch, args.actor) \ No newline at end of file + check_for_differences(args.reference_file, file_list, args.branch, args.actor) diff --git a/.github/workflows/check_properties.yml b/.github/workflows/check_toml.yml similarity index 77% rename from .github/workflows/check_properties.yml rename to .github/workflows/check_toml.yml index 73232eee9..8fc1a75b8 100644 --- a/.github/workflows/check_properties.yml +++ b/.github/workflows/check_toml.yml @@ -1,19 +1,14 @@ -name: Check Properties Files on PR +name: Check TOML Translation Files on PR + +# This workflow validates TOML translation files on: pull_request_target: types: [opened, synchronize, reopened] paths: - - "app/core/src/main/resources/messages_*.properties" + - "frontend/public/locales/*/translation.toml" # cancel in-progress jobs if a new job is triggered -# This is useful to avoid running multiple builds for the same branch if a new commit is pushed -# or a pull request is updated. -# It helps to save resources and time by ensuring that only the latest commit is built and tested -# This is particularly useful for long-running jobs that may take a while to complete. -# The `group` is set to a combination of the workflow name, event name, and branch name. -# This ensures that jobs are grouped by the workflow and branch, allowing for cancellation of -# in-progress jobs when a new commit is pushed to the same branch or a new pull request is opened. concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref_name || github.ref }} cancel-in-progress: true @@ -73,22 +68,22 @@ jobs: run: | echo "Fetching PR changed files..." echo "Getting list of changed files from PR..." - # Check if PR number exists - if [ -z "${{ steps.get-pr-data.outputs.pr_number }}" ]; then - echo "Error: PR number is empty" - exit 1 - fi - # Get changed files and filter for properties files, handle case where no matches are found - gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^app/core/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt || echo "No matching properties files found in PR" - # Check if any files were found - if [ ! -s changed_files.txt ]; then - echo "No properties files changed in this PR" - echo "Workflow will exit early as no relevant files to check" - exit 0 - fi - echo "Found $(wc -l < changed_files.txt) matching properties files" + # Check if PR number exists + if [ -z "${{ steps.get-pr-data.outputs.pr_number }}" ]; then + echo "Error: PR number is empty" + exit 1 + fi + # Get changed files and filter for TOML translation files + gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^frontend/public/locales/[a-zA-Z-]+/translation\.toml$' > changed_files.txt || echo "No matching TOML files found in PR" + # Check if any files were found + if [ ! -s changed_files.txt ]; then + echo "No TOML translation files changed in this PR" + echo "Workflow will exit early as no relevant files to check" + exit 0 + fi + echo "Found $(wc -l < changed_files.txt) matching TOML files" - - name: Determine reference file test + - name: Determine reference file id: determine-file uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: @@ -125,11 +120,11 @@ jobs: pull_number: prNumber, }); - // Filter for relevant files based on the PR changes + // Filter for relevant TOML files based on the PR changes const changedFiles = files .filter(file => file.status !== "removed" && - /^app\/core\/src\/main\/resources\/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$/.test(file.filename) + /^frontend\/public\/locales\/[a-zA-Z-]+\/translation\.toml$/.test(file.filename) ) .map(file => file.filename); @@ -169,16 +164,16 @@ jobs: // Determine reference file let referenceFilePath; - if (changedFiles.includes("app/core/src/main/resources/messages_en_GB.properties")) { + if (changedFiles.includes("frontend/public/locales/en-GB/translation.toml")) { console.log("Using PR branch reference file."); const { data: fileContent } = await github.rest.repos.getContent({ owner: prRepoOwner, repo: prRepoName, - path: "app/core/src/main/resources/messages_en_GB.properties", + path: "frontend/public/locales/en-GB/translation.toml", ref: branch, }); - referenceFilePath = "pr-branch-messages_en_GB.properties"; + referenceFilePath = "pr-branch-translation-en-GB.toml"; const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); fs.writeFileSync(referenceFilePath, content); } else { @@ -186,11 +181,11 @@ jobs: const { data: fileContent } = await github.rest.repos.getContent({ owner: repoOwner, repo: repoName, - path: "app/core/src/main/resources/messages_en_GB.properties", + path: "frontend/public/locales/en-GB/translation.toml", ref: "main", }); - referenceFilePath = "main-branch-messages_en_GB.properties"; + referenceFilePath = "main-branch-translation-en-GB.toml"; const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); fs.writeFileSync(referenceFilePath, content); } @@ -198,11 +193,20 @@ jobs: console.log(`Reference file path: ${referenceFilePath}`); core.exportVariable("REFERENCE_FILE", referenceFilePath); + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: "3.12" + + - name: Install Python dependencies + run: | + pip install tomli-w + - name: Run Python script to check files id: run-check run: | - echo "Running Python script to check files..." - python .github/scripts/check_language_properties.py \ + echo "Running Python script to check TOML files..." + python .github/scripts/check_language_toml.py \ --actor ${{ github.event.pull_request.user.login }} \ --reference-file "${REFERENCE_FILE}" \ --branch "pr-branch" \ @@ -213,7 +217,7 @@ jobs: id: capture-output run: | if [ -f result.txt ] && [ -s result.txt ]; then - echo "Test, capturing output..." + echo "Capturing output..." SCRIPT_OUTPUT=$(cat result.txt) echo "SCRIPT_OUTPUT<> $GITHUB_ENV echo "$SCRIPT_OUTPUT" >> $GITHUB_ENV @@ -227,7 +231,7 @@ jobs: echo "FAIL_JOB=false" >> $GITHUB_ENV fi else - echo "No update found." + echo "No output found." echo "SCRIPT_OUTPUT=" >> $GITHUB_ENV echo "FAIL_JOB=false" >> $GITHUB_ENV fi @@ -249,7 +253,7 @@ jobs: issue_number: issueNumber }); - const comment = comments.data.find(c => c.body.includes("## 🚀 Translation Verification Summary")); + const comment = comments.data.find(c => c.body.includes("## 🌐 TOML Translation Verification Summary")); // Only update or create comments by the action user const expectedActor = "${{ steps.setup-bot.outputs.app-slug }}[bot]"; @@ -260,7 +264,7 @@ jobs: owner: repoOwner, repo: repoName, comment_id: comment.id, - body: `## 🚀 Translation Verification Summary\n\n\n${SCRIPT_OUTPUT}\n` + body: `## 🌐 TOML Translation Verification Summary\n\n\n${SCRIPT_OUTPUT}\n` }); console.log("Updated existing comment."); } else if (!comment) { @@ -269,7 +273,7 @@ jobs: owner: repoOwner, repo: repoName, issue_number: issueNumber, - body: `## 🚀 Translation Verification Summary\n\n\n${SCRIPT_OUTPUT}\n` + body: `## 🌐 TOML Translation Verification Summary\n\n\n${SCRIPT_OUTPUT}\n` }); console.log("Created new comment."); } else { @@ -287,6 +291,6 @@ jobs: run: | echo "Cleaning up temporary files..." rm -rf pr-branch - rm -f pr-branch-messages_en_GB.properties main-branch-messages_en_GB.properties changed_files.txt result.txt + rm -f pr-branch-translation-en-GB.toml main-branch-translation-en-GB.toml changed_files.txt result.txt echo "Cleanup complete." continue-on-error: true # Ensure cleanup runs even if previous steps fail diff --git a/.github/workflows/sync_files.yml b/.github/workflows/sync_files.yml deleted file mode 100644 index 1233ac701..000000000 --- a/.github/workflows/sync_files.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: Sync Files - -on: - workflow_dispatch: - push: - branches: - - main - paths: - - "build.gradle" - - "README.md" - - "app/core/src/main/resources/messages_*.properties" - - "app/core/src/main/resources/static/3rdPartyLicenses.json" - - "scripts/ignore_translation.toml" - -# cancel in-progress jobs if a new job is triggered -# This is useful to avoid running multiple builds for the same branch if a new commit is pushed -# or a pull request is updated. -# It helps to save resources and time by ensuring that only the latest commit is built and tested -# This is particularly useful for long-running jobs that may take a while to complete. -# The `group` is set to a combination of the workflow name, event name, and branch name. -# This ensures that jobs are grouped by the workflow and branch, allowing for cancellation of -# in-progress jobs when a new commit is pushed to the same branch or a new pull request is opened. -concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref_name || github.ref }} - cancel-in-progress: true - -permissions: - contents: read - -jobs: - sync-files: - runs-on: ubuntu-latest - env: - # Prevents sdist builds → no tar extraction - PIP_ONLY_BINARY: ":all:" - PIP_DISABLE_PIP_VERSION_CHECK: "1" - steps: - - name: Harden Runner - uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 - with: - egress-policy: audit - - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup GitHub App Bot - id: setup-bot - uses: ./.github/actions/setup-bot - with: - app-id: ${{ secrets.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 - with: - python-version: "3.12" - cache: "pip" # caching pip dependencies - - - name: Sync translation property files - run: | - python .github/scripts/check_language_properties.py --reference-file "app/core/src/main/resources/messages_en_GB.properties" --branch main - - - name: Commit translation files - run: | - git add app/core/src/main/resources/messages_*.properties - git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "No changes detected" - - - name: Install dependencies - # Wheels-only + Hash-Pinning - run: | - pip install --require-hashes --only-binary=:all: -r ./.github/scripts/requirements_sync_readme.txt - - - name: Sync README.md - run: | - python scripts/counter_translation.py - - - name: Run git add - run: | - git add README.md scripts/ignore_translation.toml - git diff --staged --quiet || git commit -m ":memo: Sync README.md & scripts/ignore_translation.toml" || echo "No changes detected" - - - name: Create Pull Request - if: always() - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 - with: - token: ${{ steps.setup-bot.outputs.token }} - commit-message: Update files - committer: ${{ steps.setup-bot.outputs.committer }} - author: ${{ steps.setup-bot.outputs.committer }} - signoff: true - branch: sync_readme - title: ":globe_with_meridians: Sync Translations + Update README Progress Table" - body: | - ### Description of Changes - - This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made: - - #### **1. Synchronization of Translation Files** - - Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`. - - Ensured consistency and synchronization across all supported language files. - - Highlighted any missing or incomplete translations. - - #### **2. Update README.md** - - Generated the translation progress table in `README.md`. - - Added a summary of the current translation status for all supported languages. - - Included up-to-date statistics on translation coverage. - - #### **Why these changes are necessary** - - Keeps translation files aligned with the latest reference updates. - - Ensures the documentation reflects the current translation progress. - - --- - - Auto-generated by [create-pull-request][1]. - - [1]: https://github.com/peter-evans/create-pull-request - draft: false - delete-branch: true - labels: github-actions - sign-commits: true - add-paths: | - README.md - app/core/src/main/resources/messages_*.properties diff --git a/.github/workflows/sync_files_v2.yml b/.github/workflows/sync_files_v2.yml index 84645c59e..935252be2 100644 --- a/.github/workflows/sync_files_v2.yml +++ b/.github/workflows/sync_files_v2.yml @@ -1,15 +1,15 @@ -name: Sync Files V2 +name: Sync Files (TOML) on: workflow_dispatch: push: branches: - - V2 + - main - syncLangTest paths: - "build.gradle" - "README.md" - - "frontend/public/locales/*/translation.json" + - "frontend/public/locales/*/translation.toml" - "app/core/src/main/resources/static/3rdPartyLicenses.json" - "scripts/ignore_translation.toml" @@ -52,21 +52,25 @@ jobs: python-version: "3.12" cache: "pip" # caching pip dependencies - - name: Sync translation JSON files + - name: Install Python dependencies run: | - python .github/scripts/check_language_json.py --reference-file "frontend/public/locales/en-GB/translation.json" --branch V2 + pip install tomli-w + + - name: Sync translation TOML files + run: | + python .github/scripts/check_language_toml.py --reference-file "frontend/public/locales/en-GB/translation.toml" --branch main - name: Commit translation files run: | - git add frontend/public/locales/*/translation.json - git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "No changes detected" + git add frontend/public/locales/*/translation.toml + git diff --staged --quiet || git commit -m ":memo: Sync translation files (TOML)" || echo "No changes detected" - - name: Install dependencies + - name: Install README dependencies run: pip install --require-hashes -r ./.github/scripts/requirements_sync_readme.txt - name: Sync README.md run: | - python scripts/counter_translation_v2.py + python scripts/counter_translation_v3.py - name: Run git add run: | @@ -82,21 +86,22 @@ jobs: committer: ${{ steps.setup-bot.outputs.committer }} author: ${{ steps.setup-bot.outputs.committer }} signoff: true - branch: sync_readme_v2 - base: V2 - title: ":globe_with_meridians: [V2] Sync Translations + Update README Progress Table" + branch: sync_readme_v3 + base: main + title: ":globe_with_meridians: Sync Translations + Update README Progress Table" body: | ### Description of Changes - This Pull Request was automatically generated to synchronize updates to translation files and documentation for the **V2 branch**. Below are the details of the changes made: + This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made: #### **1. Synchronization of Translation Files** - - Updated translation files (`frontend/public/locales/*/translation.json`) to reflect changes in the reference file `en-GB/translation.json`. + - Updated translation files (`frontend/public/locales/*/translation.toml`) to reflect changes in the reference file `en-GB/translation.toml`. - Ensured consistency and synchronization across all supported language files. - Highlighted any missing or incomplete translations. + - **Format**: TOML #### **2. Update README.md** - - Generated the translation progress table in `README.md`. + - Generated the translation progress table in `README.md` using `counter_translation_v3.py`. - Added a summary of the current translation status for all supported languages. - Included up-to-date statistics on translation coverage. @@ -115,4 +120,5 @@ jobs: sign-commits: true add-paths: | README.md - frontend/public/locales/*/translation.json \ No newline at end of file + frontend/public/locales/*/translation.toml + scripts/ignore_translation.toml \ No newline at end of file diff --git a/ADDING_TOOLS.md b/ADDING_TOOLS.md index ef1501bfc..d24641b00 100644 --- a/ADDING_TOOLS.md +++ b/ADDING_TOOLS.md @@ -202,10 +202,10 @@ const [ToolName] = (props: BaseToolProps) => { ## 5. Add Translations Update translation files. **Important: Only update `en-GB` files** - other languages are handled separately. -**File to update:** `frontend/public/locales/en-GB/translation.json` +**File to update:** `frontend/public/locales/en-GB/translation.toml` **Required Translation Keys**: -```json +```toml { "home": { "[toolName]": { @@ -251,7 +251,7 @@ Update translation files. **Important: Only update `en-GB` files** - other langu ``` **Translation Notes:** -- **Only update `en-GB/translation.json`** - other locale files are managed separately +- **Only update `en-GB/translation.toml`** - other locale files are managed separately - Use descriptive keys that match your component's `t()` calls - Include tooltip translations if you created tooltip hooks - Add `options.*` keys if your tool has settings with descriptions diff --git a/devGuide/HowToAddNewLanguage.md b/devGuide/HowToAddNewLanguage.md index 6a9ed17f2..861772576 100644 --- a/devGuide/HowToAddNewLanguage.md +++ b/devGuide/HowToAddNewLanguage.md @@ -8,36 +8,33 @@ Fork Stirling-PDF and create a new branch out of `main`. -Then add a reference to the language in the navbar by adding a new language entry to the dropdown: +## Frontend Translation Files (TOML Format) -- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/core/src/main/resources/templates/fragments/languages.html) +### Add Language Directory and Translation File +1. Create a new language directory in `frontend/public/locales/` + - Use hyphenated format: `pl-PL` (not underscore) -For example, to add Polish, you would add: +2. Copy the reference translation file: + - Source: `frontend/public/locales/en-GB/translation.toml` + - Destination: `frontend/public/locales/pl-PL/translation.toml` -```html -

-``` +3. Translate all entries in the TOML file + - Keep the TOML structure intact + - Preserve all placeholders like `{n}`, `{total}`, `{filename}`, `{{variable}}` + - See `scripts/translations/README.md` for translation tools and workflows -The `data-bs-language-code` is the code used to reference the file in the next step. +4. Update the language selector in the frontend to include your new language -### Add Language Property File - -Start by copying the existing English property file: - -- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/app/core/src/main/resources/messages_en_GB.properties) - -Copy and rename it to `messages_{your data-bs-language-code here}.properties`. In the Polish example, you would set the name to `messages_pl_PL.properties`. - -Then simply translate all property entries within that file and make a Pull Request (PR) into `main` for others to use! - -If you do not have a Java IDE, I am happy to verify that the changes work once you raise the PR (but I won't be able to verify the translations themselves). +Then make a Pull Request (PR) into `main` for others to use! ## Handling Untranslatable Strings -Sometimes, certain strings in the properties file may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations. +Sometimes, certain strings may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations. -For example, if the English string `error=Error` does not need translation in Polish, add it to the `ignore_translation.toml` under the Polish section: +For example, if the English string `error` does not need translation in Polish, add it to the `ignore_translation.toml` under the Polish section: + +**Note**: Use underscores in `ignore_translation.toml` even though frontend uses hyphens (e.g., `pl_PL` not `pl-PL`) ```toml [pl_PL] @@ -50,27 +47,27 @@ ignore = [ ## Add New Translation Tags > [!IMPORTANT] -> If you add any new translation tags, they must first be added to the `messages_en_GB.properties` file. This ensures consistency across all language files. +> If you add any new translation tags, they must first be added to the `en-GB/translation.toml` file. This ensures consistency across all language files. -- New translation tags **must be added** to the `messages_en_GB.properties` file to maintain a reference for other languages. -- After adding the new tags to `messages_en_GB.properties`, add and translate them in the respective language file (e.g., `messages_pl_PL.properties`). +- New translation tags **must be added** to `frontend/public/locales/en-GB/translation.toml` to maintain a reference for other languages. +- After adding the new tags to `en-GB/translation.toml`, add and translate them in the respective language file (e.g., `pl-PL/translation.toml`). +- Use the scripts in `scripts/translations/` to validate and manage translations (see `scripts/translations/README.md`) Make sure to place the entry under the correct language section. This helps maintain the accuracy of translation progress statistics and ensures that the translation tool or scripts do not misinterpret the completion rate. -### Use this code to perform a local check +### Validation Commands -#### Windows command - -```powershell -python .github/scripts/check_language_properties.py --reference-file app\core\src\main\resources\messages_en_GB.properties --branch "" --files app\core\src\main\resources\messages_pl_PL.properties - -python .github/scripts/check_language_properties.py --reference-file app\core\src\main\resources\messages_en_GB.properties --branch "" --check-file app\core\src\main\resources\messages_pl_PL.properties -``` - -#### Linux command +Use the translation scripts in `scripts/translations/` directory: ```bash -python3 .github/scripts/check_language_properties.py --reference-file app/core/src/main/resources/messages_en_GB.properties --branch "" --files app/core/src/main/resources/messages_pl_PL.properties +# Analyze translation progress +python3 scripts/translations/translation_analyzer.py --language pl-PL -python3 .github/scripts/check_language_properties.py --reference-file app/core/src/main/resources/messages_en_GB.properties --branch "" --check-file app/core/src/main/resources/messages_pl_PL.properties +# Validate TOML structure +python3 scripts/translations/validate_json_structure.py --language pl-PL + +# Validate placeholders +python3 scripts/translations/validate_placeholders.py --language pl-PL ``` + +See `scripts/translations/README.md` for complete documentation. diff --git a/frontend/public/locales/ar-AR/translation.toml b/frontend/public/locales/ar-AR/translation.toml index 0942b37b5..4c437dbf4 100644 --- a/frontend/public/locales/ar-AR/translation.toml +++ b/frontend/public/locales/ar-AR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "إزالة من المفضلة" fullscreen = "التبديل إلى وضع ملء الشاشة" sidebar = "التبديل إلى وضع الشريط الجانبي" +[backendStartup] +notFoundTitle = "لم يتم العثور على الخادم الخلفي" +retry = "إعادة المحاولة" +unreachable = "لا يمكن للتطبيق حالياً الاتصال بالخادم الخلفي. تحقق من حالة الخادم والاتصال بالشبكة، ثم حاول مرة أخرى." + [zipWarning] title = "ملف ZIP كبير" message = "هذا الملف ZIP يحتوي على {{count}} ملفات. هل تريد الاستخراج على أي حال؟" @@ -912,6 +917,9 @@ desc = "ابنِ تدفّقات عمل متعددة الخطوات بسلسلة desc = "تراكب ملف PDF فوق آخر" title = "تراكب ملفات PDF" +[home.pdfTextEditor] +title = "محرر نص PDF" +desc = "حرّر النصوص والصور الموجودة داخل ملفات PDF" [home.addText] tags = "نص,تعليق,تسمية" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "توقيع مرسوم" defaultImageLabel = "توقيع مرفوع" defaultTextLabel = "توقيع مكتوب" saveButton = "حفظ التوقيع" +savePersonal = "حفظ شخصي" +saveShared = "حفظ مشترك" saveUnavailable = "أنشئ توقيعاً أولاً لحفظه." noChanges = "التوقيع الحالي محفوظ بالفعل." +tempStorageTitle = "تخزين مؤقت في المتصفح" +tempStorageDescription = "يتم تخزين التواقيع في متصفحك فقط. ستُفقد إذا حذفت بيانات المتصفح أو بدّلت المتصفح." +personalHeading = "تواقيع شخصية" +sharedHeading = "تواقيع مشتركة" +personalDescription = "أنت فقط من يمكنه رؤية هذه التواقيع." +sharedDescription = "يمكن لجميع المستخدمين رؤية هذه التواقيع واستخدامها." [sign.saved.type] canvas = "رسم" @@ -3438,6 +3454,9 @@ signinTitle = "الرجاء تسجيل الدخول" ssoSignIn = "تسجيل الدخول عبر تسجيل الدخول الأحادي" oAuth2AutoCreateDisabled = "تم تعطيل الإنشاء التلقائي لمستخدم OAuth2" oAuth2AdminBlockedUser = "تم حظر تسجيل أو تسجيل دخول المستخدمين غير المسجلين حاليًا. يرجى الاتصال بالمسؤول." +oAuth2RequiresLicense = "يتطلب تسجيل الدخول عبر OAuth/SSO ترخيصاً مدفوعاً (Server أو Enterprise). يرجى الاتصال بالمسؤول لترقية باقتك." +saml2RequiresLicense = "يتطلب تسجيل الدخول عبر SAML ترخيصاً مدفوعاً (Server أو Enterprise). يرجى الاتصال بالمسؤول لترقية باقتك." +maxUsersReached = "تم الوصول إلى الحد الأقصى لعدد المستخدمين ضمن ترخيصك الحالي. يرجى الاتصال بالمسؤول لترقية باقتك أو إضافة مقاعد إضافية." oauth2RequestNotFound = "لم يتم العثور على طلب التفويض" oauth2InvalidUserInfoResponse = "استجابة معلومات المستخدم غير صالحة" oauth2invalidRequest = "طلب غير صالح" @@ -3771,7 +3790,7 @@ version = "الإصدار الحالي" title = "توثيق API" header = "توثيق API" desc = "عرض واختبار نقاط نهاية Stirling PDF API" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,توثيق,swagger,نقاط النهاية,تطوير" [cookieBanner.popUp] title = "كيف نستخدم ملفات تعريف الارتباط" @@ -3846,14 +3865,17 @@ fitToWidth = "ملاءمة للعرض" actualSize = "الحجم الفعلي" [viewer] +cannotPreviewFile = "لا يمكن معاينة الملف" +dualPageView = "عرض صفحتين" firstPage = "الصفحة الأولى" lastPage = "الصفحة الأخيرة" -previousPage = "الصفحة السابقة" nextPage = "الصفحة التالية" +onlyPdfSupported = "عارض الملفات يدعم ملفات PDF فقط. يبدو أن هذا الملف بتنسيق مختلف." +previousPage = "الصفحة السابقة" +singlePageView = "عرض صفحة واحدة" +unknownFile = "ملف غير معروف" zoomIn = "تكبير" zoomOut = "تصغير" -singlePageView = "عرض صفحة واحدة" -dualPageView = "عرض صفحتين" [rightRail] closeSelected = "إغلاق الصفحات المحددة" @@ -3877,6 +3899,7 @@ toggleSidebar = "تبديل الشريط الجانبي" exportSelected = "تصدير الصفحات المحددة" toggleAnnotations = "تبديل ظهور التعليقات التوضيحية" annotationMode = "تبديل وضع التعليقات" +print = "طباعة PDF" draw = "رسم" save = "حفظ" saveChanges = "حفظ التغييرات" @@ -4494,6 +4517,7 @@ description = "عنوان URL أو اسم الملف الخاص بـ Impressum ( title = "الممتاز والمؤسسي" description = "تهيئة مفتاح الترخيص للمزايا الممتازة أو المؤسسية." license = "تهيئة الترخيص" +noInput = "يرجى تقديم مفتاح ترخيص أو ملف" [admin.settings.premium.licenseKey] toggle = "هل لديك مفتاح ترخيص أو ملف شهادة؟" @@ -4511,6 +4535,25 @@ line1 = "لا يمكن التراجع عن استبدال مفتاح الترخ line2 = "سيُفقد ترخيصك السابق نهائياً ما لم تكن قد احتفظت بنسخة احتياطية منه في مكان آخر." line3 = "مهم: احتفظ بمفاتيح الترخيص خاصة وآمنة. لا تشاركها علناً أبداً." +[admin.settings.premium.inputMethod] +text = "مفتاح الترخيص" +file = "ملف الشهادة" + +[admin.settings.premium.file] +label = "ملف شهادة الترخيص" +description = "قم بتحميل ملف الترخيص .lic أو .cert من عمليات الشراء دون اتصال" +choose = "اختر ملف الترخيص" +selected = "المحدد: {{filename}} ({{size}})" +successMessage = "تم تحميل ملف الترخيص وتفعيله بنجاح. لا يلزم إعادة التشغيل." + +[admin.settings.premium.currentLicense] +title = "الترخيص النشط" +file = "المصدر: ملف الترخيص ({{path}})" +key = "المصدر: مفتاح الترخيص" +type = "النوع: {{type}}" +noInput = "يرجى تقديم مفتاح ترخيص أو تحميل ملف شهادة" +success = "نجاح" + [admin.settings.premium.enabled] label = "تمكين الميزات الممتازة" description = "تمكين التحقق من مفتاح الترخيص لميزات Pro/المؤسسة" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} محدد" download = "تنزيل" delete = "حذف" unsupported = "غير مدعوم" +active = "نشط" addToUpload = "إضافة إلى الرفع" +closeFile = "إغلاق الملف" deleteAll = "حذف الكل" loadingFiles = "جارٍ تحميل الملفات..." noFiles = "لا توجد ملفات متاحة" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "مطلوب عنوان بريد إلكتروني واحد على الأقل" submit = "إرسال الدعوات" success = "تمت دعوة المستخدم/المستخدمين بنجاح" -partialSuccess = "فشلت بعض الدعوات" +partialFailure = "فشل بعض الدعوات" allFailed = "فشلت دعوة المستخدمين" error = "فشل إرسال الدعوات" @@ -5797,6 +5842,13 @@ submit = "تسجيل الدخول" signInWith = "تسجيل الدخول باستخدام" oauthPending = "جارٍ فتح المتصفح للمصادقة..." orContinueWith = "أو المتابعة بالبريد الإلكتروني" +serverRequirement = "ملاحظة: يجب أن يكون تسجيل الدخول مفعّلاً على الخادم." +showInstructions = "كيفية التمكين؟" +hideInstructions = "إخفاء الإرشادات" +instructions = "لتمكين تسجيل الدخول على خادم Stirling PDF الخاص بك:" +instructionsEnvVar = "عيّن متغيّر البيئة:" +instructionsOrYml = "أو في settings.yml:" +instructionsRestart = "ثم أعد تشغيل الخادم لتصبح التغييرات نافذة." [setup.login.username] label = "اسم المستخدم" diff --git a/frontend/public/locales/az-AZ/translation.toml b/frontend/public/locales/az-AZ/translation.toml index d4c20aea6..092b0fda7 100644 --- a/frontend/public/locales/az-AZ/translation.toml +++ b/frontend/public/locales/az-AZ/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Seçilmişlərdən çıxar" fullscreen = "Tam ekran rejiminə keç" sidebar = "Yan panel rejiminə keç" +[backendStartup] +notFoundTitle = "Backend tapılmadı" +retry = "Yenidən cəhd et" +unreachable = "Tətbiq hazırda backend-ə qoşula bilmir. Backend-in vəziyyətini və şəbəkə bağlantısını yoxlayın, sonra yenidən cəhd edin." + [zipWarning] title = "Böyük ZIP faylı" message = "Bu ZIP {{count}} fayl ehtiva edir. Yenə də çıxarılsın?" @@ -912,6 +917,9 @@ desc = "PDF əməliyyatlarını zəncirləyərək çoxaddımlı iş axınları q desc = "Bir PDF-i digərinin üstünə qoyur" title = "Üst-Üstə Qoy" +[home.pdfTextEditor] +title = "PDF Mətn Redaktoru" +desc = "PDF-lərin içindəki mövcud mətn və şəkilləri redaktə edin" [home.addText] tags = "mətn,şərh,etiket" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Çəkilmiş imza" defaultImageLabel = "Yüklənmiş imza" defaultTextLabel = "Yazılmış imza" saveButton = "İmzanı saxla" +savePersonal = "Şəxsi yadda saxla" +saveShared = "Paylaşılanı yadda saxla" saveUnavailable = "Saxlamaq üçün əvvəlcə imza yaradın." noChanges = "Cari imza artıq saxlanıb." +tempStorageTitle = "Müvəqqəti brauzer yaddaşı" +tempStorageDescription = "İmzalar yalnız brauzerinizdə saxlanılır. Brauzer məlumatlarını təmizləsəniz və ya brauzer dəyişsəniz, itəcək." +personalHeading = "Şəxsi imzalar" +sharedHeading = "Paylaşılan imzalar" +personalDescription = "Bu imzaları yalnız siz görə bilirsiniz." +sharedDescription = "Bütün istifadəçilər bu imzaları görə və istifadə edə bilərlər." [sign.saved.type] canvas = "Rəsm" @@ -3438,6 +3454,9 @@ signinTitle = "Zəhmət olmasa, daxil olun" ssoSignIn = "Single Sign-on vasitəsilə daxil olun" oAuth2AutoCreateDisabled = "OAUTH2 Auto-Create İstifadəçisi Deaktivləşdirilmişdir" oAuth2AdminBlockedUser = "Qeydiyyatdan keçməmiş istifadəçilərin qeydiyyatı və daxil olması hal-hazırda bloklanmışdır. Zəhmət olmasa, administratorla əlaqə saxlayın." +oAuth2RequiresLicense = "OAuth/SSO ilə giriş üçün ödənişli lisenziya (Server və ya Enterprise) tələb olunur. Planınızı yüksəltmək üçün administratorla əlaqə saxlayın." +saml2RequiresLicense = "SAML ilə giriş üçün ödənişli lisenziya (Server və ya Enterprise) tələb olunur. Planınızı yüksəltmək üçün administratorla əlaqə saxlayın." +maxUsersReached = "Mövcud lisenziyanız üçün maksimum istifadəçi sayına çatılıb. Planınızı yüksəltmək və ya əlavə yerlər əlavə etmək üçün administratorla əlaqə saxlayın." oauth2RequestNotFound = "Təsdiqlənmə sorğusu tapılmadı" oauth2InvalidUserInfoResponse = "Yanlış İstifadəçi Məlumatı Cavabı" oauth2invalidRequest = "Etibarsız Sorğu" @@ -3846,14 +3865,17 @@ fitToWidth = "Eninə sığdır" actualSize = "Həqiqi ölçü" [viewer] +cannotPreviewFile = "Faylın önizlənməsi mümkün deyil" +dualPageView = "İki Səhifə Görünüşü" firstPage = "Birinci səhifə" lastPage = "Son səhifə" -previousPage = "Əvvəlki səhifə" nextPage = "Növbəti səhifə" +onlyPdfSupported = "Görüntüləyici yalnız PDF fayllarını dəstəkləyir. Bu fayl fərqli formatda görünür." +previousPage = "Əvvəlki səhifə" +singlePageView = "Tək Səhifə Görünüşü" +unknownFile = "Naməlum fayl" zoomIn = "Böyüt" zoomOut = "Kiçilt" -singlePageView = "Tək Səhifə Görünüşü" -dualPageView = "İki Səhifə Görünüşü" [rightRail] closeSelected = "Seçilmiş faylları bağla" @@ -3877,6 +3899,7 @@ toggleSidebar = "Yan paneli aç/bağla" exportSelected = "Seçilmiş səhifələri ixrac et" toggleAnnotations = "Annotasiyaların görünməsini dəyiş" annotationMode = "Annotasiya rejimini dəyiş" +print = "PDF-i çap et" draw = "Rəsm çək" save = "Yadda saxla" saveChanges = "Dəyişiklikləri yadda saxla" @@ -4407,7 +4430,7 @@ description = "Daha geniş sistem müvəqqəti qovluğunu təmizləyib-təmizlə label = "Proses İcraedicisi Limitləri" description = "Hər icraedici üçün sessiya limitlərini və taym-outları konfiqurasiya edin" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDF-dən HTML-ə" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4494,6 +4517,7 @@ description = "Impressum üçün URL və ya fayl adı (bəzi yurisdiksiyalarda t title = "Premium və Enterprise" description = "Premium və ya enterprise lisenziya açarınızı konfiqurasiya edin." license = "Lisenziya Konfiqurasiyası" +noInput = "Zəhmət olmasa lisenziya açarı və ya fayl təqdim edin" [admin.settings.premium.licenseKey] toggle = "Lisenziya açarınız və ya sertifikat faylınız var?" @@ -4511,6 +4535,25 @@ line1 = "Cari lisenziya açarının üzərinə yazmaq geri alına bilməz." line2 = "Ehtiyat nüsxəsi yoxdursa, əvvəlki lisenziyanız birdəfəlik itəcək." line3 = "Vacibdir: Lisenziya açarlarını məxfi və təhlükəsiz saxlayın. Heç vaxt onları ictimai paylaşmayın." +[admin.settings.premium.inputMethod] +text = "Lisenziya açarı" +file = "Sertifikat faylı" + +[admin.settings.premium.file] +label = "Lisenziya sertifikat faylı" +description = "Oflayn alışdan əldə etdiyiniz .lic və ya .cert lisenziya faylını yükləyin" +choose = "Lisenziya faylını seçin" +selected = "Seçildi: {{filename}} ({{size}})" +successMessage = "Lisenziya faylı uğurla yüklənib və aktivləşdirilib. Yenidən başlatmağa ehtiyac yoxdur." + +[admin.settings.premium.currentLicense] +title = "Aktiv lisenziya" +file = "Mənbə: Lisenziya faylı ({{path}})" +key = "Mənbə: Lisenziya açarı" +type = "Növ: {{type}}" +noInput = "Zəhmət olmasa lisenziya açarı verin və ya sertifikat faylı yükləyin" +success = "Uğurlu" + [admin.settings.premium.enabled] label = "Premium Xüsusiyyətlərini aktiv et" description = "Pro/enterprise xüsusiyyətləri üçün lisenziya açarı yoxlamalarını aktiv et" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} seçildi" download = "Endir" delete = "Sil" unsupported = "Dəstəklənmir" +active = "Aktiv" addToUpload = "Yükləməyə əlavə et" +closeFile = "Faylı bağla" deleteAll = "Hamısını sil" loadingFiles = "Fayllar yüklənir..." noFiles = "Fayl mövcud deyil" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Ən azı bir e-poçt ünvanı tələb olunur" submit = "Dəvətnamələri göndər" success = "istifadəçi(lər) uğurla dəvət olundu" -partialSuccess = "Bəzi dəvətnamələr alınmadı" +partialFailure = "Bəzi dəvətlər uğursuz oldu" allFailed = "İstifadəçiləri dəvət etmək alınmadı" error = "Dəvətnamələri göndərmək alınmadı" @@ -5288,8 +5333,8 @@ emailDisabled = "E-poçt dəvətləri üçün ayarlarda SMTP konfiqurasiyası v [workspace.people.license] users = "istifadəçi" availableSlots = "Mövcud yerlər" -grandfathered = "Grandfathered" -grandfatheredShort = "{{count}} grandfathered" +grandfathered = "Əvvəlki şərtlərlə" +grandfatheredShort = "{{count}} əvvəlki şərtlərlə" fromLicense = "lisenziyadan" slotsAvailable = "{{count}} istifadəçi yeri mövcuddur" noSlotsAvailable = "Mövcud yer yoxdur" @@ -5797,6 +5842,13 @@ submit = "Daxil ol" signInWith = "Bununla daxil ol" oauthPending = "Təsdiqləmə üçün brauzer açılır..." orContinueWith = "Və ya e-poçt ilə davam edin" +serverRequirement = "Qeyd: Serverdə giriş funksiyası aktiv olmalıdır." +showInstructions = "Necə aktivləşdirmək olar?" +hideInstructions = "Təlimatları gizlət" +instructions = "Stirling PDF serverinizdə girişi aktivləşdirmək üçün:" +instructionsEnvVar = "Mühit dəyişənini təyin edin:" +instructionsOrYml = "Və ya settings.yml faylında:" +instructionsRestart = "Dəyişikliklərin qüvvəyə minməsi üçün serveri yenidən başladın." [setup.login.username] label = "İstifadəçi adı" diff --git a/frontend/public/locales/bg-BG/translation.toml b/frontend/public/locales/bg-BG/translation.toml index 2d33576bf..13ae29767 100644 --- a/frontend/public/locales/bg-BG/translation.toml +++ b/frontend/public/locales/bg-BG/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Премахване от любими" fullscreen = "Превключване към режим на цял екран" sidebar = "Превключване към режим със странична лента" +[backendStartup] +notFoundTitle = "Бекендът не е намерен" +retry = "Опитай отново" +unreachable = "Приложението в момента не може да се свърже с бекенда. Проверете състоянието на бекенда и мрежовата свързаност, след което опитайте отново." + [zipWarning] title = "Голям ZIP файл" message = "Този ZIP съдържа {{count}} файла. Да се извлече въпреки това?" @@ -912,6 +917,9 @@ desc = "Създавайте многостъпкови работни проц desc = "Наслагва PDF файлове върху друг PDF" title = "Наслагване PDF-и" +[home.pdfTextEditor] +title = "Редактор на текст в PDF" +desc = "Редактирайте съществуващ текст и изображения в PDF файлове" [home.addText] tags = "текст,анотация,етикет" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Нарисуван подпис" defaultImageLabel = "Качен подпис" defaultTextLabel = "Въведен подпис" saveButton = "Запази подписа" +savePersonal = "Запази като личен" +saveShared = "Запази като споделен" saveUnavailable = "Първо създайте подпис, за да го запазите." noChanges = "Текущият подпис вече е запазен." +tempStorageTitle = "Временно съхранение в браузъра" +tempStorageDescription = "Подписите се съхраняват само във вашия браузър. Ще бъдат загубени, ако изчистите данните на браузъра или смените браузър." +personalHeading = "Лични подписи" +sharedHeading = "Споделени подписи" +personalDescription = "Само вие можете да виждате тези подписи." +sharedDescription = "Всички потребители могат да виждат и използват тези подписи." [sign.saved.type] canvas = "Рисунка" @@ -3438,6 +3454,9 @@ signinTitle = "Моля впишете се" ssoSignIn = "Влизане чрез еднократно влизане" oAuth2AutoCreateDisabled = "OAUTH2 Автоматично създаване на потребител е деактивирано" oAuth2AdminBlockedUser = "Регистрацията или влизането на нерегистрирани потребители в момента е блокирано. Моля, свържете се с администратора." +oAuth2RequiresLicense = "Вход с OAuth/SSO изисква платен лиценз (Server или Enterprise). Моля, свържете се с администратора, за да надстроите плана си." +saml2RequiresLicense = "Вход със SAML изисква платен лиценз (Server или Enterprise). Моля, свържете се с администратора, за да надстроите плана си." +maxUsersReached = "Достигнат е максималният брой потребители за текущия ви лиценз. Моля, свържете се с администратора, за да надстроите плана си или да добавите още места." oauth2RequestNotFound = "Заявката за оторизация не е намерена" oauth2InvalidUserInfoResponse = "Невалидна информация за потребителя" oauth2invalidRequest = "Невалидна заявка" @@ -3846,14 +3865,17 @@ fitToWidth = "Побиране по ширина" actualSize = "Действителен размер" [viewer] +cannotPreviewFile = "Не може да се визуализира файлът" +dualPageView = "Изглед: две страници" firstPage = "Първа страница" lastPage = "Последна страница" -previousPage = "Предишна страница" nextPage = "Следваща страница" +onlyPdfSupported = "Прегледачът поддържа само PDF файлове. Този файл изглежда е в друг формат." +previousPage = "Предишна страница" +singlePageView = "Изглед: една страница" +unknownFile = "Непознат файл" zoomIn = "Увеличи" zoomOut = "Намали" -singlePageView = "Изглед: една страница" -dualPageView = "Изглед: две страници" [rightRail] closeSelected = "Затвори избраните файлове" @@ -3877,6 +3899,7 @@ toggleSidebar = "Показване/скриване на страничната exportSelected = "Експорт на избраните страници" toggleAnnotations = "Показване/скриване на анотациите" annotationMode = "Превключи режим на анотации" +print = "Печат на PDF" draw = "Рисуване" save = "Запази" saveChanges = "Запази промените" @@ -4494,6 +4517,7 @@ description = "URL или име на файл към импресум (задъ title = "Премиум и Enterprise" description = "Конфигурирайте вашия премиум или enterprise лицензионен ключ." license = "Конфигурация на лиценз" +noInput = "Моля, предоставете лицензен ключ или файл" [admin.settings.premium.licenseKey] toggle = "Имате лицензен ключ или сертификат?" @@ -4511,6 +4535,25 @@ line1 = "Презаписването на текущия лицензен кл line2 = "Предишният лиценз ще бъде окончателно загубен, освен ако не сте го архивирали другаде." line3 = "Важно: Пазете лицензните ключове поверителни и сигурни. Никога не ги споделяйте публично." +[admin.settings.premium.inputMethod] +text = "Лицензен ключ" +file = "Файл със сертификат" + +[admin.settings.premium.file] +label = "Файл с лицензен сертификат" +description = "Качете вашия .lic или .cert лицензен файл от офлайн покупки" +choose = "Изберете лицензен файл" +selected = "Избрано: {{filename}} ({{size}})" +successMessage = "Лицензният файл беше качен и активиран успешно. Не е необходимо рестартиране." + +[admin.settings.premium.currentLicense] +title = "Активен лиценз" +file = "Източник: Лицензен файл ({{path}})" +key = "Източник: Лицензен ключ" +type = "Тип: {{type}}" +noInput = "Моля, предоставете лицензен ключ или качете файл със сертификат" +success = "Успешно" + [admin.settings.premium.enabled] label = "Активирай премиум функции" description = "Активира проверки на лицензионния ключ за pro/enterprise функции" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} избрани" download = "Изтегли" delete = "Изтрий" unsupported = "Неподдържано" +active = "Активен" addToUpload = "Добави към качването" +closeFile = "Затвори файла" deleteAll = "Изтрий всички" loadingFiles = "Зареждане на файлове..." noFiles = "Няма налични файлове" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Изисква се поне един имейл адрес" submit = "Изпрати покани" success = "Потребител(и) поканени успешно" -partialSuccess = "Някои покани не успяха" +partialFailure = "Някои покани бяха неуспешни" allFailed = "Неуспешно канене на потребители" error = "Неуспешно изпращане на покани" @@ -5797,6 +5842,13 @@ submit = "Вход" signInWith = "Вписване с" oauthPending = "Отваряне на браузър за удостоверяване..." orContinueWith = "Или продължете с имейл" +serverRequirement = "Забележка: Сървърът трябва да има активиран вход." +showInstructions = "Как да се активира?" +hideInstructions = "Скрий инструкциите" +instructions = "За да активирате вход на вашия Stirling PDF сървър:" +instructionsEnvVar = "Задайте променливата на средата:" +instructionsOrYml = "Или в settings.yml:" +instructionsRestart = "След това рестартирайте сървъра, за да влязат промените в сила." [setup.login.username] label = "Потребителско име" diff --git a/frontend/public/locales/ca-CA/translation.toml b/frontend/public/locales/ca-CA/translation.toml index 2d8bc23e3..85090e5a5 100644 --- a/frontend/public/locales/ca-CA/translation.toml +++ b/frontend/public/locales/ca-CA/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Elimina dels preferits" fullscreen = "Canvia al mode de pantalla completa" sidebar = "Canvia al mode de barra lateral" +[backendStartup] +notFoundTitle = "Backend no trobat" +retry = "Torneu-ho a intentar" +unreachable = "L'aplicació no pot connectar-se al backend ara mateix. Verifiqueu l'estat del backend i la connectivitat de xarxa i torneu-ho a intentar." + [zipWarning] title = "Fitxer ZIP gran" message = "Aquest ZIP conté {{count}} fitxers. Vols extreure'l igualment?" @@ -912,6 +917,9 @@ desc = "Construeix fluxos de treball multietapa enllaçant accions PDF. Ideal pe desc = "Superposa PDFs sobre un altre PDF" title = "Superposar PDFs" +[home.pdfTextEditor] +title = "Editor de text PDF" +desc = "Edita el text i les imatges existents dins dels PDF" [home.addText] tags = "text,anotació,etiqueta" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Signatura dibuixada" defaultImageLabel = "Signatura pujada" defaultTextLabel = "Signatura teclejada" saveButton = "Desa la signatura" +savePersonal = "Desa com a personal" +saveShared = "Desa com a compartida" saveUnavailable = "Crea una signatura primer per poder-la desar." noChanges = "La signatura actual ja està desada." +tempStorageTitle = "Emmagatzematge temporal del navegador" +tempStorageDescription = "Les signatures només s'emmagatzemen al vostre navegador. Es perdran si netegeu les dades del navegador o canvieu de navegador." +personalHeading = "Signatures personals" +sharedHeading = "Signatures compartides" +personalDescription = "Només vosaltres podeu veure aquestes signatures." +sharedDescription = "Tots els usuaris poden veure i utilitzar aquestes signatures." [sign.saved.type] canvas = "Dibuix" @@ -3438,6 +3454,9 @@ signinTitle = "Autenticat" ssoSignIn = "Inicia sessió mitjançant inici de sessió únic" oAuth2AutoCreateDisabled = "La creació automàtica d'usuaris OAUTH2 està desactivada" oAuth2AdminBlockedUser = "El registre o inici de sessió d'usuaris no registrats està actualment bloquejat. Si us plau, contacta amb l'administrador." +oAuth2RequiresLicense = "L'inici de sessió OAuth/SSO requereix una llicència de pagament (Server o Enterprise). Poseu-vos en contacte amb l'administrador per actualitzar el vostre pla." +saml2RequiresLicense = "L'inici de sessió SAML requereix una llicència de pagament (Server o Enterprise). Poseu-vos en contacte amb l'administrador per actualitzar el vostre pla." +maxUsersReached = "S'ha assolit el nombre màxim d'usuaris de la vostra llicència actual. Poseu-vos en contacte amb l'administrador per actualitzar el vostre pla o afegir més places." oauth2RequestNotFound = "Sol·licitud d'autorització no trobada" oauth2InvalidUserInfoResponse = "Resposta d'informació d'usuari no vàlida" oauth2invalidRequest = "Sol·licitud no vàlida" @@ -3846,14 +3865,17 @@ fitToWidth = "Ajusta a l'amplada" actualSize = "Mida real" [viewer] +cannotPreviewFile = "No es pot previsualitzar el fitxer" +dualPageView = "Vista de dues pàgines" firstPage = "Primera pàgina" lastPage = "Última pàgina" -previousPage = "Pàgina anterior" nextPage = "Pàgina següent" +onlyPdfSupported = "El visualitzador només admet fitxers PDF. Aquest fitxer sembla ser d'un format diferent." +previousPage = "Pàgina anterior" +singlePageView = "Vista d'una sola pàgina" +unknownFile = "Fitxer desconegut" zoomIn = "Amplia" zoomOut = "Redueix" -singlePageView = "Vista d'una sola pàgina" -dualPageView = "Vista de dues pàgines" [rightRail] closeSelected = "Tanca els fitxers seleccionats" @@ -3877,6 +3899,7 @@ toggleSidebar = "Mostra/oculta la barra lateral" exportSelected = "Exporta les pàgines seleccionades" toggleAnnotations = "Mostra/oculta les anotacions" annotationMode = "Activa/desactiva el mode d'anotació" +print = "Imprimeix el PDF" draw = "Dibuixa" save = "Desa" saveChanges = "Desa els canvis" @@ -3925,7 +3948,7 @@ files = "Fitxers" activity = "Registre" help = "Ajuda" account = "Compte" -config = "Config" +config = "Configuració" settings = "Ajustos" adminSettings = "Ajustos admin" allTools = "All Tools" @@ -4494,6 +4517,7 @@ description = "URL o nom de fitxer de l'impressum (requerit en algunes jurisdicc title = "Premium i Enterprise" description = "Configureu la clau de llicència Premium o Enterprise." license = "Configuració de llicència" +noInput = "Proporcioneu una clau de llicència o un fitxer" [admin.settings.premium.licenseKey] toggle = "Tens una clau de llicència o un fitxer de certificat?" @@ -4511,6 +4535,25 @@ line1 = "Sobreescriure la clau de llicència actual no es pot desfer." line2 = "La llicència anterior es perdrà permanentment si no en tens una còpia de seguretat." line3 = "Important: mantén les claus de llicència privades i segures. No les comparteixis mai públicament." +[admin.settings.premium.inputMethod] +text = "Clau de llicència" +file = "Fitxer de certificat" + +[admin.settings.premium.file] +label = "Fitxer de certificat de llicència" +description = "Pugeu el vostre fitxer de llicència .lic o .cert de compres fora de línia" +choose = "Trieu el fitxer de llicència" +selected = "Seleccionat: {{filename}} ({{size}})" +successMessage = "Fitxer de llicència pujat i activat correctament. No cal reiniciar." + +[admin.settings.premium.currentLicense] +title = "Llicència activa" +file = "Origen: Fitxer de llicència ({{path}})" +key = "Origen: Clau de llicència" +type = "Tipus: {{type}}" +noInput = "Proporcioneu una clau de llicència o pugeu un fitxer de certificat" +success = "Èxit" + [admin.settings.premium.enabled] label = "Habilita les funcions Premium" description = "Habilita les comprovacions de clau per a funcions pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} seleccionats" download = "Descarrega" delete = "Esborra" unsupported = "No compatible" +active = "Actiu" addToUpload = "Afegeix a la pujada" +closeFile = "Tanca el fitxer" deleteAll = "Suprimeix-ho tot" loadingFiles = "Carregant fitxers..." noFiles = "No hi ha fitxers disponibles" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Cal almenys una adreça de correu" submit = "Envia invitacions" success = "usuari(s) convidat(s) correctament" -partialSuccess = "Algunes invitacions han fallat" +partialFailure = "Algunes invitacions han fallat" allFailed = "No s’ha pogut convidar els usuaris" error = "No s’han pogut enviar les invitacions" @@ -5797,6 +5842,13 @@ submit = "Inicia sessió" signInWith = "Inicia sessió amb" oauthPending = "Obrint el navegador per autenticar-te..." orContinueWith = "O continua amb el correu electrònic" +serverRequirement = "Nota: el servidor ha de tenir l'inici de sessió habilitat." +showInstructions = "Com s'habilita?" +hideInstructions = "Amagueu les instruccions" +instructions = "Per habilitar l'inici de sessió al vostre servidor de Stirling PDF:" +instructionsEnvVar = "Establiu la variable d'entorn:" +instructionsOrYml = "O a settings.yml:" +instructionsRestart = "A continuació, reinicieu el servidor perquè els canvis tinguin efecte." [setup.login.username] label = "Nom d'usuari" diff --git a/frontend/public/locales/cs-CZ/translation.toml b/frontend/public/locales/cs-CZ/translation.toml index 0f80dd14b..d1ffd5b7f 100644 --- a/frontend/public/locales/cs-CZ/translation.toml +++ b/frontend/public/locales/cs-CZ/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Odebrat z oblíbených" fullscreen = "Přepnout na režim na celou obrazovku" sidebar = "Přepnout na režim postranního panelu" +[backendStartup] +notFoundTitle = "Backend nebyl nalezen" +retry = "Zkusit znovu" +unreachable = "Aplikace se nyní nemůže připojit k backendu. Ověřte stav backendu a síťové připojení a poté to zkuste znovu." + [zipWarning] title = "Velký soubor ZIP" message = "Tento ZIP obsahuje {{count}} souborů. Přesto rozbalit?" @@ -347,7 +352,7 @@ teams = "Týmy" title = "Konfigurace" systemSettings = "Systémová nastavení" features = "Funkce" -endpoints = "Endpoints" +endpoints = "Koncové body" database = "Databáze" advanced = "Pokročilé" @@ -912,6 +917,9 @@ desc = "Vytvářejte vícekrokové workflow řetězením akcí PDF. Ideální pr desc = "Překryje PDF nad jiným PDF" title = "Překrýt PDF" +[home.pdfTextEditor] +title = "Editor textu PDF" +desc = "Upravujte existující text a obrázky v PDF" [home.addText] tags = "text,anotace,štítek" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Nakreslený podpis" defaultImageLabel = "Nahraný podpis" defaultTextLabel = "Napsaný podpis" saveButton = "Uložit podpis" +savePersonal = "Uložit osobní" +saveShared = "Uložit sdílené" saveUnavailable = "Nejprve vytvořte podpis, abyste jej mohli uložit." noChanges = "Aktuální podpis je již uložen." +tempStorageTitle = "Dočasné úložiště prohlížeče" +tempStorageDescription = "Podpisy jsou uloženy pouze ve vašem prohlížeči. Při vymazání dat prohlížeče nebo při přepnutí na jiný prohlížeč budou ztraceny." +personalHeading = "Osobní podpisy" +sharedHeading = "Sdílené podpisy" +personalDescription = "Tyto podpisy vidíte pouze vy." +sharedDescription = "Všichni uživatelé mohou tyto podpisy vidět a používat." [sign.saved.type] canvas = "Kresba" @@ -3438,6 +3454,9 @@ signinTitle = "Prosím přihlaste se" ssoSignIn = "Přihlásit se přes Single Sign-on" oAuth2AutoCreateDisabled = "Automatické vytváření OAUTH2 uživatelů je zakázáno" oAuth2AdminBlockedUser = "Registrace nebo přihlášení neregistrovaných uživatelů je momentálně blokováno. Kontaktujte prosím správce." +oAuth2RequiresLicense = "Přihlášení pomocí OAuth/SSO vyžaduje placenou licenci (Server nebo Enterprise). Kontaktujte prosím administrátora kvůli upgradu vašeho plánu." +saml2RequiresLicense = "Přihlášení pomocí SAML vyžaduje placenou licenci (Server nebo Enterprise). Kontaktujte prosím administrátora kvůli upgradu vašeho plánu." +maxUsersReached = "Byl dosažen maximální počet uživatelů pro vaši aktuální licenci. Kontaktujte prosím administrátora kvůli upgradu vašeho plánu nebo přidání dalších míst." oauth2RequestNotFound = "Požadavek na autorizaci nebyl nalezen" oauth2InvalidUserInfoResponse = "Neplatná odpověď s informacemi o uživateli" oauth2invalidRequest = "Neplatný požadavek" @@ -3846,14 +3865,17 @@ fitToWidth = "Přizpůsobit šířce" actualSize = "Skutečná velikost" [viewer] +cannotPreviewFile = "Nelze zobrazit náhled souboru" +dualPageView = "Zobrazení dvou stránek" firstPage = "První stránka" lastPage = "Poslední stránka" -previousPage = "Předchozí stránka" nextPage = "Další stránka" +onlyPdfSupported = "Prohlížeč podporuje pouze soubory PDF. Tento soubor má zřejmě jiný formát." +previousPage = "Předchozí stránka" +singlePageView = "Zobrazení jedné stránky" +unknownFile = "Neznámý soubor" zoomIn = "Přiblížit" zoomOut = "Oddálit" -singlePageView = "Zobrazení jedné stránky" -dualPageView = "Zobrazení dvou stránek" [rightRail] closeSelected = "Zavřít vybrané soubory" @@ -3877,6 +3899,7 @@ toggleSidebar = "Přepnout postranní panel" exportSelected = "Exportovat vybrané stránky" toggleAnnotations = "Přepnout viditelnost anotací" annotationMode = "Přepnout režim anotací" +print = "Tisk PDF" draw = "Kreslit" save = "Uložit" saveChanges = "Uložit změny" @@ -4494,6 +4517,7 @@ description = "URL nebo název souboru k Impressu (vyžadováno v některých ju title = "Premium a Enterprise" description = "Nakonfigurujte svůj prémiový nebo enterprise licenční klíč." license = "Konfigurace licence" +noInput = "Zadejte licenční klíč nebo soubor" [admin.settings.premium.licenseKey] toggle = "Máte licenční klíč nebo certifikační soubor?" @@ -4511,6 +4535,25 @@ line1 = "Přepsání aktuálního licenčního klíče nelze vrátit zpět." line2 = "Předchozí licence bude trvale ztracena, pokud ji nemáte zálohovanou jinde." line3 = "Důležité: Uchovávejte licenční klíče v soukromí a v bezpečí. Nikdy je nesdílejte veřejně." +[admin.settings.premium.inputMethod] +text = "Licenční klíč" +file = "Soubor certifikátu" + +[admin.settings.premium.file] +label = "Soubor licenčního certifikátu" +description = "Nahrajte svůj licenční soubor .lic nebo .cert z offline nákupu" +choose = "Vybrat licenční soubor" +selected = "Vybráno: {{filename}} ({{size}})" +successMessage = "Licenční soubor byl úspěšně nahrán a aktivován. Restart není vyžadován." + +[admin.settings.premium.currentLicense] +title = "Aktivní licence" +file = "Zdroj: Licenční soubor ({{path}})" +key = "Zdroj: Licenční klíč" +type = "Typ: {{type}}" +noInput = "Zadejte licenční klíč nebo nahrajte soubor certifikátu" +success = "Úspěch" + [admin.settings.premium.enabled] label = "Povolit prémiové funkce" description = "Povolit kontrolu licenčního klíče pro pro/enterprise funkce" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} vybráno" download = "Stáhnout" delete = "Smazat" unsupported = "Nepodporováno" +active = "Aktivní" addToUpload = "Přidat k nahrání" +closeFile = "Zavřít soubor" deleteAll = "Smazat vše" loadingFiles = "Načítání souborů..." noFiles = "Nejsou k dispozici žádné soubory" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "uzivatel1@priklad.cz, uzivatel2@priklad.cz" emailsRequired = "Je vyžadována alespoň jedna e‑mailová adresa" submit = "Odeslat pozvánky" success = "uživatel(é) úspěšně pozváni" -partialSuccess = "Některé pozvánky se nepodařilo odeslat" +partialFailure = "Některá pozvání selhala" allFailed = "Nepodařilo se pozvat uživatele" error = "Nepodařilo se odeslat pozvánky" @@ -5709,7 +5754,7 @@ title = "Graf využití endpointů" [usage.table] title = "Podrobné statistiky" -endpoint = "Endpoint" +endpoint = "Koncový bod" visits = "Návštěvy" percentage = "Procenta" noData = "Žádná data nejsou k dispozici" @@ -5797,6 +5842,13 @@ submit = "Přihlásit se" signInWith = "Přihlásit se pomocí" oauthPending = "Otevírám prohlížeč pro ověření..." orContinueWith = "Nebo pokračovat e-mailem" +serverRequirement = "Poznámka: Na serveru musí být povoleno přihlášení." +showInstructions = "Jak povolit?" +hideInstructions = "Skrýt pokyny" +instructions = "Chcete-li povolit přihlášení na vašem serveru Stirling PDF:" +instructionsEnvVar = "Nastavte proměnnou prostředí:" +instructionsOrYml = "Nebo v settings.yml:" +instructionsRestart = "Poté restartujte server, aby se změny projevily." [setup.login.username] label = "Uživatelské jméno" @@ -5840,7 +5892,7 @@ paragraph = "Odstavcová stránka" sparse = "Řídký text" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automaticky" paragraph = "Odstavec" singleLine = "Jeden řádek" @@ -5932,13 +5984,13 @@ warnings = "Varování" suggestions = "Poznámky" currentPageFonts = "Fonty na této stránce" allFonts = "Všechny fonty" -fallback = "fallback" +fallback = "náhradní" missing = "chybí" perfectMessage = "Všechny fonty lze reprodukovat dokonale." warningMessage = "Některé fonty se nemusí vykreslit správně." infoMessage = "K dispozici jsou informace o reprodukci fontů." -perfect = "perfect" -subset = "subset" +perfect = "dokonalé" +subset = "podmnožina" [pdfTextEditor.errors] invalidJson = "Nelze přečíst soubor JSON. Ujistěte se, že byl vytvořen nástrojem PDF to JSON." diff --git a/frontend/public/locales/da-DK/translation.toml b/frontend/public/locales/da-DK/translation.toml index bc44aa479..d3a6cca28 100644 --- a/frontend/public/locales/da-DK/translation.toml +++ b/frontend/public/locales/da-DK/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Fjern fra favoritter" fullscreen = "Skift til fuldskærmstilstand" sidebar = "Skift til sidepanel-tilstand" +[backendStartup] +notFoundTitle = "Backend ikke fundet" +retry = "Prøv igen" +unreachable = "Programmet kan i øjeblikket ikke forbinde til backend. Kontroller backend-status og netværksforbindelse, og prøv igen." + [zipWarning] title = "Stor ZIP-fil" message = "Denne ZIP indeholder {{count}} filer. Udpak alligevel?" @@ -347,7 +352,7 @@ teams = "Teams" title = "Konfiguration" systemSettings = "Systemindstillinger" features = "Funktioner" -endpoints = "Endpoints" +endpoints = "Slutpunkter" database = "Database" advanced = "Avanceret" @@ -359,7 +364,7 @@ connections = "Forbindelser" [settings.licensingAnalytics] title = "Licensering & Analytics" plan = "Plan" -audit = "Audit" +audit = "Revision" usageAnalytics = "Brugsanalyse" [settings.policiesPrivacy] @@ -556,13 +561,13 @@ totalEndpoints = "Endpoints i alt" totalVisits = "Besøg i alt" showing = "Viser" selectedVisits = "Valgte besøg" -endpoint = "Endpoint" +endpoint = "Slutpunkt" visits = "Besøg" percentage = "Procent" loading = "Laster..." failedToLoad = "Kunne ikke indlæse endpoint-data. Prøv at opdatere." home = "Hjem" -login = "Login" +login = "Log ind" top = "Top" numberOfVisits = "Antal besøg" visitsTooltip = "Besøg: {0} ({1}% af totalen)" @@ -912,6 +917,9 @@ desc = "Byg flertrins-workflows ved at kæde PDF-handlinger sammen. Ideelt til t desc = "Overlejrer PDF'er oven på en anden PDF" title = "Overlejr PDF'er" +[home.pdfTextEditor] +title = "PDF-teksteditor" +desc = "Rediger eksisterende tekst og billeder i PDF'er" [home.addText] tags = "tekst,annotering,etiket" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "Vælg filer i hovedvisningen for at komme i gang" settings = "Indstillinger" conversionCompleted = "Konvertering fuldført" results = "Resultater" -defaultFilename = "converted_file" +defaultFilename = "konverteret_fil" conversionResults = "Konverteringsresultater" convertFrom = "Konvertér fra" convertTo = "Konvertér til" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Tegnet signatur" defaultImageLabel = "Uploadet signatur" defaultTextLabel = "Indtastet signatur" saveButton = "Gem signatur" +savePersonal = "Gem personlig" +saveShared = "Gem delt" saveUnavailable = "Opret først en signatur for at gemme den." noChanges = "Nuværende signatur er allerede gemt." +tempStorageTitle = "Midlertidig browserlagring" +tempStorageDescription = "Signaturer gemmes kun i din browser. De går tabt, hvis du rydder browserdata eller skifter browser." +personalHeading = "Personlige signaturer" +sharedHeading = "Delte signaturer" +personalDescription = "Kun du kan se disse signaturer." +sharedDescription = "Alle brugere kan se og bruge disse signaturer." [sign.saved.type] canvas = "Tegning" @@ -3438,6 +3454,9 @@ signinTitle = "Log venligst ind" ssoSignIn = "Log ind via Single Sign-on" oAuth2AutoCreateDisabled = "OAUTH2 Auto-Opret Bruger Deaktiveret" oAuth2AdminBlockedUser = "Registrering eller login af ikke-registrerede brugere er i øjeblikket blokeret. Kontakt venligst administratoren." +oAuth2RequiresLicense = "OAuth/SSO-login kræver en betalt licens (Server eller Enterprise). Kontakt administratoren for at opgradere din plan." +saml2RequiresLicense = "SAML-login kræver en betalt licens (Server eller Enterprise). Kontakt administratoren for at opgradere din plan." +maxUsersReached = "Maksimalt antal brugere er nået for din nuværende licens. Kontakt administratoren for at opgradere din plan eller tilføje flere pladser." oauth2RequestNotFound = "Autorisationsanmodning ikke fundet" oauth2InvalidUserInfoResponse = "Ugyldigt Brugerinfo Svar" oauth2invalidRequest = "Ugyldig Anmodning" @@ -3846,14 +3865,17 @@ fitToWidth = "Tilpas til bredde" actualSize = "Faktisk størrelse" [viewer] +cannotPreviewFile = "Kan ikke forhåndsvise fil" +dualPageView = "To-siders visning" firstPage = "Første side" lastPage = "Sidste side" -previousPage = "Forrige side" nextPage = "Næste side" +onlyPdfSupported = "Visningen understøtter kun PDF-filer. Denne fil ser ud til at være et andet format." +previousPage = "Forrige side" +singlePageView = "Enkelt-sides visning" +unknownFile = "Ukendt fil" zoomIn = "Zoom ind" zoomOut = "Zoom ud" -singlePageView = "Enkelt-sides visning" -dualPageView = "To-siders visning" [rightRail] closeSelected = "Luk valgte filer" @@ -3877,6 +3899,7 @@ toggleSidebar = "Skift sidepanel" exportSelected = "Eksporter valgte sider" toggleAnnotations = "Skift visning af annoteringer" annotationMode = "Skift annoteringstilstand" +print = "Udskriv PDF" draw = "Tegn" save = "Gem" saveChanges = "Gem ændringer" @@ -4343,7 +4366,7 @@ features = "Funktionsflag" processing = "Behandling" [admin.settings.advanced.endpoints] -label = "Endpoints" +label = "Slutpunkter" manage = "Administrer API-endpoints" description = "Endpointstyring konfigureres via YAML. Se dokumentationen for detaljer om aktivering/deaktivering af specifikke endpoints." @@ -4494,6 +4517,7 @@ description = "URL eller filnavn til impressum (påkrævet i nogle jurisdiktione title = "Premium og Enterprise" description = "Konfigurer din premium- eller enterprise-licensnøgle." license = "Licenskonfiguration" +noInput = "Angiv en licensnøgle eller fil" [admin.settings.premium.licenseKey] toggle = "Har du en licensnøgle eller en certifikatfil?" @@ -4511,6 +4535,25 @@ line1 = "Overskrivning af din nuværende licensnøgle kan ikke fortrydes." line2 = "Din tidligere licens går permanent tabt, medmindre du har sikkerhedskopieret den andetsteds." line3 = "Vigtigt: Hold licensnøgler private og sikre. Del dem aldrig offentligt." +[admin.settings.premium.inputMethod] +text = "Licensnøgle" +file = "Certifikatfil" + +[admin.settings.premium.file] +label = "Licenscertifikatfil" +description = "Upload din .lic- eller .cert-licensfil fra offlinekøb" +choose = "Vælg licensfil" +selected = "Valgt: {{filename}} ({{size}})" +successMessage = "Licensfil uploadet og aktiveret. Genstart er ikke påkrævet." + +[admin.settings.premium.currentLicense] +title = "Aktiv licens" +file = "Kilde: Licensfil ({{path}})" +key = "Kilde: Licensnøgle" +type = "Type: {{type}}" +noInput = "Angiv en licensnøgle eller upload en certifikatfil" +success = "Succes" + [admin.settings.premium.enabled] label = "Aktivér premium-funktioner" description = "Aktivér licensnøgletjek for pro-/enterprise-funktioner" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} valgt" download = "Download" delete = "Slet" unsupported = "Ikke understøttet" +active = "Aktiv" addToUpload = "Føj til upload" +closeFile = "Luk fil" deleteAll = "Slet alle" loadingFiles = "Indlæser filer..." noFiles = "Ingen filer tilgængelige" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Mindst én e-mailadresse er påkrævet" submit = "Send invitationer" success = "Bruger(e) inviteret" -partialSuccess = "Nogle invitationer mislykkedes" +partialFailure = "Nogle invitationer mislykkedes" allFailed = "Kunne ikke invitere brugere" error = "Kunne ikke sende invitationer" @@ -5288,8 +5333,8 @@ emailDisabled = "E-mailinvitationer kræver SMTP-konfiguration og mail.enableInv [workspace.people.license] users = "brugere" availableSlots = "Tilgængelige pladser" -grandfathered = "Grandfathered" -grandfatheredShort = "{{count}} grandfathered" +grandfathered = "På gamle vilkår" +grandfatheredShort = "{{count}} på gamle vilkår" fromLicense = "fra licens" slotsAvailable = "{{count}} ledig(e) brugerplads(er)" noSlotsAvailable = "Ingen pladser tilgængelige" @@ -5709,7 +5754,7 @@ title = "Diagram over endpoint-brug" [usage.table] title = "Detaljeret statistik" -endpoint = "Endpoint" +endpoint = "Slutpunkt" visits = "Besøg" percentage = "Procent" noData = "Ingen data tilgængelige" @@ -5752,7 +5797,7 @@ label = "Vælg server" description = "Selvhostet server" [setup.step3] -label = "Login" +label = "Log ind" description = "Indtast loginoplysninger" [setup.mode.saas] @@ -5797,6 +5842,13 @@ submit = "Log ind" signInWith = "Log ind med" oauthPending = "Åbner browser for godkendelse..." orContinueWith = "Eller fortsæt med email" +serverRequirement = "Bemærk: Serveren skal have login aktiveret." +showInstructions = "Hvordan aktiveres det?" +hideInstructions = "Skjul instruktioner" +instructions = "Sådan aktiverer du login på din Stirling PDF-server:" +instructionsEnvVar = "Sæt miljøvariablen:" +instructionsOrYml = "Eller i settings.yml:" +instructionsRestart = "Genstart derefter serveren, så ændringerne træder i kraft." [setup.login.username] label = "Brugernavn" diff --git a/frontend/public/locales/de-DE/translation.toml b/frontend/public/locales/de-DE/translation.toml index c8c8e6f71..70dcf86b2 100644 --- a/frontend/public/locales/de-DE/translation.toml +++ b/frontend/public/locales/de-DE/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Aus Favoriten entfernen" fullscreen = "In den Vollbildmodus wechseln" sidebar = "In den Seitenleistenmodus wechseln" +[backendStartup] +notFoundTitle = "Backend nicht gefunden" +retry = "Erneut versuchen" +unreachable = "Die Anwendung kann derzeit keine Verbindung zum Backend herstellen. Überprüfen Sie den Backend-Status und die Netzwerkverbindung und versuchen Sie es dann erneut." + [zipWarning] title = "Große ZIP-Datei" message = "Dieses ZIP enthält {{count}} Dateien. Trotzdem extrahieren?" @@ -347,7 +352,7 @@ teams = "Teams" title = "Konfiguration" systemSettings = "Systemeinstellungen" features = "Funktionen" -endpoints = "Endpoints" +endpoints = "Endpunkte" database = "Datenbank" advanced = "Erweitert" @@ -383,7 +388,7 @@ logout = "Abmelden" [settings.connection.mode] saas = "Stirling Cloud" -selfhosted = "Self-Hosted" +selfhosted = "Selbst gehostet" [settings.general] title = "Allgemein" @@ -612,7 +617,7 @@ desc = "Anzeigen, Kommentieren, Text oder Bilder hinzufügen" brandAlt = "Stirling PDF-Logo" openFiles = "Dateien öffnen" swipeHint = "Zum Wechseln der Ansicht nach links oder rechts wischen" -tools = "Tools" +tools = "Werkzeuge" toolsSlide = "Bereich für Toolauswahl" viewSwitcher = "Ansicht des Arbeitsbereichs wechseln" workbenchSlide = "Arbeitsbereichs-Panel" @@ -912,9 +917,12 @@ desc = "Mehrstufige Arbeitsabläufe durch Verkettung von PDF-Aktionen erstellen. desc = "Ein PDF über ein anderes legen" title = "PDFs überlagern" +[home.pdfTextEditor] +title = "PDF-Texteditor" +desc = "Vorhandenen Text und Bilder in PDFs bearbeiten" [home.addText] -tags = "text,annotation,label" +tags = "text,anmerkung,beschriftung" title = "Text hinzufügen" desc = "Beliebigen Text überall in Ihrem PDF hinzufügen" @@ -1213,7 +1221,7 @@ pdfaDigitalSignatureWarning = "Das PDF enthält eine digitale Signatur. Sie wird fileFormat = "Dateiformat" wordDoc = "Word-Dokument" wordDocExt = "Word-Dokument (.docx)" -odtExt = "OpenDocument Text (.odt)" +odtExt = "OpenDocument-Text (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "OpenDocument Präsentation (.odp)" txtExt = "Einfacher Text (.txt)" @@ -2259,12 +2267,20 @@ defaultCanvasLabel = "Gezeichnete Unterschrift" defaultImageLabel = "Hochgeladene Unterschrift" defaultTextLabel = "Getippte Unterschrift" saveButton = "Unterschrift speichern" +savePersonal = "Persönlich speichern" +saveShared = "Geteilt speichern" saveUnavailable = "Erstellen Sie zuerst eine Unterschrift, um sie zu speichern." noChanges = "Die aktuelle Unterschrift ist bereits gespeichert." +tempStorageTitle = "Temporärer Browser-Speicher" +tempStorageDescription = "Signaturen werden nur in Ihrem Browser gespeichert. Sie gehen verloren, wenn Sie Browserdaten löschen oder den Browser wechseln." +personalHeading = "Persönliche Signaturen" +sharedHeading = "Geteilte Signaturen" +personalDescription = "Nur Sie können diese Signaturen sehen." +sharedDescription = "Alle Benutzer können diese Signaturen sehen und verwenden." [sign.saved.type] canvas = "Zeichnung" -image = "Upload" +image = "Hochladen" text = "Text" [sign.saved.status] @@ -3438,6 +3454,9 @@ signinTitle = "Bitte melden Sie sich an." ssoSignIn = "Anmeldung per Single Sign-On" oAuth2AutoCreateDisabled = "OAUTH2 Benutzer automatisch erstellen deaktiviert" oAuth2AdminBlockedUser = "Die Registrierung bzw. das anmelden von nicht registrierten Benutzern ist derzeit gesperrt. Bitte wenden Sie sich an den Administrator." +oAuth2RequiresLicense = "OAuth/SSO-Anmeldung erfordert eine kostenpflichtige Lizenz (Server oder Enterprise). Bitte wenden Sie sich an den Administrator, um Ihren Plan zu aktualisieren." +saml2RequiresLicense = "SAML-Anmeldung erfordert eine kostenpflichtige Lizenz (Server oder Enterprise). Bitte wenden Sie sich an den Administrator, um Ihren Plan zu aktualisieren." +maxUsersReached = "Die maximale Benutzeranzahl für Ihre aktuelle Lizenz wurde erreicht. Bitte wenden Sie sich an den Administrator, um Ihren Plan zu aktualisieren oder weitere Benutzerplätze hinzuzufügen." oauth2RequestNotFound = "Autorisierungsanfrage nicht gefunden" oauth2InvalidUserInfoResponse = "Ungültige Benutzerinformationsantwort" oauth2invalidRequest = "ungültige Anfrage" @@ -3846,14 +3865,17 @@ fitToWidth = "An Breite anpassen" actualSize = "Originalgröße" [viewer] +cannotPreviewFile = "Datei kann nicht in der Vorschau angezeigt werden" +dualPageView = "Doppelseitenansicht" firstPage = "Erste Seite" lastPage = "Letzte Seite" -previousPage = "Vorherige Seite" nextPage = "Nächste Seite" +onlyPdfSupported = "Der Viewer unterstützt nur PDF-Dateien. Diese Datei scheint ein anderes Format zu haben." +previousPage = "Vorherige Seite" +singlePageView = "Einzelseitenansicht" +unknownFile = "Unbekannte Datei" zoomIn = "Vergrößern" zoomOut = "Verkleinern" -singlePageView = "Einzelseitenansicht" -dualPageView = "Doppelseitenansicht" [rightRail] closeSelected = "Ausgewählte Dateien schließen" @@ -3877,6 +3899,7 @@ toggleSidebar = "Seitenleiste umschalten" exportSelected = "Ausgewählte Seiten exportieren" toggleAnnotations = "Anmerkungen ein-/ausblenden" annotationMode = "Anmerkungsmodus umschalten" +print = "PDF drucken" draw = "Zeichnen" save = "Speichern" saveChanges = "Änderungen speichern" @@ -3928,7 +3951,7 @@ account = "Konto" config = "Konfig" settings = "Optionen" adminSettings = "Admin Optionen" -allTools = "Tools" +allTools = "Werkzeuge" reader = "Reader" [quickAccess.helpMenu] @@ -4494,6 +4517,7 @@ description = "URL oder Dateiname zum Impressum (in einigen Rechtsordnungen erfo title = "Premium & Enterprise" description = "Ihren Premium- oder Enterprise-Lizenzschlüssel konfigurieren." license = "Lizenzkonfiguration" +noInput = "Bitte geben Sie einen Lizenzschlüssel oder eine Datei an" [admin.settings.premium.licenseKey] toggle = "Lizenzschlüssel oder Zertifikatsdatei vorhanden?" @@ -4511,6 +4535,25 @@ line1 = "Das Überschreiben Ihres aktuellen Lizenzschlüssels kann nicht rückg line2 = "Ihre vorherige Lizenz geht dauerhaft verloren, sofern Sie sie nicht anderweitig gesichert haben." line3 = "Wichtig: Halten Sie Lizenzschlüssel privat und sicher. Geben Sie sie niemals öffentlich weiter." +[admin.settings.premium.inputMethod] +text = "Lizenzschlüssel" +file = "Zertifikatsdatei" + +[admin.settings.premium.file] +label = "Lizenz-Zertifikatsdatei" +description = "Laden Sie Ihre .lic- oder .cert-Lizenzdatei aus Offline-Käufen hoch" +choose = "Lizenzdatei auswählen" +selected = "Ausgewählt: {{filename}} ({{size}})" +successMessage = "Lizenzdatei erfolgreich hochgeladen und aktiviert. Kein Neustart erforderlich." + +[admin.settings.premium.currentLicense] +title = "Aktive Lizenz" +file = "Quelle: Lizenzdatei ({{path}})" +key = "Quelle: Lizenzschlüssel" +type = "Typ: {{type}}" +noInput = "Bitte geben Sie einen Lizenzschlüssel an oder laden Sie eine Zertifikatdatei hoch" +success = "Erfolg" + [admin.settings.premium.enabled] label = "Premium-Funktionen aktivieren" description = "Lizenzschlüssel-Prüfungen für Pro-/Enterprise-Funktionen aktivieren" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} ausgewählt" download = "Herunterladen" delete = "Löschen" unsupported = "Nicht unterstützt" +active = "Aktiv" addToUpload = "Zum Upload hinzufügen" +closeFile = "Datei schließen" deleteAll = "Alle löschen" loadingFiles = "Dateien werden geladen..." noFiles = "Keine Dateien verfügbar" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Mindestens eine E-Mail-Adresse ist erforderlich" submit = "Einladungen senden" success = "Benutzer erfolgreich eingeladen" -partialSuccess = "Einige Einladungen sind fehlgeschlagen" +partialFailure = "Einige Einladungen sind fehlgeschlagen" allFailed = "Benutzer konnten nicht eingeladen werden" error = "Einladungen konnten nicht gesendet werden" @@ -5752,7 +5797,7 @@ label = "Server auswählen" description = "Self-Hosted-Server" [setup.step3] -label = "Login" +label = "Anmeldung" description = "Anmeldedaten eingeben" [setup.mode.saas] @@ -5793,10 +5838,17 @@ testFailed = "Verbindungstest fehlgeschlagen" title = "Anmelden" subtitle = "Geben Sie Ihre Anmeldedaten ein, um fortzufahren" connectingTo = "Verbinden mit:" -submit = "Login" +submit = "Anmelden" signInWith = "Anmelden mit" oauthPending = "Browser zur Authentifizierung wird geöffnet..." orContinueWith = "Oder mit E-Mail fortfahren" +serverRequirement = "Hinweis: Auf dem Server muss die Anmeldung aktiviert sein." +showInstructions = "Wie aktivieren?" +hideInstructions = "Anleitung ausblenden" +instructions = "So aktivieren Sie die Anmeldung auf Ihrem Stirling PDF-Server:" +instructionsEnvVar = "Setzen Sie die Umgebungsvariable:" +instructionsOrYml = "Oder in der settings.yml:" +instructionsRestart = "Starten Sie anschließend Ihren Server neu, damit die Änderungen wirksam werden." [setup.login.username] label = "Benutzername" @@ -5847,7 +5899,7 @@ singleLine = "Einzeilig" [pdfTextEditor.badges] unsaved = "Bearbeitet" modified = "Bearbeitet" -earlyAccess = "Early Access" +earlyAccess = "Früher Zugriff" [pdfTextEditor.actions] reset = "Änderungen zurücksetzen" diff --git a/frontend/public/locales/el-GR/translation.toml b/frontend/public/locales/el-GR/translation.toml index 265646627..d3cf4c860 100644 --- a/frontend/public/locales/el-GR/translation.toml +++ b/frontend/public/locales/el-GR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Αφαίρεση από τα Αγαπημένα" fullscreen = "Μετάβαση σε λειτουργία πλήρους οθόνης" sidebar = "Μετάβαση σε λειτουργία πλευρικής γραμμής" +[backendStartup] +notFoundTitle = "Το backend δεν βρέθηκε" +retry = "Επανάληψη" +unreachable = "Η εφαρμογή δεν μπορεί προς το παρόν να συνδεθεί με το backend. Ελέγξτε την κατάσταση του backend και τη συνδεσιμότητα δικτύου, μετά δοκιμάστε ξανά." + [zipWarning] title = "Μεγάλο αρχείο ZIP" message = "Αυτό το ZIP περιέχει {{count}} αρχεία. Να γίνει αποσυμπίεση ούτως ή άλλως;" @@ -287,7 +292,7 @@ help = "Βοήθεια Pipeline" scanHelp = "Βοήθεια σάρωσης φακέλων" deletePrompt = "Είστε βέβαιοι ότι θέλετε να διαγράψετε το pipeline;" tags = "αυτοματοποίηση,ακολουθία,προγραμματισμένο,επεξεργασία-παρτίδας" -title = "Pipeline" +title = "Ροή" [pipelineOptions] header = "Διαμόρφωση Pipeline" @@ -296,7 +301,7 @@ saveSettings = "Αποθήκευση ρυθμίσεων λειτουργίας" pipelineNamePrompt = "Εισάγετε όνομα pipeline εδώ" selectOperation = "Επιλογή λειτουργίας" addOperationButton = "Προσθήκη λειτουργίας" -pipelineHeader = "Pipeline:" +pipelineHeader = "Ροή:" saveButton = "Λήψη" validateButton = "Επικύρωση" @@ -347,7 +352,7 @@ teams = "Ομάδες" title = "Διαμόρφωση" systemSettings = "Ρυθμίσεις συστήματος" features = "Δυνατότητες" -endpoints = "Endpoints" +endpoints = "Σημεία τερματισμού" database = "Βάση δεδομένων" advanced = "Προχωρημένα" @@ -369,7 +374,7 @@ privacy = "Απόρρητο" [settings.developer] title = "Προγραμματιστής" -apiKeys = "API Keys" +apiKeys = "Κλειδιά API" [settings.tooltips] enableLoginFirst = "Ενεργοποιήστε πρώτα τη λειτουργία σύνδεσης" @@ -383,7 +388,7 @@ logout = "Αποσύνδεση" [settings.connection.mode] saas = "Stirling Cloud" -selfhosted = "Self-Hosted" +selfhosted = "Αυτο-φιλοξενούμενο" [settings.general] title = "Γενικά" @@ -912,6 +917,9 @@ desc = "Δημιουργήστε ροές πολλών βημάτων συνδέ desc = "Επικάλυψη PDF πάνω σε άλλο PDF" title = "Επικάλυψη PDF" +[home.pdfTextEditor] +title = "Επεξεργαστής κειμένου PDF" +desc = "Επεξεργαστείτε υπάρχον κείμενο και εικόνες μέσα σε αρχεία PDF" [home.addText] tags = "κείμενο,σχολιασμός,ετικέτα" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "Επιλέξτε αρχεία στην κύρια πρ settings = "Ρυθμίσεις" conversionCompleted = "Η μετατροπή ολοκληρώθηκε" results = "Αποτελέσματα" -defaultFilename = "converted_file" +defaultFilename = "μετατραπμένο_αρχείο" conversionResults = "Αποτελέσματα μετατροπής" convertFrom = "Μετατροπή από" convertTo = "Μετατροπή σε" @@ -1360,7 +1368,7 @@ title = "Προσθήκη υδατογραφήματος" desc = "Προσθέστε υδατογραφήματα κειμένου ή εικόνας σε αρχεία PDF" completed = "Το υδατογράφημα προστέθηκε" submit = "Προσθήκη υδατογραφήματος" -filenamePrefix = "watermarked" +filenamePrefix = "υδατογραφημένο" [watermark.error] failed = "Παρουσιάστηκε σφάλμα κατά την προσθήκη υδατογραφήματος στο PDF." @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Σχεδιασμένη υπογραφή" defaultImageLabel = "Ανεβασμένη υπογραφή" defaultTextLabel = "Πληκτρολογημένη υπογραφή" saveButton = "Αποθήκευση υπογραφής" +savePersonal = "Αποθήκευση ως Προσωπική" +saveShared = "Αποθήκευση ως Κοινόχρηστη" saveUnavailable = "Δημιουργήστε πρώτα μια υπογραφή για να την αποθηκεύσετε." noChanges = "Η τρέχουσα υπογραφή είναι ήδη αποθηκευμένη." +tempStorageTitle = "Προσωρινή αποθήκευση στον περιηγητή" +tempStorageDescription = "Οι υπογραφές αποθηκεύονται μόνο στον περιηγητή σας. Θα χαθούν αν καθαρίσετε τα δεδομένα του περιηγητή ή αλλάξετε περιηγητή." +personalHeading = "Προσωπικές υπογραφές" +sharedHeading = "Κοινόχρηστες υπογραφές" +personalDescription = "Μόνο εσείς μπορείτε να δείτε αυτές τις υπογραφές." +sharedDescription = "Όλοι οι χρήστες μπορούν να βλέπουν και να χρησιμοποιούν αυτές τις υπογραφές." [sign.saved.type] canvas = "Σχέδιο" @@ -2701,7 +2717,7 @@ header = "Αφαίρεση της ψηφιακής υπογραφής από τ selectPDF = "Επιλέξτε ένα αρχείο PDF:" submit = "Αφαίρεση υπογραφής" description = "Αυτό το εργαλείο θα αφαιρέσει τις υπογραφές ψηφιακού πιστοποιητικού από το PDF σας." -filenamePrefix = "unsigned" +filenamePrefix = "ανυπόγραφο" [removeCertSign.files] placeholder = "Επιλέξτε ένα αρχείο PDF στην κύρια προβολή για να ξεκινήσετε" @@ -3438,6 +3454,9 @@ signinTitle = "Παρακαλώ συνδεθείτε" ssoSignIn = "Σύνδεση μέσω Single Sign-on" oAuth2AutoCreateDisabled = "Η αυτόματη δημιουργία χρήστη OAUTH2 είναι απενεργοποιημένη" oAuth2AdminBlockedUser = "Η εγγραφή ή σύνδεση μη εγγεγραμμένων χρηστών είναι προς το παρόν αποκλεισμένη. Παρακαλώ επικοινωνήστε με τον διαχειριστή." +oAuth2RequiresLicense = "Η σύνδεση μέσω OAuth/SSO απαιτεί επί πληρωμή άδεια (Server ή Enterprise). Παρακαλούμε επικοινωνήστε με τον διαχειριστή για να αναβαθμίσετε το πλάνο σας." +saml2RequiresLicense = "Η σύνδεση μέσω SAML απαιτεί επί πληρωμή άδεια (Server ή Enterprise). Παρακαλούμε επικοινωνήστε με τον διαχειριστή για να αναβαθμίσετε το πλάνο σας." +maxUsersReached = "Έχει επιτευχθεί ο μέγιστος αριθμός χρηστών για την τρέχουσα άδειά σας. Παρακαλούμε επικοινωνήστε με τον διαχειριστή για να αναβαθμίσετε το πλάνο σας ή να προσθέσετε περισσότερες θέσεις." oauth2RequestNotFound = "Το αίτημα εξουσιοδότησης δεν βρέθηκε" oauth2InvalidUserInfoResponse = "Μη έγκυρη απόκριση πληροφοριών χρήστη" oauth2invalidRequest = "Μη έγκυρο αίτημα" @@ -3533,7 +3552,7 @@ title = "PDF σε μία σελίδα" header = "PDF σε μία σελίδα" submit = "Μετατροπή σε μία σελίδα" description = "Αυτό το εργαλείο θα συγχωνεύσει όλες τις σελίδες του PDF σας σε μία μεγάλη ενιαία σελίδα. Το πλάτος θα παραμείνει ίδιο με των αρχικών σελίδων, αλλά το ύψος θα είναι το άθροισμα όλων των υψών." -filenamePrefix = "single_page" +filenamePrefix = "μονοσέλιδο" [pdfToSinglePage.files] placeholder = "Επιλέξτε ένα αρχείο PDF στην κύρια προβολή για να ξεκινήσετε" @@ -3846,14 +3865,17 @@ fitToWidth = "Προσαρμογή στο πλάτος" actualSize = "Πραγματικό μέγεθος" [viewer] +cannotPreviewFile = "Δεν είναι δυνατή η προεπισκόπηση του αρχείου" +dualPageView = "Προβολή διπλής σελίδας" firstPage = "Πρώτη σελίδα" lastPage = "Τελευταία σελίδα" -previousPage = "Προηγούμενη σελίδα" nextPage = "Επόμενη σελίδα" +onlyPdfSupported = "Ο προβολέας υποστηρίζει μόνο αρχεία PDF. Αυτό το αρχείο φαίνεται να είναι διαφορετικής μορφής." +previousPage = "Προηγούμενη σελίδα" +singlePageView = "Προβολή μίας σελίδας" +unknownFile = "Άγνωστο αρχείο" zoomIn = "Μεγέθυνση" zoomOut = "Σμίκρυνση" -singlePageView = "Προβολή μίας σελίδας" -dualPageView = "Προβολή διπλής σελίδας" [rightRail] closeSelected = "Κλείσιμο επιλεγμένων αρχείων" @@ -3877,6 +3899,7 @@ toggleSidebar = "Εναλλαγή πλευρικής γραμμής" exportSelected = "Εξαγωγή επιλεγμένων σελίδων" toggleAnnotations = "Εναλλαγή ορατότητας σχολιασμών" annotationMode = "Εναλλαγή λειτουργίας σχολιασμού" +print = "Εκτύπωση PDF" draw = "Σχεδίαση" save = "Αποθήκευση" saveChanges = "Αποθήκευση αλλαγών" @@ -4235,11 +4258,11 @@ label = "URL εκδότη" description = "Το URL εκδότη του παρόχου OAuth2" [admin.settings.connections.oauth2.clientId] -label = "Client ID" +label = "Αναγνωριστικό πελάτη (Client ID)" description = "Το Client ID OAuth2 από τον πάροχό σας" [admin.settings.connections.oauth2.clientSecret] -label = "Client Secret" +label = "Μυστικό πελάτη (Client Secret)" description = "Το Client Secret OAuth2 από τον πάροχό σας" [admin.settings.connections.oauth2.useAsUsername] @@ -4494,6 +4517,7 @@ description = "URL ή όνομα αρχείου για το impressum (απαι title = "Premium & Enterprise" description = "Ρυθμίστε το κλειδί άδειας premium ή enterprise." license = "Διαμόρφωση άδειας" +noInput = "Παρακαλώ δώστε ένα κλειδί άδειας ή αρχείο" [admin.settings.premium.licenseKey] toggle = "Έχετε κλειδί άδειας ή αρχείο πιστοποιητικού;" @@ -4511,6 +4535,25 @@ line1 = "Η αντικατάσταση του τρέχοντος κλειδιο line2 = "Η προηγούμενη άδεια θα χαθεί οριστικά εκτός αν την έχετε αποθηκεύσει αλλού." line3 = "Σημαντικό: Κρατήστε τα κλειδιά άδειας ιδιωτικά και ασφαλή. Μην τα κοινοποιείτε δημόσια." +[admin.settings.premium.inputMethod] +text = "Κλειδί άδειας" +file = "Αρχείο πιστοποιητικού" + +[admin.settings.premium.file] +label = "Αρχείο πιστοποιητικού άδειας" +description = "Μεταφορτώστε το αρχείο άδειας .lic ή .cert από αγορές εκτός σύνδεσης" +choose = "Επιλέξτε αρχείο άδειας" +selected = "Επιλεγμένο: {{filename}} ({{size}})" +successMessage = "Το αρχείο άδειας μεταφορτώθηκε και ενεργοποιήθηκε με επιτυχία. Δεν απαιτείται επανεκκίνηση." + +[admin.settings.premium.currentLicense] +title = "Ενεργή άδεια" +file = "Πηγή: Αρχείο άδειας ({{path}})" +key = "Πηγή: Κλειδί άδειας" +type = "Τύπος: {{type}}" +noInput = "Παρακαλώ δώστε ένα κλειδί άδειας ή μεταφορτώστε ένα αρχείο πιστοποιητικού" +success = "Επιτυχία" + [admin.settings.premium.enabled] label = "Ενεργοποίηση λειτουργιών premium" description = "Ενεργοποίηση ελέγχων κλειδιού άδειας για λειτουργίες pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} επιλεγμένα" download = "Λήψη" delete = "Διαγραφή" unsupported = "Μη υποστηριζόμενο" +active = "Ενεργό" addToUpload = "Προσθήκη στη μεταφόρτωση" +closeFile = "Κλείσιμο αρχείου" deleteAll = "Διαγραφή όλων" loadingFiles = "Φόρτωση αρχείων..." noFiles = "Δεν υπάρχουν διαθέσιμα αρχεία" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Απαιτείται τουλάχιστον μία διεύθυνση email" submit = "Αποστολή προσκλήσεων" success = "στάλθηκαν προσκλήσεις με επιτυχία" -partialSuccess = "Κάποιες προσκλήσεις απέτυχαν" +partialFailure = "Ορισμένες προσκλήσεις απέτυχαν" allFailed = "Αποτυχία πρόσκλησης χρηστών" error = "Αποτυχία αποστολής προσκλήσεων" @@ -5709,7 +5754,7 @@ title = "Διάγραμμα χρήσης Endpoints" [usage.table] title = "Αναλυτικά στατιστικά" -endpoint = "Endpoint" +endpoint = "Σημείο τερματισμού" visits = "Επισκέψεις" percentage = "Ποσοστό" noData = "Δεν υπάρχουν διαθέσιμα δεδομένα" @@ -5797,6 +5842,13 @@ submit = "Σύνδεση" signInWith = "Σύνδεση με" oauthPending = "Άνοιγμα προγράμματος περιήγησης για έλεγχο ταυτότητας..." orContinueWith = "Ή συνεχίστε με email" +serverRequirement = "Σημείωση: Ο διακομιστής πρέπει να έχει ενεργοποιημένη τη σύνδεση." +showInstructions = "Πώς ενεργοποιείται;" +hideInstructions = "Απόκρυψη οδηγιών" +instructions = "Για να ενεργοποιήσετε τη σύνδεση στον διακομιστή Stirling PDF:" +instructionsEnvVar = "Ορίστε τη μεταβλητή περιβάλλοντος:" +instructionsOrYml = "Ή στο settings.yml:" +instructionsRestart = "Στη συνέχεια, επανεκκινήστε τον διακομιστή σας για να εφαρμοστούν οι αλλαγές." [setup.login.username] label = "Όνομα χρήστη" diff --git a/frontend/public/locales/es-ES/translation.toml b/frontend/public/locales/es-ES/translation.toml index 7890318ff..437c0ac2c 100644 --- a/frontend/public/locales/es-ES/translation.toml +++ b/frontend/public/locales/es-ES/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Quitar de favoritos" fullscreen = "Cambiar a modo pantalla completa" sidebar = "Cambiar a modo barra lateral" +[backendStartup] +notFoundTitle = "Backend no encontrado" +retry = "Reintentar" +unreachable = "La aplicación no puede conectarse actualmente al backend. Verifique el estado del backend y la conectividad de red, luego inténtelo de nuevo." + [zipWarning] title = "Archivo ZIP grande" message = "Este ZIP contiene {{count}} archivos. ¿Extraer de todos modos?" @@ -347,7 +352,7 @@ teams = "Equipos" title = "Configuración" systemSettings = "Ajustes del sistema" features = "Funciones" -endpoints = "Endpoints" +endpoints = "Puntos de conexión" database = "Base de datos" advanced = "Avanzado" @@ -912,6 +917,9 @@ desc = "Crear flujos de trabajo de múltiples pasos encadenando acciones de PDF. desc = "Superponer PDFs encima de otro PDF" title = "Superponer PDFs" +[home.pdfTextEditor] +title = "Editor de texto de PDF" +desc = "Edita texto e imágenes existentes dentro de archivos PDF" [home.addText] tags = "texto,anotación,etiqueta" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Firma dibujada" defaultImageLabel = "Firma subida" defaultTextLabel = "Firma escrita" saveButton = "Guardar firma" +savePersonal = "Guardar personal" +saveShared = "Guardar compartida" saveUnavailable = "Cree primero una firma para guardarla." noChanges = "La firma actual ya está guardada." +tempStorageTitle = "Almacenamiento temporal del navegador" +tempStorageDescription = "Las firmas se almacenan solo en tu navegador. Se perderán si borras los datos del navegador o cambias de navegador." +personalHeading = "Firmas personales" +sharedHeading = "Firmas compartidas" +personalDescription = "Solo tú puedes ver estas firmas." +sharedDescription = "Todos los usuarios pueden ver y usar estas firmas." [sign.saved.type] canvas = "Dibujo" @@ -3438,6 +3454,9 @@ signinTitle = "Por favor, inicie sesión" ssoSignIn = "Iniciar sesión a través del inicio de sesión único" oAuth2AutoCreateDisabled = "Usuario de creación automática de OAUTH2 DESACTIVADO" oAuth2AdminBlockedUser = "El registro o inicio de sesión de usuarios no registrados está actualmente bloqueado. Por favor, póngase en contacto con el administrador." +oAuth2RequiresLicense = "El inicio de sesión OAuth/SSO requiere una licencia de pago (Server o Enterprise). Póngase en contacto con el administrador para actualizar su plan." +saml2RequiresLicense = "El inicio de sesión SAML requiere una licencia de pago (Server o Enterprise). Póngase en contacto con el administrador para actualizar su plan." +maxUsersReached = "Se alcanzó el número máximo de usuarios para su licencia actual. Póngase en contacto con el administrador para actualizar su plan o añadir más plazas." oauth2RequestNotFound = "Solicitud de autorización no encontrada" oauth2InvalidUserInfoResponse = "Respuesta de información de usuario no válida" oauth2invalidRequest = "Solicitud no válida" @@ -3846,14 +3865,17 @@ fitToWidth = "Ajustar al Ancho" actualSize = "Tamaño Real" [viewer] +cannotPreviewFile = "No se puede previsualizar el archivo" +dualPageView = "Vista de Página Doble" firstPage = "Primera Página" lastPage = "Última Página" -previousPage = "Página Anterior" nextPage = "Página Siguiente" +onlyPdfSupported = "El visor solo admite archivos PDF. Este archivo parece ser de un formato diferente." +previousPage = "Página Anterior" +singlePageView = "Vista de Página Única" +unknownFile = "Archivo desconocido" zoomIn = "Acercar" zoomOut = "Alejar" -singlePageView = "Vista de Página Única" -dualPageView = "Vista de Página Doble" [rightRail] closeSelected = "Cerrar Archivos Seleccionados" @@ -3877,6 +3899,7 @@ toggleSidebar = "Alternar Barra Lateral" exportSelected = "Exportar páginas seleccionadas" toggleAnnotations = "Mostrar/ocultar anotaciones" annotationMode = "Cambiar modo de anotaciones" +print = "Imprimir PDF" draw = "Dibujar" save = "Guardar" saveChanges = "Guardar cambios" @@ -4494,6 +4517,7 @@ description = "URL o nombre de archivo del impressum (requerido en algunas juris title = "Premium y Enterprise" description = "Configura tu clave de licencia premium o enterprise." license = "Configuración de licencia" +noInput = "Proporciona una clave o archivo de licencia" [admin.settings.premium.licenseKey] toggle = "¿Tiene una clave de licencia o un archivo de certificado?" @@ -4511,6 +4535,25 @@ line1 = "Sobrescribir su clave de licencia actual no se puede deshacer." line2 = "Su licencia anterior se perderá de forma permanente a menos que la haya respaldado en otro lugar." line3 = "Importante: mantenga las claves de licencia privadas y seguras. Nunca las comparta públicamente." +[admin.settings.premium.inputMethod] +text = "Clave de licencia" +file = "Archivo de certificado" + +[admin.settings.premium.file] +label = "Archivo de certificado de licencia" +description = "Sube tu archivo de licencia .lic o .cert de compras sin conexión" +choose = "Elegir archivo de licencia" +selected = "Seleccionado: {{filename}} ({{size}})" +successMessage = "Archivo de licencia subido y activado correctamente. No es necesario reiniciar." + +[admin.settings.premium.currentLicense] +title = "Licencia activa" +file = "Origen: Archivo de licencia ({{path}})" +key = "Origen: Clave de licencia" +type = "Tipo: {{type}}" +noInput = "Proporciona una clave de licencia o sube un archivo de certificado" +success = "Éxito" + [admin.settings.premium.enabled] label = "Habilitar funciones Premium" description = "Habilitar la verificación de la clave de licencia para funciones pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} seleccionados" download = "Descargar" delete = "Borrar" unsupported = "No Soportado" +active = "Activo" addToUpload = "Añadir a la subida" +closeFile = "Cerrar archivo" deleteAll = "Eliminar todo" loadingFiles = "Cargando archivos..." noFiles = "No hay archivos disponibles" @@ -5204,7 +5249,7 @@ user = "Usuario" [workspace.people.addMember] title = "Añadir miembro" username = "Nombre de usuario (correo)" -usernamePlaceholder = "user@example.com" +usernamePlaceholder = "usuario@ejemplo.com" password = "Contraseña" passwordPlaceholder = "Introduce la contraseña" role = "Rol" @@ -5241,11 +5286,11 @@ error = "No se pudo eliminar el usuario" tab = "Invitación por correo electrónico" description = "Escribe o pega correos a continuación, separados por comas. Los usuarios recibirán credenciales de inicio de sesión por correo electrónico." emails = "Direcciones de correo electrónico" -emailsPlaceholder = "user1@example.com, user2@example.com" +emailsPlaceholder = "usuario1@ejemplo.com, usuario2@ejemplo.com" emailsRequired = "Se requiere al menos una dirección de correo electrónico" submit = "Enviar invitaciones" success = "usuario(s) invitado(s) correctamente" -partialSuccess = "Algunas invitaciones fallaron" +partialFailure = "Algunas invitaciones fallaron" allFailed = "No se pudo invitar a los usuarios" error = "No se pudieron enviar las invitaciones" @@ -5541,7 +5586,7 @@ emailInvalid = "Introduzca una dirección de correo válida" title = "Introduzca su correo electrónico" description = "Lo usaremos para enviar su clave de licencia y recibos." emailLabel = "Dirección de correo electrónico" -emailPlaceholder = "your@email.com" +emailPlaceholder = "su@email.com" continue = "Continuar" modalTitle = "Comenzar - {{planName}}" @@ -5797,13 +5842,20 @@ submit = "Iniciar sesión" signInWith = "Iniciar sesión con" oauthPending = "Abriendo el navegador para autenticación..." orContinueWith = "O continuar con email" +serverRequirement = "Nota: el servidor debe tener el inicio de sesión habilitado." +showInstructions = "¿Cómo habilitarlo?" +hideInstructions = "Ocultar instrucciones" +instructions = "Para habilitar el inicio de sesión en su servidor de Stirling PDF:" +instructionsEnvVar = "Establezca la variable de entorno:" +instructionsOrYml = "O en settings.yml:" +instructionsRestart = "Luego reinicie su servidor para que los cambios surtan efecto." [setup.login.username] label = "Nombre de usuario" placeholder = "Introduzca su nombre de usuario" [setup.login.email] -label = "Email" +label = "Correo electrónico" placeholder = "Introduzca su email" [setup.login.password] @@ -5840,7 +5892,7 @@ paragraph = "Página de párrafos" sparse = "Texto disperso" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automático" paragraph = "Párrafo" singleLine = "Línea única" diff --git a/frontend/public/locales/eu-ES/translation.toml b/frontend/public/locales/eu-ES/translation.toml index 89a7dddd5..3fc897147 100644 --- a/frontend/public/locales/eu-ES/translation.toml +++ b/frontend/public/locales/eu-ES/translation.toml @@ -99,7 +99,7 @@ visitGithub = "Bisitatu Github biltegia" donate = "Dohaintza egin" color = "Color" sponsor = "Babestu" -info = "Info" +info = "Informazioa" pro = "Pro" page = "Orrialdea" pages = "Orrialdeak" @@ -131,7 +131,7 @@ unsupported = "Ez da onartzen" [toolPanel] placeholder = "Aukeratu tresna bat hasteko" -alpha = "Alpha" +alpha = "Alfa" premiumFeature = "Premium ezaugarria:" comingSoon = "Laster eskuragarri:" @@ -163,6 +163,11 @@ unfavorite = "Kendu gogokoetatik" fullscreen = "Aldatu pantaila osoko modura" sidebar = "Aldatu alboko barra modura" +[backendStartup] +notFoundTitle = "Backend-a ez da aurkitu" +retry = "Saiatu berriro" +unreachable = "Aplikazioak une honetan ezin du backend-arekin konektatu. Egiaztatu backend-aren egoera eta sare-konexioa, eta saiatu berriro." + [zipWarning] title = "ZIP fitxategi handia" message = "ZIP honek {{count}} fitxategi ditu. Erauzi hala ere?" @@ -274,7 +279,7 @@ iAgreeToThe = "Onartzen ditut honako hauek guztiak" terms = "Baldintzak eta erabilera-baldintzak" accessibility = "Irisgarritasuna" cookie = "Cookie politika" -impressum = "Impressum" +impressum = "Lege oharra" showCookieBanner = "Cookie-hobespenak" [pipeline] @@ -296,7 +301,7 @@ saveSettings = "Gorde eragiketa-ezarpenak" pipelineNamePrompt = "Sartu hemen pipeline izena" selectOperation = "Aukeratu eragiketa" addOperationButton = "Gehitu eragiketa" -pipelineHeader = "Pipeline:" +pipelineHeader = "Pipelinea:" saveButton = "Distira" validateButton = "Balidatu" @@ -347,7 +352,7 @@ teams = "Taldeak" title = "Konfigurazioa" systemSettings = "Sistemaren ezarpenak" features = "Eginbideak" -endpoints = "Endpoints" +endpoints = "Amaiera-puntuak" database = "Datu-basea" advanced = "Aurreratua" @@ -364,7 +369,7 @@ usageAnalytics = "Erabilera-analitika" [settings.policiesPrivacy] title = "Politikak eta Pribatutasuna" -legal = "Legal" +legal = "Lege" privacy = "Pribatutasuna" [settings.developer] @@ -513,7 +518,7 @@ syncToAccount = "Sync Kontua <- Nabigatzailea" [adminUserSettings] title = "Erabiltzailearen Ezarpenen Kontrolak" header = "Admin Erabiltzailearen Ezarpenen Kontrolak" -admin = "Admin" +admin = "Administratzailea" user = "Erabiltzaile" addUser = "Erabiltzaile berria" deleteUser = "Ezabatu erabiltzailea" @@ -912,6 +917,9 @@ desc = "Eraiki hainbat pausotako workflowak PDF ekintzak kateatuz. Egokia zeregi desc = "Overlays PDFs on-top of another PDF" title = "Gainjarri PDFak" +[home.pdfTextEditor] +title = "PDF testu editorea" +desc = "Editatu PDFetako lehendik dauden testuak eta irudiak" [home.addText] tags = "testua,anotazioa,etiketa" @@ -1217,7 +1225,7 @@ odtExt = "OpenDocument testua (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "OpenDocument aurkezpena (.odp)" txtExt = "Testu laua (.txt)" -rtfExt = "Rich Text Format (.rtf)" +rtfExt = "Testu aberatsaren formatua (.rtf)" selectedFiles = "Hautatutako fitxategiak" noFileSelected = "Ez da fitxategirik hautatu. Erabili fitxategi-panela fitxategiak gehitzeko." convertFiles = "Bihurtu fitxategiak" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Marrazketa sinadura" defaultImageLabel = "Igotako sinadura" defaultTextLabel = "Idatzitako sinadura" saveButton = "Gorde sinadura" +savePersonal = "Gorde pertsonala" +saveShared = "Gorde partekatua" saveUnavailable = "Lehenik sortu sinadura bat gordetzeko." noChanges = "Uneko sinadura dagoeneko gorde da." +tempStorageTitle = "Aldi baterako nabigatzaileko biltegiratzea" +tempStorageDescription = "Sinadurak zure nabigatzailean bakarrik gordetzen dira. Nabigatzailearen datuak ezabatzen badituzu edo nabigatzailea aldatzen baduzu, galdu egingo dira." +personalHeading = "Sinadura pertsonalak" +sharedHeading = "Partekatutako sinadurak" +personalDescription = "Zuk bakarrik ikus ditzakezu sinadura hauek." +sharedDescription = "Erabiltzaile guztiek ikus eta erabil ditzakete sinadura hauek." [sign.saved.type] canvas = "Marrazkia" @@ -3438,6 +3454,9 @@ signinTitle = "Mesedez, hasi saioa" ssoSignIn = "Hasi saioa Saioa hasteko modu bakarraren bidez" oAuth2AutoCreateDisabled = "OAUTH2 Sortu automatikoki erabiltzailea desgaituta dago" oAuth2AdminBlockedUser = "Erregistratu gabeko erabiltzaileen erregistroa edo saio-hasiera une honetan blokeatuta dago. Jarri harremanetan administratzailearekin." +oAuth2RequiresLicense = "OAuth/SSO bidezko saio-hasierak lizentzia ordaindua behar du (Server edo Enterprise). Mesedez, jarri harremanetan administratzailearekin plana eguneratzeko." +saml2RequiresLicense = "SAML bidezko saio-hasierak lizentzia ordaindua behar du (Server edo Enterprise). Mesedez, jarri harremanetan administratzailearekin plana eguneratzeko." +maxUsersReached = "Zure uneko lizentziarekin erabiltzaile kopuru maximoa gainditu da. Mesedez, jarri harremanetan administratzailearekin plana eguneratzeko edo eserleku gehiago gehitzeko." oauth2RequestNotFound = "Baimen-eskaera ez da aurkitu" oauth2InvalidUserInfoResponse = "Erabiltzaile-informazioaren erantzun baliogabea" oauth2invalidRequest = "Eskaera baliogabea" @@ -3533,7 +3552,7 @@ title = "PDF Orrialde bakarrera" header = "PDF Orrialde bakarrera" submit = "Orrialde bakarrera bihurtu" description = "Tresna honek zure PDFko orri guztiak orri handi bakarrean batuko ditu. Zabalera bera izango du jatorrizko orrienarekin, baina altuera orri guztien altueren batura izango da." -filenamePrefix = "single_page" +filenamePrefix = "orrialde_bakarra" [pdfToSinglePage.files] placeholder = "Hautatu PDF fitxategi bat ikuspegi nagusian hasteko" @@ -3846,14 +3865,17 @@ fitToWidth = "Zabalera egokitu" actualSize = "Benetako tamaina" [viewer] +cannotPreviewFile = "Ezin da fitxategia aurreikusi" +dualPageView = "Orri biko ikuspegia" firstPage = "Lehen orria" lastPage = "Azken orria" -previousPage = "Aurreko orria" nextPage = "Hurrengo orria" +onlyPdfSupported = "Ikustaileak PDF fitxategiak bakarrik onartzen ditu. Fitxategi honek beste formatu batekoa dirudi." +previousPage = "Aurreko orria" +singlePageView = "Orri bakarreko ikuspegia" +unknownFile = "Fitxategi ezezaguna" zoomIn = "Zoom handitu" zoomOut = "Zoom txikitu" -singlePageView = "Orri bakarreko ikuspegia" -dualPageView = "Orri biko ikuspegia" [rightRail] closeSelected = "Itxi hautatutako fitxategiak" @@ -3877,6 +3899,7 @@ toggleSidebar = "Alboko barra txandakatu" exportSelected = "Esportatu hautatutako orriak" toggleAnnotations = "Oharpenen ikusgarritasuna txandakatu" annotationMode = "Oharpen modua txandakatu" +print = "Inprimatu PDFa" draw = "Marraztu" save = "Gorde" saveChanges = "Aldaketak gorde" @@ -4407,7 +4430,7 @@ description = "Sistema zabalagoko aldi baterako direktorioa garbitu ala ez (kont label = "Prozesu-exekutorearen mugak" description = "Konfiguratu saio-mugak eta denbora-mugak prozesu-exekutore bakoitzerako" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDFtik HTMLra" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4487,13 +4510,14 @@ label = "Cookieen politika" description = "Cookieen politikara doan URLa edo fitxategi-izena" [admin.settings.legal.impressum] -label = "Impressum" +label = "Lege oharra" description = "Impressum-era doan URLa edo fitxategi-izena (beharrezkoa jurisdikzio batzuetan)" [admin.settings.premium] title = "Premium eta Enterprise" description = "Konfiguratu zure premium edo enterprise lizentzia-gakoa." license = "Lizentziaren konfigurazioa" +noInput = "Eman lizentzia-gakoa edo fitxategia, mesedez" [admin.settings.premium.licenseKey] toggle = "Lizentzia-gakoa edo ziurtagiri-fitxategia duzu?" @@ -4511,6 +4535,25 @@ line1 = "Uneko lizentzia-gakoa gainidaztea ezin da desegin." line2 = "Aurreko lizentzia betiko galduko da beste nonbait babestu ezean." line3 = "Garrantzitsua: Mantendu lizentzia-gakoak pribatu eta seguru. Ez partekatu publikoki inoiz." +[admin.settings.premium.inputMethod] +text = "Lizentzia-gakoa" +file = "Ziurtagiri-fitxategia" + +[admin.settings.premium.file] +label = "Lizentzia-ziurtagiriaren fitxategia" +description = "Igo zure .lic edo .cert lizentzia-fitxategia lineaz kanpoko erosketetatik" +choose = "Aukeratu lizentzia-fitxategia" +selected = "Hautatuta: {{filename}} ({{size}})" +successMessage = "Lizentzia-fitxategia behar bezala igo eta aktibatu da. Ez da berrabiaraztea beharrezkoa." + +[admin.settings.premium.currentLicense] +title = "Lizentzia aktiboa" +file = "Iturburua: Lizentzia-fitxategia ({{path}})" +key = "Iturburua: Lizentzia-gakoa" +type = "Mota: {{type}}" +noInput = "Eman lizentzia-gakoa edo igo ziurtagiri-fitxategi bat, mesedez" +success = "Arrakasta" + [admin.settings.premium.enabled] label = "Premium eginbideak gaitu" description = "Gaitu lizentzia-gakoen egiaztapenak pro/enterprise eginbideetarako" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} hautatuta" download = "Distira" delete = "ezabatu" unsupported = "Ez da onartzen" +active = "Aktibo" addToUpload = "Gehitu igoerara" +closeFile = "Itxi fitxategia" deleteAll = "Ezabatu denak" loadingFiles = "Fitxategiak kargatzen..." noFiles = "Ez dago fitxategirik eskuragarri" @@ -5178,7 +5223,7 @@ active = "Aktibo" disabled = "Desgaituta" activeSession = "Saio aktiboa" member = "Kidea" -admin = "Admin" +admin = "Administratzailea" editRole = "Rola editatu" enable = "Gaitu" disable = "Desgaitu" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Gutxienez helbide elektroniko bat behar da" submit = "Bidali gonbidapenak" success = "erabiltzaile(a)(k) ongi gonbidatu dira" -partialSuccess = "Gonbidapen batzuek huts egin dute" +partialFailure = "Gonbidapen batzuk huts egin dute" allFailed = "Ezin izan da erabiltzaileak gonbidatu" error = "Ezin izan dira gonbidapenak bidali" @@ -5709,7 +5754,7 @@ title = "Endpoints erabileraren diagrama" [usage.table] title = "Estatistika xeheak" -endpoint = "Endpoint" +endpoint = "Amaiera-puntua" visits = "Bisitak" percentage = "Ehunekoa" noData = "Ez dago daturik eskuragarri" @@ -5797,6 +5842,13 @@ submit = "Hasi saioa" signInWith = "Hasi saioa honekin" oauthPending = "Nabigatzailea irekitzen autentifikaziorako..." orContinueWith = "Edo jarraitu emailarekin" +serverRequirement = "Oharra: zerbitzariak saioa hastea gaituta eduki behar du." +showInstructions = "Nola gaitu?" +hideInstructions = "Ezkutatu argibideak" +instructions = "Saioa hastea gaitzeko zure Stirling PDF zerbitzarian:" +instructionsEnvVar = "Ezarri ingurune-aldagaia:" +instructionsOrYml = "Edo settings.yml fitxategian:" +instructionsRestart = "Ondoren, berrabiarazi zerbitzaria aldaketak indarrean sartzeko." [setup.login.username] label = "Erabiltzaile-izena" @@ -5840,7 +5892,7 @@ paragraph = "Paragrafo orria" sparse = "Testu sakabanatua" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automatikoa" paragraph = "Paragrafoa" singleLine = "Lerro bakarra" diff --git a/frontend/public/locales/fa-IR/translation.toml b/frontend/public/locales/fa-IR/translation.toml index f2cb9bd91..8102a9c7c 100644 --- a/frontend/public/locales/fa-IR/translation.toml +++ b/frontend/public/locales/fa-IR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "حذف از علاقه‌مندی‌ها" fullscreen = "تغییر به حالت تمام‌صفحه" sidebar = "تغییر به حالت نوار کناری" +[backendStartup] +notFoundTitle = "بک‌اند یافت نشد" +retry = "تلاش مجدد" +unreachable = "برنامه در حال حاضر نمی‌تواند به بک‌اند متصل شود. وضعیت بک‌اند و اتصال شبکه را بررسی کرده و سپس دوباره تلاش کنید." + [zipWarning] title = "فایل ZIP بزرگ" message = "این ZIP شامل {{count}} فایل است. با این حال استخراج شود؟" @@ -912,6 +917,9 @@ desc = "ساخت گردش‌کارهای چندمرحله‌ای با زنجیر desc = "PDF‌ها را بر روی PDF دیگری هم‌پوشانی می‌کند" title = "هم‌پوشانی PDF‌ها" +[home.pdfTextEditor] +title = "ویرایشگر متن PDF" +desc = "ویرایش متن و تصاویر موجود در PDFها" [home.addText] tags = "متن,حاشیه‌نویسی,برچسب" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "امضای ترسیمی" defaultImageLabel = "امضای بارگذاری‌شده" defaultTextLabel = "امضای تایپی" saveButton = "ذخیره امضا" +savePersonal = "ذخیره شخصی" +saveShared = "ذخیره اشتراکی" saveUnavailable = "برای ذخیره، ابتدا امضایی بسازید." noChanges = "امضای فعلی قبلاً ذخیره شده است." +tempStorageTitle = "ذخیره‌سازی موقت در مرورگر" +tempStorageDescription = "امضاها فقط در مرورگر شما ذخیره می‌شوند. در صورت پاک‌کردن داده‌های مرورگر یا تعویض مرورگر، از بین می‌روند." +personalHeading = "امضاهای شخصی" +sharedHeading = "امضاهای اشتراکی" +personalDescription = "تنها شما می‌توانید این امضاها را ببینید." +sharedDescription = "همه کاربران می‌توانند این امضاها را ببینند و استفاده کنند." [sign.saved.type] canvas = "ترسیمی" @@ -3438,6 +3454,9 @@ signinTitle = "لطفاً وارد شوید" ssoSignIn = "ورود از طریق Single Sign-on" oAuth2AutoCreateDisabled = "ایجاد خودکار کاربر با OAUTH2 غیرفعال است" oAuth2AdminBlockedUser = "ثبت‌نام یا ورود کاربران ثبت‌نشده در حال حاضر مسدود است. لطفاً با مدیر تماس بگیرید." +oAuth2RequiresLicense = "ورود با OAuth/SSO به لایسنس پولی (Server یا Enterprise) نیاز دارد. لطفاً برای ارتقای طرح خود با مدیر تماس بگیرید." +saml2RequiresLicense = "ورود با SAML به لایسنس پولی (Server یا Enterprise) نیاز دارد. لطفاً برای ارتقای طرح خود با مدیر تماس بگیرید." +maxUsersReached = "حداکثر تعداد کاربران برای لایسنس کنونی شما به حد نصاب رسیده است. لطفاً برای ارتقای طرح یا افزودن کاربران بیشتر با مدیر تماس بگیرید." oauth2RequestNotFound = "درخواست احراز هویت پیدا نشد" oauth2InvalidUserInfoResponse = "پاسخ اطلاعات کاربری نامعتبر است" oauth2invalidRequest = "درخواست نامعتبر" @@ -3846,14 +3865,17 @@ fitToWidth = "تناسب با عرض" actualSize = "اندازه واقعی" [viewer] +cannotPreviewFile = "امکان پیش‌نمایش فایل نیست" +dualPageView = "نمای دوصفحه‌ای" firstPage = "صفحه نخست" lastPage = "صفحه آخر" -previousPage = "صفحه قبل" nextPage = "صفحه بعد" +onlyPdfSupported = "نمایشگر فقط فایل‌های PDF را پشتیبانی می‌کند. به نظر می‌رسد این فایل قالب متفاوتی دارد." +previousPage = "صفحه قبل" +singlePageView = "نمای تک‌صفحه‌ای" +unknownFile = "فایل ناشناخته" zoomIn = "بزرگ‌نمایی" zoomOut = "کوچک‌نمایی" -singlePageView = "نمای تک‌صفحه‌ای" -dualPageView = "نمای دوصفحه‌ای" [rightRail] closeSelected = "بستن فایل‌های انتخاب‌شده" @@ -3877,6 +3899,7 @@ toggleSidebar = "تغییر وضعیت نوار کناری" exportSelected = "برون‌بری صفحات انتخاب‌شده" toggleAnnotations = "تغییر وضعیت نمایش حاشیه‌نویسی‌ها" annotationMode = "تغییر حالت حاشیه‌نویسی" +print = "چاپ PDF" draw = "رسم" save = "ذخیره" saveChanges = "ذخیره تغییرات" @@ -4487,13 +4510,14 @@ label = "خط‌مشی کوکی" description = "URL یا نام فایل برای خط‌مشی کوکی" [admin.settings.legal.impressum] -label = "Impressum" +label = "اطلاعات حقوقی" description = "URL یا نام فایل برای impressum (در برخی حوزه‌های قضایی الزامی است)" [admin.settings.premium] title = "پرمیوم و سازمانی" description = "کلید لایسنس پرمیوم یا سازمانی خود را پیکربندی کنید." license = "پیکربندی لایسنس" +noInput = "لطفاً کلید یا فایل مجوز را ارائه کنید" [admin.settings.premium.licenseKey] toggle = "کلید لایسنس یا فایل گواهی دارید؟" @@ -4511,6 +4535,25 @@ line1 = "بازنویسی کلید لایسنس فعلی قابل بازگشت line2 = "مگر آنکه در جایی پشتیبان گرفته باشید، لایسنس قبلی به‌طور دائمی از دست می‌رود." line3 = "مهم: کلیدهای لایسنس را خصوصی و امن نگه دارید. هرگز آن‌ها را عمومی به‌اشتراک نگذارید." +[admin.settings.premium.inputMethod] +text = "کلید مجوز" +file = "فایل گواهی" + +[admin.settings.premium.file] +label = "فایل گواهی مجوز" +description = "فایل مجوز .lic یا .cert مربوط به خریدهای آفلاین خود را بارگذاری کنید" +choose = "انتخاب فایل مجوز" +selected = "انتخاب‌شده: {{filename}} ({{size}})" +successMessage = "فایل مجوز با موفقیت بارگذاری و فعال شد. نیازی به راه‌اندازی مجدد نیست." + +[admin.settings.premium.currentLicense] +title = "مجوز فعال" +file = "منبع: فایل مجوز ({{path}})" +key = "منبع: کلید مجوز" +type = "نوع: {{type}}" +noInput = "لطفاً کلید مجوز ارائه کنید یا فایل گواهی را بارگذاری کنید" +success = "موفق" + [admin.settings.premium.enabled] label = "فعال‌سازی قابلیت‌های پرمیوم" description = "فعال‌سازی بررسی کلید لایسنس برای قابلیت‌های حرفه‌ای/سازمانی" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} مورد انتخاب‌شده" download = "دانلود" delete = "حذف" unsupported = "پشتیبانی‌نشده" +active = "فعال" addToUpload = "افزودن به بارگذاری" +closeFile = "بستن فایل" deleteAll = "حذف همه" loadingFiles = "در حال بارگذاری فایل‌ها..." noFiles = "فایلی موجود نیست" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "حداقل یک آدرس ایمیل الزامی است" submit = "ارسال دعوت‌نامه‌ها" success = "کاربر(ان) با موفقیت دعوت شد(ند)" -partialSuccess = "برخی دعوت‌ها ناموفق بود" +partialFailure = "برخی دعوت‌ها ناموفق بودند" allFailed = "دعوت کاربران ناموفق بود" error = "ارسال دعوت‌نامه‌ها ناموفق بود" @@ -5797,6 +5842,13 @@ submit = "ورود" signInWith = "ورود با" oauthPending = "در حال باز کردن مرورگر برای احراز هویت..." orContinueWith = "یا با ایمیل ادامه دهید" +serverRequirement = "توجه: سرور باید ورود را فعال کرده باشد." +showInstructions = "نحوه فعال‌سازی؟" +hideInstructions = "مخفی کردن دستورالعمل‌ها" +instructions = "برای فعال‌سازی ورود در سرور Stirling PDF خود:" +instructionsEnvVar = "متغیر محیطی را تنظیم کنید:" +instructionsOrYml = "یا در settings.yml:" +instructionsRestart = "سپس سرور خود را راه‌اندازی مجدد کنید تا تغییرات اعمال شوند." [setup.login.username] label = "نام کاربری" diff --git a/frontend/public/locales/fr-FR/translation.toml b/frontend/public/locales/fr-FR/translation.toml index 2bd5da5c5..5ae44d3f7 100644 --- a/frontend/public/locales/fr-FR/translation.toml +++ b/frontend/public/locales/fr-FR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Retirer des favoris" fullscreen = "Passer en mode plein écran" sidebar = "Passer en mode barre latérale" +[backendStartup] +notFoundTitle = "Backend introuvable" +retry = "Réessayer" +unreachable = "L’application ne peut actuellement pas se connecter au backend. Vérifiez l’état du backend et la connectivité réseau, puis réessayez." + [zipWarning] title = "Fichier ZIP volumineux" message = "Ce ZIP contient {{count}} fichiers. Extraire quand même ?" @@ -347,7 +352,7 @@ teams = "Équipes" title = "Configuration" systemSettings = "Paramètres système" features = "Fonctionnalités" -endpoints = "Endpoints" +endpoints = "Points de terminaison" database = "Base de données" advanced = "Avancé" @@ -912,6 +917,9 @@ desc = "Créez des workflows multi-étapes en enchaînant des actions PDF. Idéa desc = "Superposer un PDF sur un autre" title = "Superposer des PDF" +[home.pdfTextEditor] +title = "Éditeur de texte PDF" +desc = "Modifier le texte et les images existants dans les PDF" [home.addText] tags = "texte,annotation,étiquette" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Signature dessinée" defaultImageLabel = "Signature téléversée" defaultTextLabel = "Signature saisie" saveButton = "Enregistrer la signature" +savePersonal = "Enregistrer en personnel" +saveShared = "Enregistrer en partagé" saveUnavailable = "Créez d’abord une signature pour l’enregistrer." noChanges = "La signature actuelle est déjà enregistrée." +tempStorageTitle = "Stockage temporaire du navigateur" +tempStorageDescription = "Les signatures sont stockées uniquement dans votre navigateur. Elles seront perdues si vous effacez les données du navigateur ou si vous changez de navigateur." +personalHeading = "Signatures personnelles" +sharedHeading = "Signatures partagées" +personalDescription = "Vous seul pouvez voir ces signatures." +sharedDescription = "Tous les utilisateurs peuvent voir et utiliser ces signatures." [sign.saved.type] canvas = "Dessin" @@ -3438,6 +3454,9 @@ signinTitle = "Veuillez vous connecter" ssoSignIn = "Se connecter via l'authentification unique" oAuth2AutoCreateDisabled = "OAUTH2 Création automatique d'utilisateur désactivée" oAuth2AdminBlockedUser = "La création ou l'authentification d'utilisateurs non enregistrés est actuellement bloquée. Veuillez contacter l'administrateur." +oAuth2RequiresLicense = "La connexion OAuth/SSO nécessite une licence payante (Server ou Enterprise). Veuillez contacter l’administrateur pour mettre à niveau votre plan." +saml2RequiresLicense = "La connexion SAML nécessite une licence payante (Server ou Enterprise). Veuillez contacter l’administrateur pour mettre à niveau votre plan." +maxUsersReached = "Nombre maximal d’utilisateurs atteint pour votre licence actuelle. Veuillez contacter l’administrateur pour mettre à niveau votre plan ou ajouter des places." oauth2RequestNotFound = "Demande d'autorisation introuvable" oauth2InvalidUserInfoResponse = "Réponse contenant les informations de l'utilisateur est invalide" oauth2invalidRequest = "Requête invalide" @@ -3846,14 +3865,17 @@ fitToWidth = "Ajuster à la largeur" actualSize = "Taille réelle" [viewer] +cannotPreviewFile = "Impossible d’afficher un aperçu du fichier" +dualPageView = "Vue double page" firstPage = "Première page" lastPage = "Dernière page" -previousPage = "Page précédente" nextPage = "Page suivante" +onlyPdfSupported = "Le visualiseur prend uniquement en charge les fichiers PDF. Ce fichier semble être d’un autre format." +previousPage = "Page précédente" +singlePageView = "Vue page unique" +unknownFile = "Fichier inconnu" zoomIn = "Zoom avant" zoomOut = "Zoom arrière" -singlePageView = "Vue page unique" -dualPageView = "Vue double page" [rightRail] closeSelected = "Fermer les fichiers sélectionnés" @@ -3877,6 +3899,7 @@ toggleSidebar = "Afficher/masquer la barre latérale" exportSelected = "Exporter les pages sélectionnées" toggleAnnotations = "Afficher/masquer les annotations" annotationMode = "Basculer en mode annotation" +print = "Imprimer le PDF" draw = "Dessiner" save = "Enregistrer" saveChanges = "Enregistrer les modifications" @@ -4153,7 +4176,7 @@ description = "Suivre les actions des utilisateurs et les événements système [admin.settings.security.audit.level] label = "Niveau d’audit" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=DÉSACTIVÉ, 1=BASIQUE, 2=STANDARD, 3=VERBEUX" [admin.settings.security.audit.retentionDays] label = "Rétention des journaux (jours)" @@ -4491,9 +4514,10 @@ label = "Mentions légales" description = "URL ou nom de fichier de l’impressum (obligatoire dans certaines juridictions)" [admin.settings.premium] -title = "Premium & Enterprise" +title = "Premium et Entreprise" description = "Configurer votre clé de licence Premium ou Enterprise." license = "Configuration de la licence" +noInput = "Veuillez fournir une clé de licence ou un fichier" [admin.settings.premium.licenseKey] toggle = "Vous avez une clé de licence ou un fichier de certificat ?" @@ -4511,6 +4535,25 @@ line1 = "Écraser votre clé de licence actuelle est irréversible." line2 = "Votre licence précédente sera définitivement perdue, sauf si vous l’avez sauvegardée ailleurs." line3 = "Important : gardez vos clés de licence privées et sécurisées. Ne les partagez jamais publiquement." +[admin.settings.premium.inputMethod] +text = "Clé de licence" +file = "Fichier de certificat" + +[admin.settings.premium.file] +label = "Fichier de certificat de licence" +description = "Téléversez votre fichier de licence .lic ou .cert issu d’achats hors ligne" +choose = "Choisir le fichier de licence" +selected = "Sélectionné: {{filename}} ({{size}})" +successMessage = "Fichier de licence téléversé et activé avec succès. Aucun redémarrage requis." + +[admin.settings.premium.currentLicense] +title = "Licence active" +file = "Source: Fichier de licence ({{path}})" +key = "Source: Clé de licence" +type = "Type: {{type}}" +noInput = "Veuillez fournir une clé de licence ou téléverser un fichier de certificat" +success = "Succès" + [admin.settings.premium.enabled] label = "Activer les fonctionnalités Premium" description = "Activer la vérification de la clé de licence pour les fonctionnalités Pro/Enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} sélectionné(s)" download = "Télécharger" delete = "Supprimer" unsupported = "Non pris en charge" +active = "Actif" addToUpload = "Ajouter au téléversement" +closeFile = "Fermer le fichier" deleteAll = "Tout supprimer" loadingFiles = "Chargement des fichiers..." noFiles = "Aucun fichier disponible" @@ -5178,7 +5223,7 @@ active = "Actif" disabled = "Désactivé" activeSession = "Session active" member = "Membre" -admin = "Admin" +admin = "Administrateur" editRole = "Modifier le rôle" enable = "Activer" disable = "Désactiver" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Au moins une adresse e-mail est requise" submit = "Envoyer les invitations" success = "Utilisateur(s) invité(s) avec succès" -partialSuccess = "Certaines invitations ont échoué" +partialFailure = "Certaines invitations ont échoué" allFailed = "Échec de l’invitation des utilisateurs" error = "Échec de l’envoi des invitations" @@ -5709,7 +5754,7 @@ title = "Graphique d’utilisation des endpoints" [usage.table] title = "Statistiques détaillées" -endpoint = "Endpoint" +endpoint = "Point de terminaison" visits = "Visites" percentage = "Pourcentage" noData = "Aucune donnée disponible" @@ -5797,13 +5842,20 @@ submit = "Se connecter" signInWith = "Se connecter avec" oauthPending = "Ouverture du navigateur pour l'authentification..." orContinueWith = "Ou continuer avec l’email" +serverRequirement = "Remarque : le serveur doit avoir la connexion activée." +showInstructions = "Comment l’activer ?" +hideInstructions = "Masquer les instructions" +instructions = "Pour activer la connexion sur votre serveur Stirling PDF :" +instructionsEnvVar = "Définissez la variable d’environnement :" +instructionsOrYml = "Ou dans settings.yml :" +instructionsRestart = "Redémarrez ensuite votre serveur pour que les modifications prennent effet." [setup.login.username] label = "Nom d’utilisateur" placeholder = "Entrez votre nom d’utilisateur" [setup.login.email] -label = "Email" +label = "E-mail" placeholder = "Saisissez votre email" [setup.login.password] diff --git a/frontend/public/locales/ga-IE/translation.toml b/frontend/public/locales/ga-IE/translation.toml index d34fbfba5..254c8578a 100644 --- a/frontend/public/locales/ga-IE/translation.toml +++ b/frontend/public/locales/ga-IE/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Bain den Cheanáin" fullscreen = "Athraigh go mód lánscáileáin" sidebar = "Athraigh go mód barra taoibh" +[backendStartup] +notFoundTitle = "Níor aimsíodh an cúlchóras" +retry = "Atriail" +unreachable = "Ní féidir leis an bhfeidhmchlár ceangal leis an gcúlchóras faoi láthair. Deimhnigh stádas an chúlchórais agus nascacht an líonra, ansin bain triail eile as." + [zipWarning] title = "Comhad ZIP Mór" message = "Tá {{count}} comhad sa ZIP seo. An mbaineann tú amach mar sin féin?" @@ -912,6 +917,9 @@ desc = "Tóg sreafaí oibre ilchéime trí ghníomhartha PDF a nascadh le chéil desc = "Forleagain PDF ar bharr PDF eile" title = "Forleagan PDF" +[home.pdfTextEditor] +title = "Eagarthóir Téacs PDF" +desc = "Cuir téacs agus íomhánna atá ann cheana in eagar laistigh de PDFanna" [home.addText] tags = "téacs,anótáil,lipéad" @@ -1635,7 +1643,7 @@ subtitle = "Íoslódáil an comhad próiseáilte nó cealaigh an oibríocht thí [removePages] tags = "Bain leathanaigh, scrios leathanaigh" title = "Bain" -filenamePrefix = "pages_removed" +filenamePrefix = "leathanaigh_bainte" submit = "Bain" [removePages.pageNumbers] @@ -1837,7 +1845,7 @@ title = "Bain Léamh-Amháin ó Réimsí Foirme" header = "Díghlasáil Foirmeacha PDF" submit = "Remove" description = "Bainfidh an uirlis seo srianta léamh-amáin ó réimsí foirme PDF, rud a fhágann go mbeidh siad in-eagarthóireachta agus inlíonta." -filenamePrefix = "unlocked_forms" +filenamePrefix = "foirmeacha_díghlasáilte" [unlockPDFForms.files] placeholder = "Roghnaigh comhad PDF sa phríomh-amharc chun tosú" @@ -1851,7 +1859,7 @@ title = "Torthaí Díghlasála Foirmeacha" [changeMetadata] header = "Athraigh Meiteashonraí" submit = "Athrú" -filenamePrefix = "metadata" +filenamePrefix = "meiteashonraí" [changeMetadata.settings] title = "Socruithe Meiteashonraí" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Síniú líníochta" defaultImageLabel = "Síniú uaslódáilte" defaultTextLabel = "Síniú clóscríofa" saveButton = "Sábháil síniú" +savePersonal = "Sábháil Pearsanta" +saveShared = "Sábháil Comhroinnte" saveUnavailable = "Cruthaigh síniú ar dtús chun é a shábháil." noChanges = "Tá an síniú reatha sábháilte cheana." +tempStorageTitle = "Stóráil shealadach an bhrabhsálaí" +tempStorageDescription = "Stóráiltear na sínithe i do bhrabhsálaí amháin. Caillfear iad má ghlanann tú sonraí an bhrabhsálaí nó má athraíonn tú brabhsálaithe." +personalHeading = "Sínithe Pearsanta" +sharedHeading = "Sínithe Comhroinnte" +personalDescription = "Ní féidir ach leatsa na sínithe seo a fheiceáil." +sharedDescription = "Is féidir le gach úsáideoir na sínithe seo a fheiceáil agus a úsáid." [sign.saved.type] canvas = "Líníocht" @@ -2318,7 +2334,7 @@ title = "Comhcheangail" header = "PDF cothromú" flattenOnlyForms = "Flatten foirmeacha amháin" submit = "Comhcheangail" -filenamePrefix = "flattened" +filenamePrefix = "maolaithe" [flatten.files] placeholder = "Roghnaigh comhad PDF sa phríomh-amharc chun tosú" @@ -2366,7 +2382,7 @@ title = "Deisiúchán" header = "PDF a dheisiú" submit = "Deisiúchán" description = "Déanfaidh an uirlis seo iarracht comhaid PDF truaillithe nó damáiste a dheisiú. Níl aon socruithe breise ag teastáil." -filenamePrefix = "repaired" +filenamePrefix = "deisithe" [repair.files] placeholder = "Roghnaigh comhad PDF sa phríomh-amharc chun tosú" @@ -2567,7 +2583,7 @@ stopButton = "Stop comparáid" [certSign] tags = "fíordheimhnigh, PEM, P12, oifigiúil, criptigh" title = "Síniú Teastais" -filenamePrefix = "signed" +filenamePrefix = "síníthe" chooseCertificate = "Roghnaigh Comhad Teastais" chooseJksFile = "Roghnaigh Comhad JKS" chooseP12File = "Roghnaigh Comhad PKCS12" @@ -2701,7 +2717,7 @@ header = "Bain an deimhniú digiteach ó PDF" selectPDF = "Roghnaigh comhad PDF:" submit = "Bain Síniú" description = "Bainfidh an uirlis seo sínithe teastais dhigiteacha de do dhoiciméad PDF." -filenamePrefix = "unsigned" +filenamePrefix = "neamhshínithe" [removeCertSign.files] placeholder = "Roghnaigh comhad PDF sa phríomh-amharc chun tosú" @@ -3438,6 +3454,9 @@ signinTitle = "Sínigh isteach le do thoil" ssoSignIn = "Logáil isteach trí Chlárú Aonair" oAuth2AutoCreateDisabled = "OAUTH2 Uath-Chruthaigh Úsáideoir faoi Mhíchumas" oAuth2AdminBlockedUser = "Tá bac faoi láthair ar chlárú nó logáil isteach úsáideoirí neamhchláraithe. Déan teagmháil leis an riarthóir le do thoil." +oAuth2RequiresLicense = "Teastaíonn ceadúnas íoctha (Server nó Enterprise) chun logáil isteach le OAuth/SSO. Déan teagmháil leis an riarthóir chun do phlean a uasghrádú." +saml2RequiresLicense = "Teastaíonn ceadúnas íoctha (Server nó Enterprise) chun logáil isteach le SAML. Déan teagmháil leis an riarthóir chun do phlean a uasghrádú." +maxUsersReached = "Sroicheadh an líon uasta úsáideoirí do do cheadúnas reatha. Déan teagmháil leis an riarthóir chun do phlean a uasghrádú nó suíocháin bhreise a chur leis." oauth2RequestNotFound = "Níor aimsíodh iarratas údaraithe" oauth2InvalidUserInfoResponse = "Freagra Neamhbhailí Faisnéise Úsáideora" oauth2invalidRequest = "Iarratas Neamhbhailí" @@ -3533,7 +3552,7 @@ title = "PDF go leathanach amháin" header = "PDF go leathanach amháin" submit = "Tiontaigh go Leathanach Aonair" description = "Cuirfidh an uirlis seo gach leathanach de do PDF le chéile in aon leathanach mór amháin. Fanfaidh an leithead mar an gcéanna leis na leathanaigh bhunaidh, ach beidh an airde cothrom le suim airde na leathanach go léir." -filenamePrefix = "single_page" +filenamePrefix = "leathanach_aonair" [pdfToSinglePage.files] placeholder = "Roghnaigh comhad PDF sa phríomh-amharc chun tosú" @@ -3846,14 +3865,17 @@ fitToWidth = "Oiriúnaigh don Leithead" actualSize = "Fíormhéid" [viewer] +cannotPreviewFile = "Ní féidir an comhad a réamhamharc." +dualPageView = "Amharc Dhá Leathanach" firstPage = "An Chéad Leathanach" lastPage = "An Leathanach Deireanach" -previousPage = "Leathanach Roimhe Seo" nextPage = "Leathanach Ar Aghaidh" +onlyPdfSupported = "Ní thacaíonn an t-amharcán ach le comhaid PDF. Is cosúil gur formáid eile é an comhad seo." +previousPage = "Leathanach Roimhe Seo" +singlePageView = "Amharc Leathanach Aonair" +unknownFile = "Comhad anaithnid" zoomIn = "Súmáil Isteach" zoomOut = "Súmáil Amach" -singlePageView = "Amharc Leathanach Aonair" -dualPageView = "Amharc Dhá Leathanach" [rightRail] closeSelected = "Dún na Comhaid Roghnaithe" @@ -3877,6 +3899,7 @@ toggleSidebar = "Athraigh an Barra Taoibh" exportSelected = "Easpórtáil na Leathanaigh Roghnaithe" toggleAnnotations = "Athraigh Infheictheacht Anótálacha" annotationMode = "Athraigh Mód Anótála" +print = "Priontáil PDF" draw = "Tarraing" save = "Sábháil" saveChanges = "Sábháil Athruithe" @@ -4494,6 +4517,7 @@ description = "URL nó ainm comhaid don impressum (riachtanach i roinnt dlínsí title = "Préimh & Fiontar" description = "Cumraigh do eochair cheadúnais préimhe nó fiontair." license = "Cumraíocht Ceadúnais" +noInput = "Tabhair eochair nó comhad ceadúnais, le do thoil" [admin.settings.premium.licenseKey] toggle = "An bhfuil eochair cheadúnais nó comhad teastais agat?" @@ -4511,6 +4535,25 @@ line1 = "Ní féidir forshcríobh ar do eochair cheadúnais reatha a chealú." line2 = "Caillefar do cheadúnas roimhe seo go buan mura bhfuil cúltaca de in áit eile agat." line3 = "Tábhachtach: Coinnigh eochracha ceadúnais príobháideach agus slán. Ná roinn go poiblí riamh." +[admin.settings.premium.inputMethod] +text = "Eochair Ceadúnais" +file = "Comhad Teastais" + +[admin.settings.premium.file] +label = "Comhad Teastais Ceadúnais" +description = "Uaslódáil do chomhad ceadúnais .lic nó .cert ó cheannacháin as líne" +choose = "Roghnaigh Comhad Ceadúnais" +selected = "Roghnaithe: {{filename}} ({{size}})" +successMessage = "D’éirigh le huaslódáil agus gníomhachtú an chomhaid cheadúnais. Níl atosú ag teastáil." + +[admin.settings.premium.currentLicense] +title = "Ceadúnas Gníomhach" +file = "Foinse: Comhad ceadúnais ({{path}})" +key = "Foinse: Eochair ceadúnais" +type = "Cineál: {{type}}" +noInput = "Tabhair eochair ceadúnais nó uaslódáil comhad teastais, le do thoil" +success = "Rath" + [admin.settings.premium.enabled] label = "Cumasaigh Gnéithe Préimhe" description = "Cumasaigh seiceálacha eochrach ceadúnais do ghnéithe pro/fiontair" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} roghnaithe" download = "Íosluchtaigh" delete = "Scrios" unsupported = "Gan tacaíocht" +active = "Gníomhach" addToUpload = "Cuir leis an Uaslódáil" +closeFile = "Dún an comhad" deleteAll = "Scrios Uile" loadingFiles = "Comhaid á Luchtú..." noFiles = "Níl comhaid ar fáil" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Tá ar a laghad seoladh ríomhphoist amháin de dhíth" submit = "Seol Cuirí" success = "Tugadh cuireadh d’úsáideoir(í) go rathúil" -partialSuccess = "Theip ar chuid de na cuirí" +partialFailure = "Níor éirigh le roinnt cuirí" allFailed = "Theip ar úsáideoirí a thabhairt isteach" error = "Theip ar churí a sheoladh" @@ -5797,6 +5842,13 @@ submit = "Logáil Isteach" signInWith = "Sínigh isteach le" oauthPending = "Brabhsálaí á oscailt le haghaidh fíordheimhnithe..." orContinueWith = "Nó lean ar aghaidh le ríomhphost" +serverRequirement = "Nóta: Ní mór an cumas logála isteach a bheith cumasaithe ar an bhfreastalaí." +showInstructions = "Conas é a chumasú?" +hideInstructions = "Folaigh na treoracha" +instructions = "Chun logáil isteach a chumasú ar do fhreastalaí Stirling PDF:" +instructionsEnvVar = "Socraigh an athróg chomhshaoil:" +instructionsOrYml = "Nó i settings.yml:" +instructionsRestart = "Ansin atosaigh do fhreastalaí chun go mbeidh na hathruithe i bhfeidhm." [setup.login.username] label = "Ainm Úsáideora" diff --git a/frontend/public/locales/hi-IN/translation.toml b/frontend/public/locales/hi-IN/translation.toml index f0fcf7833..c569e48ba 100644 --- a/frontend/public/locales/hi-IN/translation.toml +++ b/frontend/public/locales/hi-IN/translation.toml @@ -131,7 +131,7 @@ unsupported = "असमर्थित" [toolPanel] placeholder = "शुरू करने के लिए कोई टूल चुनें" -alpha = "Alpha" +alpha = "अल्फा" premiumFeature = "प्रीमियम फीचर:" comingSoon = "जल्द आ रहा है:" @@ -163,6 +163,11 @@ unfavorite = "पसंदीदा से हटाएं" fullscreen = "फुलस्क्रीन मोड पर स्विच करें" sidebar = "साइडबार मोड पर स्विच करें" +[backendStartup] +notFoundTitle = "बैकएंड नहीं मिला" +retry = "पुनः प्रयास करें" +unreachable = "एप्लिकेशन फिलहाल बैकएंड से कनेक्ट नहीं हो पा रहा है। कृपया बैकएंड की स्थिति और नेटवर्क कनेक्टिविटी जांचें, फिर पुनः प्रयास करें।" + [zipWarning] title = "बड़ी ZIP फ़ाइल" message = "इस ZIP में {{count}} फ़ाइलें हैं। फिर भी निकालें?" @@ -369,7 +374,7 @@ privacy = "गोपनीयता" [settings.developer] title = "डेवलपर" -apiKeys = "API Keys" +apiKeys = "API कुंजियाँ" [settings.tooltips] enableLoginFirst = "पहले लॉगिन मोड सक्षम करें" @@ -912,6 +917,9 @@ desc = "PDF क्रियाओं को जोड़कर बहु-चर desc = "PDF को दूसरी PDF के ऊपर ओवरले करें" title = "PDF ओवरले करें" +[home.pdfTextEditor] +title = "PDF टेक्स्ट एडिटर" +desc = "PDF फ़ाइलों के भीतर मौजूदा टेक्स्ट और इमेज संपादित करें" [home.addText] tags = "text,annotation,label" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "शुरू करने के लिए मुख settings = "सेटिंग्स" conversionCompleted = "रूपांतरण पूरा हुआ" results = "परिणाम" -defaultFilename = "converted_file" +defaultFilename = "परिवर्तित_फ़ाइल" conversionResults = "रूपांतरण परिणाम" convertFrom = "से रूपांतरित करें" convertTo = "में रूपांतरित करें" @@ -1216,8 +1224,8 @@ wordDocExt = "Word दस्तावेज़ (.docx)" odtExt = "OpenDocument Text (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "OpenDocument Presentation (.odp)" -txtExt = "Plain Text (.txt)" -rtfExt = "Rich Text Format (.rtf)" +txtExt = "सादा पाठ (.txt)" +rtfExt = "रिच टेक्स्ट फ़ॉर्मेट (.rtf)" selectedFiles = "चयनित फ़ाइलें" noFileSelected = "कोई फ़ाइल चयनित नहीं। फ़ाइलें जोड़ने के लिए फ़ाइल पैनल का उपयोग करें।" convertFiles = "फ़ाइलें रूपांतरित करें" @@ -1360,7 +1368,7 @@ title = "वॉटरमार्क जोड़ें" desc = "PDF फ़ाइलों में टेक्स्ट या इमेज वॉटरमार्क जोड़ें" completed = "वॉटरमार्क जोड़ा गया" submit = "वॉटरमार्क जोड़ें" -filenamePrefix = "watermarked" +filenamePrefix = "वॉटरमार्क_युक्त" [watermark.error] failed = "PDF में वॉटरमार्क जोड़ते समय एक त्रुटि हुई।" @@ -1635,7 +1643,7 @@ subtitle = "प्रोसेस्ड फ़ाइल डाउनलोड [removePages] tags = "पृष्ठ निकालें,पृष्ठ हटाएं" title = "निकालें" -filenamePrefix = "pages_removed" +filenamePrefix = "पृष्ठ_हटाए_गए" submit = "निकालें" [removePages.pageNumbers] @@ -1837,7 +1845,7 @@ title = "फॉर्म फ़ील्ड से Read-Only हटाएं" header = "PDF फॉर्म अनलॉक करें" submit = "Remove" description = "यह टूल PDF फॉर्म फ़ील्ड से Read-Only प्रतिबंध हटाएगा, जिससे वे संपादन योग्य और भरने योग्य बनेंगे।" -filenamePrefix = "unlocked_forms" +filenamePrefix = "अनलॉक_फ़ॉर्म" [unlockPDFForms.files] placeholder = "शुरू करने के लिए मुख्य दृश्य में एक PDF फ़ाइल चुनें" @@ -1851,7 +1859,7 @@ title = "अनलॉक किए गए फॉर्म के परिणा [changeMetadata] header = "मेटाडेटा बदलें" submit = "बदलें" -filenamePrefix = "metadata" +filenamePrefix = "मेटाडेटा" [changeMetadata.settings] title = "मेटाडेटा सेटिंग्स" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "ड्रॉइंग हस्ताक्षर" defaultImageLabel = "अपलोड किया गया हस्ताक्षर" defaultTextLabel = "टाइप किया हुआ हस्ताक्षर" saveButton = "हस्ताक्षर सहेजें" +savePersonal = "व्यक्तिगत सहेजें" +saveShared = "साझा सहेजें" saveUnavailable = "सेव करने के लिए पहले एक हस्ताक्षर बनाएँ।" noChanges = "वर्तमान हस्ताक्षर पहले से सहेजा गया है।" +tempStorageTitle = "अस्थायी ब्राउज़र संग्रहण" +tempStorageDescription = "हस्ताक्षर केवल आपके ब्राउज़र में संग्रहीत होते हैं। ब्राउज़र डेटा साफ़ करने या ब्राउज़र बदलने पर वे खो जाएंगे।" +personalHeading = "व्यक्तिगत हस्ताक्षर" +sharedHeading = "साझा हस्ताक्षर" +personalDescription = "इन हस्ताक्षरों को केवल आप देख सकते हैं।" +sharedDescription = "सभी उपयोगकर्ता इन हस्ताक्षरों को देख और उपयोग कर सकते हैं।" [sign.saved.type] canvas = "ड्रॉइंग" @@ -2318,7 +2334,7 @@ title = "समतल करें" header = "PDF समतल करें" flattenOnlyForms = "केवल फ़ॉर्म समतल करें" submit = "समतल करें" -filenamePrefix = "flattened" +filenamePrefix = "समतलीकृत" [flatten.files] placeholder = "शुरू करने के लिए मुख्य दृश्य में एक PDF फ़ाइल चुनें" @@ -2366,7 +2382,7 @@ title = "मरम्मत" header = "PDF मरम्मत" submit = "मरम्मत" description = "यह टूल भ्रष्ट या क्षतिग्रस्त PDF फ़ाइलों की मरम्मत करने का प्रयास करेगा। कोई अतिरिक्त सेटिंग्स आवश्यक नहीं हैं।" -filenamePrefix = "repaired" +filenamePrefix = "मरम्मत_किया" [repair.files] placeholder = "शुरू करने के लिए मुख्य दृश्य में एक PDF फ़ाइल चुनें" @@ -2567,7 +2583,7 @@ stopButton = "तुलना रोकें" [certSign] tags = "प्रमाणीकरण,PEM,P12,आधिकारिक,एन्क्रिप्ट" title = "प्रमाणपत्र हस्ताक्षर" -filenamePrefix = "signed" +filenamePrefix = "हस्ताक्षरित" chooseCertificate = "प्रमाणपत्र फ़ाइल चुनें" chooseJksFile = "JKS फ़ाइल चुनें" chooseP12File = "PKCS12 फ़ाइल चुनें" @@ -2701,7 +2717,7 @@ header = "PDF से डिजिटल प्रमाणपत्र हटा selectPDF = "PDF फ़ाइल चुनें:" submit = "हस्ताक्षर हटाएं" description = "यह टूल आपके PDF दस्तावेज़ से डिजिटल प्रमाणपत्र हस्ताक्षर हटाएगा।" -filenamePrefix = "unsigned" +filenamePrefix = "अनहस्ताक्षरित" [removeCertSign.files] placeholder = "शुरू करने के लिए मुख्य दृश्य में एक PDF फ़ाइल चुनें" @@ -3438,6 +3454,9 @@ signinTitle = "कृपया साइन इन करें" ssoSignIn = "सिंगल साइन-ऑन के माध्यम से लॉगिन करें" oAuth2AutoCreateDisabled = "OAUTH2 स्वतः उपयोगकर्ता निर्माण अक्षम है" oAuth2AdminBlockedUser = "गैर-पंजीकृत उपयोगकर्ताओं का पंजीकरण या लॉगिन वर्तमान में अवरुद्ध है। कृपया व्यवस्थापक से संपर्क करें।" +oAuth2RequiresLicense = "OAuth/SSO लॉगिन के लिए पेड लाइसेंस (Server या Enterprise) आवश्यक है। कृपया अपना प्लान अपग्रेड करने के लिए व्यवस्थापक से संपर्क करें।" +saml2RequiresLicense = "SAML लॉगिन के लिए पेड लाइसेंस (Server या Enterprise) आवश्यक है। कृपया अपना प्लान अपग्रेड करने के लिए व्यवस्थापक से संपर्क करें।" +maxUsersReached = "आपके वर्तमान लाइसेंस के लिए उपयोगकर्ताओं की अधिकतम सीमा पूरी हो चुकी है। कृपया अपना प्लान अपग्रेड करने या अधिक सीटें जोड़ने के लिए व्यवस्थापक से संपर्क करें।" oauth2RequestNotFound = "प्राधिकरण अनुरोध नहीं मिला" oauth2InvalidUserInfoResponse = "अमान्य उपयोगकर्ता जानकारी प्रतिक्रिया" oauth2invalidRequest = "अमान्य अनुरोध" @@ -3533,7 +3552,7 @@ title = "PDF को एकल पृष्ठ में" header = "PDF को एकल पृष्ठ में" submit = "एकल पृष्ठ में बदलें" description = "यह टूल आपके PDF के सभी पृष्ठों को एक बड़े एकल पृष्ठ में मिला देगा। चौड़ाई मूल पृष्ठों जैसी ही रहेगी, पर ऊँचाई सभी पृष्ठ ऊँचाइयों का योग होगी।" -filenamePrefix = "single_page" +filenamePrefix = "एकल_पृष्ठ" [pdfToSinglePage.files] placeholder = "शुरू करने के लिए मुख्य दृश्य में एक PDF फ़ाइल चुनें" @@ -3846,14 +3865,17 @@ fitToWidth = "चौड़ाई के अनुसार फिट करे actualSize = "वास्तविक आकार" [viewer] +cannotPreviewFile = "फ़ाइल का पूर्वावलोकन नहीं किया जा सकता" +dualPageView = "दोहरा पृष्ठ दृश्य" firstPage = "पहला पृष्ठ" lastPage = "अंतिम पृष्ठ" -previousPage = "पिछला पृष्ठ" nextPage = "अगला पृष्ठ" +onlyPdfSupported = "व्यूअर केवल PDF फ़ाइलों का समर्थन करता है। यह फ़ाइल किसी भिन्न फ़ॉर्मेट में प्रतीत होती है।" +previousPage = "पिछला पृष्ठ" +singlePageView = "एकल पृष्ठ दृश्य" +unknownFile = "अज्ञात फ़ाइल" zoomIn = "ज़ूम इन" zoomOut = "ज़ूम आउट" -singlePageView = "एकल पृष्ठ दृश्य" -dualPageView = "दोहरा पृष्ठ दृश्य" [rightRail] closeSelected = "चयनित फ़ाइलें बंद करें" @@ -3877,6 +3899,7 @@ toggleSidebar = "साइडबार टॉगल करें" exportSelected = "चयनित पृष्ठ निर्यात करें" toggleAnnotations = "एनोटेशन दृश्यता टॉगल करें" annotationMode = "एनोटेशन मोड टॉगल करें" +print = "PDF प्रिंट करें" draw = "ड्रॉ" save = "सहेजें" saveChanges = "परिवर्तनों को सहेजें" @@ -4231,7 +4254,7 @@ label = "प्रदाता" description = "प्रमाणीकरण के लिए उपयोग किया जाने वाला OAuth2 प्रदाता" [admin.settings.connections.oauth2.issuer] -label = "Issuer URL" +label = "जारीकर्ता URL" description = "OAuth2 प्रदाता का Issuer URL" [admin.settings.connections.oauth2.clientId] @@ -4407,7 +4430,7 @@ description = "विस्तृत सिस्टम टेम्प डा label = "प्रोसेस एक्सीक्यूटर सीमाएँ" description = "प्रत्येक प्रोसेस एक्सीक्यूटर के लिए सेशन सीमाएँ और टाइमआउट कॉन्फ़िगर करें" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDF से HTML" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4494,6 +4517,7 @@ description = "Impressum का URL या फ़ाइल नाम (कुछ title = "प्रीमियम और एंटरप्राइज़" description = "अपनी प्रीमियम या एंटरप्राइज़ लाइसेंस कुंजी कॉन्फ़िगर करें।" license = "लाइसेंस कॉन्फ़िगरेशन" +noInput = "कृपया लाइसेंस कुंजी या फ़ाइल प्रदान करें" [admin.settings.premium.licenseKey] toggle = "क्या आपके पास लाइसेंस की या सर्टिफिकेट फ़ाइल है?" @@ -4511,6 +4535,25 @@ line1 = "वर्तमान लाइसेंस की को ओवरर line2 = "यदि आपने कहीं और बैकअप नहीं रखा है तो आपका पिछला लाइसेंस स्थायी रूप से खो जाएगा।" line3 = "महत्वपूर्ण: लाइसेंस की को निजी और सुरक्षित रखें। इन्हें कभी सार्वजनिक रूप से साझा न करें।" +[admin.settings.premium.inputMethod] +text = "लाइसेंस कुंजी" +file = "प्रमाणपत्र फ़ाइल" + +[admin.settings.premium.file] +label = "लाइसेंस प्रमाणपत्र फ़ाइल" +description = "ऑफ़लाइन खरीद से अपनी .lic या .cert लाइसेंस फ़ाइल अपलोड करें" +choose = "लाइसेंस फ़ाइल चुनें" +selected = "चयनित: {{filename}} ({{size}})" +successMessage = "लाइसेंस फ़ाइल सफलतापूर्वक अपलोड और सक्रिय की गई। पुनः आरंभ की आवश्यकता नहीं।" + +[admin.settings.premium.currentLicense] +title = "सक्रिय लाइसेंस" +file = "स्रोत: लाइसेंस फ़ाइल ({{path}})" +key = "स्रोत: लाइसेंस कुंजी" +type = "प्रकार: {{type}}" +noInput = "कृपया लाइसेंस कुंजी प्रदान करें या एक प्रमाणपत्र फ़ाइल अपलोड करें" +success = "सफलता" + [admin.settings.premium.enabled] label = "प्रीमियम फ़ीचर्स सक्रिय करें" description = "प्रो/एंटरप्राइज़ फ़ीचर्स के लिए लाइसेंस कुंजी जाँच सक्षम करें" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} चयनित" download = "डाउनलोड करें" delete = "हटाएं" unsupported = "असमर्थित" +active = "सक्रिय" addToUpload = "अपलोड में जोड़ें" +closeFile = "फ़ाइल बंद करें" deleteAll = "सब हटाएँ" loadingFiles = "फ़ाइलें लोड हो रही हैं..." noFiles = "कोई फ़ाइल उपलब्ध नहीं" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "कम से कम एक ईमेल पता आवश्यक है" submit = "आमंत्रण भेजें" success = "उपयोगकर्ता(ओं) को सफलतापूर्वक आमंत्रित किया गया" -partialSuccess = "कुछ आमंत्रण विफल रहे" +partialFailure = "कुछ निमंत्रण विफल हुए" allFailed = "उपयोगकर्ताओं को आमंत्रित करने में विफल" error = "आमंत्रण भेजने में विफल" @@ -5797,6 +5842,13 @@ submit = "लॉगिन" signInWith = "इसके साथ साइन इन करें" oauthPending = "प्रमाणीकरण के लिए ब्राउज़र खुल रहा है..." orContinueWith = "या ईमेल के साथ जारी रखें" +serverRequirement = "ध्यान दें: सर्वर पर लॉगिन सक्षम होना चाहिए।" +showInstructions = "कैसे सक्षम करें?" +hideInstructions = "निर्देश छिपाएँ" +instructions = "अपने Stirling PDF सर्वर पर लॉगिन सक्षम करने के लिए:" +instructionsEnvVar = "एन्वायरनमेंट वेरिएबल सेट करें:" +instructionsOrYml = "या settings.yml में:" +instructionsRestart = "इसके बाद बदलाव प्रभावी करने के लिए अपना सर्वर पुनः प्रारंभ करें।" [setup.login.username] label = "उपयोगकर्ता नाम" diff --git a/frontend/public/locales/hr-HR/translation.toml b/frontend/public/locales/hr-HR/translation.toml index c19e67180..3e68d5ce5 100644 --- a/frontend/public/locales/hr-HR/translation.toml +++ b/frontend/public/locales/hr-HR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Ukloni iz omiljenih" fullscreen = "Prebaci na način cijelog zaslona" sidebar = "Prebaci na način bočne trake" +[backendStartup] +notFoundTitle = "Backend nije pronađen" +retry = "Pokušaj ponovno" +unreachable = "Aplikacija se trenutačno ne može povezati s backendom. Provjerite status backenda i mrežnu povezanost, zatim pokušajte ponovno." + [zipWarning] title = "Velika ZIP datoteka" message = "Ovaj ZIP sadrži {{count}} datoteka. Ipak izdvojiti?" @@ -912,6 +917,9 @@ desc = "Izgradite višekoračne tijekove rada povezivanjem PDF radnji. Idealno z desc = "Preklapa PDF-ove na drugi PDF" title = "Preklapanje PDF-ova" +[home.pdfTextEditor] +title = "Uređivač teksta PDF-a" +desc = "Uređujte postojeći tekst i slike unutar PDF-ova" [home.addText] tags = "tekst,anotacija,oznaka" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Crtani potpis" defaultImageLabel = "Učitani potpis" defaultTextLabel = "Upisani potpis" saveButton = "Spremi potpis" +savePersonal = "Spremi osobno" +saveShared = "Spremi dijeljeno" saveUnavailable = "Najprije izradite potpis da biste ga spremili." noChanges = "Trenutačni potpis je već spremljen." +tempStorageTitle = "Privremena pohrana u pregledniku" +tempStorageDescription = "Potpisi se pohranjuju samo u vašem pregledniku. Izgubit će se ako očistite podatke preglednika ili promijenite preglednik." +personalHeading = "Osobni potpisi" +sharedHeading = "Dijeljeni potpisi" +personalDescription = "Samo vi možete vidjeti ove potpise." +sharedDescription = "Svi korisnici mogu vidjeti i koristiti ove potpise." [sign.saved.type] canvas = "Crtanje" @@ -3438,6 +3454,9 @@ signinTitle = "Molimo vas da se prijavite" ssoSignIn = "Prijavite se putem jedinstvene prijave" oAuth2AutoCreateDisabled = "OAUTH2 automatsko kreiranje korisnika je onemogućeno" oAuth2AdminBlockedUser = "Registracija ili prijava nekadreguiranih korisnika trenutno su blokirane. Molimo Vas da kontaktirate administratora." +oAuth2RequiresLicense = "Prijava putem OAuth/SSO zahtijeva plaćenu licencu (Server ili Enterprise). Obratite se administratoru radi nadogradnje vašeg plana." +saml2RequiresLicense = "Prijava putem SAML zahtijeva plaćenu licencu (Server ili Enterprise). Obratite se administratoru radi nadogradnje vašeg plana." +maxUsersReached = "Dosegnut je maksimalan broj korisnika za vašu trenutačnu licencu. Obratite se administratoru radi nadogradnje plana ili dodavanja dodatnih mjesta." oauth2RequestNotFound = "Zahtjev za autorizaciju nije pronađen" oauth2InvalidUserInfoResponse = "Nevažeće informacije o korisniku" oauth2invalidRequest = "Neispravan zahtjev" @@ -3846,14 +3865,17 @@ fitToWidth = "Prilagodi širini" actualSize = "Stvarna veličina" [viewer] +cannotPreviewFile = "Nije moguće pregledati datoteku" +dualPageView = "Prikaz dviju stranica" firstPage = "Prva stranica" lastPage = "Zadnja stranica" -previousPage = "Prethodna stranica" nextPage = "Sljedeća stranica" +onlyPdfSupported = "Preglednik podržava samo PDF datoteke. Čini se da je ova datoteka u drugačijem formatu." +previousPage = "Prethodna stranica" +singlePageView = "Prikaz jedne stranice" +unknownFile = "Nepoznata datoteka" zoomIn = "Povećaj" zoomOut = "Umanji" -singlePageView = "Prikaz jedne stranice" -dualPageView = "Prikaz dviju stranica" [rightRail] closeSelected = "Zatvori odabrane datoteke" @@ -3877,6 +3899,7 @@ toggleSidebar = "Prebaci bočnu traku" exportSelected = "Izvezi odabrane stranice" toggleAnnotations = "Prebaci vidljivost bilješki" annotationMode = "Prebaci način bilješki" +print = "Ispis PDF-a" draw = "Crtaj" save = "Spremi" saveChanges = "Spremi promjene" @@ -4494,6 +4517,7 @@ description = "URL ili naziv datoteke za impresum (obvezno u nekim nadležnostim title = "Premium i Enterprise" description = "Konfigurirajte svoj premium ili enterprise licencni ključ." license = "Konfiguracija licence" +noInput = "Molimo navedite licencni ključ ili datoteku" [admin.settings.premium.licenseKey] toggle = "Imate licencni ključ ili datoteku certifikata?" @@ -4511,6 +4535,25 @@ line1 = "Prepisivanje vašeg trenutačnog licencnog ključa ne može se poništi line2 = "Vaša će prethodna licenca trajno biti izgubljena osim ako je niste sigurnosno kopirali drugdje." line3 = "Važno: Licencne ključeve držite privatnima i sigurnima. Nikada ih javno ne dijelite." +[admin.settings.premium.inputMethod] +text = "Licencni ključ" +file = "Datoteka certifikata" + +[admin.settings.premium.file] +label = "Datoteka certifikata licence" +description = "Učitajte svoju .lic ili .cert licencnu datoteku iz izvanmrežnih kupnji" +choose = "Odaberite licencnu datoteku" +selected = "Odabrano: {{filename}} ({{size}})" +successMessage = "Licencna datoteka je uspješno učitana i aktivirana. Nije potrebno ponovno pokretanje." + +[admin.settings.premium.currentLicense] +title = "Aktivna licenca" +file = "Izvor: Licencna datoteka ({{path}})" +key = "Izvor: Licencni ključ" +type = "Vrsta: {{type}}" +noInput = "Navedite licencni ključ ili učitajte datoteku certifikata" +success = "Uspjeh" + [admin.settings.premium.enabled] label = "Omogući premium značajke" description = "Omogući provjere licencnog ključa za pro/enterprise značajke" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} odabrano" download = "Preuzmi datoteku" delete = "Izbriši" unsupported = "Nepodržano" +active = "Aktivno" addToUpload = "Dodaj za otpremu" +closeFile = "Zatvori datoteku" deleteAll = "Izbriši sve" loadingFiles = "Učitavanje datoteka..." noFiles = "Nema dostupnih datoteka" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Potreban je barem jedan e-mail" submit = "Pošalji pozive" success = "Korisnici su uspješno pozvani" -partialSuccess = "Neki pozivi nisu uspjeli" +partialFailure = "Neke pozivnice nisu uspjele" allFailed = "Pozivanje korisnika nije uspjelo" error = "Slanje poziva nije uspjelo" @@ -5797,6 +5842,13 @@ submit = "Prijava" signInWith = "Prijavite se pomoću" oauthPending = "Otvaranje preglednika za autentikaciju..." orContinueWith = "Ili nastavite s e-poštom" +serverRequirement = "Napomena: Poslužitelj mora imati omogućenu prijavu." +showInstructions = "Kako omogućiti?" +hideInstructions = "Sakrij upute" +instructions = "Da biste omogućili prijavu na svom Stirling PDF poslužitelju:" +instructionsEnvVar = "Postavite varijablu okruženja:" +instructionsOrYml = "Ili u settings.yml:" +instructionsRestart = "Zatim ponovno pokrenite poslužitelj kako bi promjene stupile na snagu." [setup.login.username] label = "Korisničko ime" @@ -5840,7 +5892,7 @@ paragraph = "Stranica s odlomcima" sparse = "Rijedak tekst" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automatski" paragraph = "Odlomak" singleLine = "Jedan redak" diff --git a/frontend/public/locales/hu-HU/translation.toml b/frontend/public/locales/hu-HU/translation.toml index 514db6f07..5c70e8a2e 100644 --- a/frontend/public/locales/hu-HU/translation.toml +++ b/frontend/public/locales/hu-HU/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Eltávolítás a kedvencekből" fullscreen = "Váltás teljes képernyős módra" sidebar = "Váltás oldalsáv módra" +[backendStartup] +notFoundTitle = "Backend nem található" +retry = "Próbálja újra" +unreachable = "Az alkalmazás jelenleg nem tud csatlakozni a Backendhez. Ellenőrizze a Backend állapotát és a hálózati kapcsolatot, majd próbálja újra." + [zipWarning] title = "Nagy ZIP fájl" message = "Ez a ZIP {{count}} fájlt tartalmaz. Mégis kibontja?" @@ -912,6 +917,9 @@ desc = "Többlépéses munkafolyamatok összeállítása PDF műveletek összef desc = "PDF-ek egymásra helyezése egy másik PDF-en" title = "PDF-ek egymásra helyezése" +[home.pdfTextEditor] +title = "PDF szövegszerkesztő" +desc = "Meglévő szöveg és képek szerkesztése a PDF-ekben" [home.addText] tags = "szöveg, megjegyzés, címke" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Rajzolt aláírás" defaultImageLabel = "Feltöltött aláírás" defaultTextLabel = "Gépelt aláírás" saveButton = "Aláírás mentése" +savePersonal = "Mentés személyesként" +saveShared = "Mentés megosztottként" saveUnavailable = "Előbb hozzon létre egy aláírást a mentéshez." noChanges = "Az aktuális aláírás már mentve van." +tempStorageTitle = "Ideiglenes böngészőbeli tárolás" +tempStorageDescription = "Az aláírások csak a böngészőben tárolódnak. Elvesznek, ha törli a böngészőadatokat vagy böngészőt vált." +personalHeading = "Személyes aláírások" +sharedHeading = "Megosztott aláírások" +personalDescription = "Csak Ön láthatja ezeket az aláírásokat." +sharedDescription = "Minden felhasználó láthatja és használhatja ezeket az aláírásokat." [sign.saved.type] canvas = "Rajz" @@ -3438,6 +3454,9 @@ signinTitle = "Kérjük, jelentkezzen be" ssoSignIn = "Bejelentkezés egyszeri bejelentkezéssel" oAuth2AutoCreateDisabled = "OAuth2 automatikus felhasználólétrehozás letiltva" oAuth2AdminBlockedUser = "A nem regisztrált felhasználók regisztrációja vagy bejelentkezése jelenleg le van tiltva. Kérjük, forduljon a rendszergazdához." +oAuth2RequiresLicense = "Az OAuth/SSO bejelentkezés fizetős licencet igényel (Server vagy Enterprise). Kérjük, lépjen kapcsolatba az adminisztrátorral a csomag frissítéséhez." +saml2RequiresLicense = "A SAML bejelentkezés fizetős licencet igényel (Server vagy Enterprise). Kérjük, lépjen kapcsolatba az adminisztrátorral a csomag frissítéséhez." +maxUsersReached = "Elérte az aktuális licenchez tartozó felhasználók maximális számát. Kérjük, lépjen kapcsolatba az adminisztrátorral a csomag frissítéséhez vagy további felhasználói helyek hozzáadásához." oauth2RequestNotFound = "A hitelesítési kérés nem található" oauth2InvalidUserInfoResponse = "Érvénytelen felhasználói információ válasz" oauth2invalidRequest = "Érvénytelen kérés" @@ -3846,14 +3865,17 @@ fitToWidth = "Szélességhez igazítás" actualSize = "Tényleges méret" [viewer] +cannotPreviewFile = "A fájl előnézete nem lehetséges" +dualPageView = "Kétoldalas nézet" firstPage = "Első oldal" lastPage = "Utolsó oldal" -previousPage = "Előző oldal" nextPage = "Következő oldal" +onlyPdfSupported = "A megjelenítő csak PDF fájlokat támogat. Úgy tűnik, ez a fájl más formátumú." +previousPage = "Előző oldal" +singlePageView = "Egyoldalas nézet" +unknownFile = "Ismeretlen fájl" zoomIn = "Nagyítás" zoomOut = "Kicsinyítés" -singlePageView = "Egyoldalas nézet" -dualPageView = "Kétoldalas nézet" [rightRail] closeSelected = "Kijelölt fájlok bezárása" @@ -3877,6 +3899,7 @@ toggleSidebar = "Oldalsáv ki/be" exportSelected = "Kijelölt oldalak exportálása" toggleAnnotations = "Jegyzetek láthatóságának váltása" annotationMode = "Jegyzetelési mód váltása" +print = "PDF nyomtatása" draw = "Rajzolás" save = "Mentés" saveChanges = "Változtatások mentése" @@ -4494,6 +4517,7 @@ description = "URL vagy fájlnév az impresszumhoz (egyes joghatóságokban köt title = "Prémium és Vállalati" description = "Prémium vagy vállalati licenckulcs konfigurálása." license = "Licenckonfiguráció" +noInput = "Kérjük, adjon meg egy licenckulcsot vagy fájlt" [admin.settings.premium.licenseKey] toggle = "Van licenckulcsa vagy tanúsítványfájlja?" @@ -4511,6 +4535,25 @@ line1 = "A jelenlegi licenckulcs felülírása nem vonható vissza." line2 = "A korábbi licenc végleg elveszik, hacsak nem készített róla máshol biztonsági másolatot." line3 = "Fontos: Tartsa a licenckulcsokat bizalmasan és biztonságban. Soha ne ossza meg nyilvánosan." +[admin.settings.premium.inputMethod] +text = "Licenckulcs" +file = "Tanúsítványfájl" + +[admin.settings.premium.file] +label = "Licenc tanúsítványfájl" +description = "Töltse fel az offline vásárlásból származó .lic vagy .cert licencfájlt" +choose = "Licencfájl kiválasztása" +selected = "Kiválasztva: {{filename}} ({{size}})" +successMessage = "A licencfájl feltöltése és aktiválása sikeres. Nincs szükség újraindításra." + +[admin.settings.premium.currentLicense] +title = "Aktív licenc" +file = "Forrás: licencfájl ({{path}})" +key = "Forrás: licenckulcs" +type = "Típus: {{type}}" +noInput = "Adjon meg egy licenckulcsot, vagy töltsön fel tanúsítványfájlt" +success = "Siker" + [admin.settings.premium.enabled] label = "Prémium funkciók engedélyezése" description = "Licenckulcs-ellenőrzések engedélyezése a pro/vállalati funkciókhoz" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} kiválasztva" download = "Letöltés" delete = "Törlés" unsupported = "Nem támogatott" +active = "Aktív" addToUpload = "Hozzáadás a feltöltéshez" +closeFile = "Fájl bezárása" deleteAll = "Összes törlése" loadingFiles = "Fájlok betöltése..." noFiles = "Nem állnak rendelkezésre fájlok" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Legalább egy e-mail cím megadása szükséges" submit = "Meghívók küldése" success = "felhasználó sikeresen meghívva" -partialSuccess = "Néhány meghívó sikertelen volt" +partialFailure = "Néhány meghívás sikertelen volt" allFailed = "Nem sikerült meghívni a felhasználókat" error = "Nem sikerült elküldeni a meghívókat" @@ -5797,6 +5842,13 @@ submit = "Bejelentkezés" signInWith = "Bejelentkezés ezzel" oauthPending = "Böngésző megnyitása hitelesítéshez..." orContinueWith = "Vagy folytassa e-maillel" +serverRequirement = "Megjegyzés: A szerveren engedélyezni kell a bejelentkezést." +showInstructions = "Hogyan engedélyezhető?" +hideInstructions = "Utasítások elrejtése" +instructions = "A bejelentkezés engedélyezéséhez a Stirling PDF szerverén:" +instructionsEnvVar = "Állítsa be a környezeti változót:" +instructionsOrYml = "Vagy a settings.yml-ben:" +instructionsRestart = "Ezután indítsa újra a szervert, hogy a módosítások életbe lépjenek." [setup.login.username] label = "Felhasználónév" diff --git a/frontend/public/locales/id-ID/translation.toml b/frontend/public/locales/id-ID/translation.toml index 010266296..78fff6735 100644 --- a/frontend/public/locales/id-ID/translation.toml +++ b/frontend/public/locales/id-ID/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Hapus dari Favorit" fullscreen = "Beralih ke mode layar penuh" sidebar = "Beralih ke mode bilah sisi" +[backendStartup] +notFoundTitle = "Backend tidak ditemukan" +retry = "Coba lagi" +unreachable = "Aplikasi saat ini tidak dapat terhubung ke backend. Periksa status backend dan konektivitas jaringan, lalu coba lagi." + [zipWarning] title = "File ZIP Besar" message = "ZIP ini berisi {{count}} file. Tetap ekstrak?" @@ -190,7 +195,7 @@ title = "Pengaturan Dibuka" message = "Silakan pilih Stirling PDF di pengaturan sistem Anda" [defaultApp.error] -title = "Error" +title = "Kesalahan" message = "Gagal menyetel penangan PDF default" [language] @@ -383,7 +388,7 @@ logout = "Keluar" [settings.connection.mode] saas = "Stirling Cloud" -selfhosted = "Self-Hosted" +selfhosted = "Dihost Sendiri" [settings.general] title = "Umum" @@ -544,8 +549,8 @@ usage = "Lihat Penggunaan" [endpointStatistics] title = "Statistik Endpoint" header = "Statistik Endpoint" -top10 = "Top 10" -top20 = "Top 20" +top10 = "10 Teratas" +top20 = "20 Teratas" all = "Semua" refresh = "Muat Ulang" dataTypeLabel = "Tipe Data:" @@ -912,6 +917,9 @@ desc = "Bangun alur kerja multi-langkah dengan merangkai tindakan PDF. Ideal unt desc = "Menumpuk PDF di atas PDF lain" title = "Tumpuk PDF" +[home.pdfTextEditor] +title = "Editor Teks PDF" +desc = "Edit teks dan gambar yang ada di dalam PDF" [home.addText] tags = "teks,anotasi,label" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "Pilih file di tampilan utama untuk memulai" settings = "Pengaturan" conversionCompleted = "Konversi selesai" results = "Hasil" -defaultFilename = "converted_file" +defaultFilename = "file_terkonversi" conversionResults = "Hasil Konversi" convertFrom = "Konversi dari" convertTo = "Konversi ke" @@ -1360,7 +1368,7 @@ title = "Tambahkan Watermark" desc = "Tambahkan tanda air teks atau gambar ke file PDF" completed = "Tanda air ditambahkan" submit = "Tambahkan Watermark" -filenamePrefix = "watermarked" +filenamePrefix = "bertanda_air" [watermark.error] failed = "Terjadi kesalahan saat menambahkan tanda air ke PDF." @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Tanda tangan gambar" defaultImageLabel = "Tanda tangan terunggah" defaultTextLabel = "Tanda tangan ketik" saveButton = "Simpan tanda tangan" +savePersonal = "Simpan Pribadi" +saveShared = "Simpan Bersama" saveUnavailable = "Buat tanda tangan terlebih dahulu untuk menyimpannya." noChanges = "Tanda tangan saat ini sudah disimpan." +tempStorageTitle = "Penyimpanan browser sementara" +tempStorageDescription = "Tanda tangan disimpan hanya di browser Anda. Data akan hilang jika Anda membersihkan data browser atau berpindah browser." +personalHeading = "Tanda Tangan Pribadi" +sharedHeading = "Tanda Tangan Bersama" +personalDescription = "Hanya Anda yang dapat melihat tanda tangan ini." +sharedDescription = "Semua pengguna dapat melihat dan menggunakan tanda tangan ini." [sign.saved.type] canvas = "Gambar" @@ -2701,7 +2717,7 @@ header = "Hapus sertifikat digital dari PDF" selectPDF = "Pilih file PDF:" submit = "Hapus Tanda Tangan" description = "Alat ini akan menghapus tanda tangan sertifikat digital dari dokumen PDF Anda." -filenamePrefix = "unsigned" +filenamePrefix = "tanpa_tanda_tangan" [removeCertSign.files] placeholder = "Pilih file PDF di tampilan utama untuk memulai" @@ -3438,6 +3454,9 @@ signinTitle = "Silakan masuk" ssoSignIn = "Masuk melalui Single Sign - on" oAuth2AutoCreateDisabled = "OAUTH2 Buat Otomatis Pengguna Dinonaktifkan" oAuth2AdminBlockedUser = "Registrasi atau login pengguna yang tidak terdaftar saat ini diblokir. Silakan hubungi administrator." +oAuth2RequiresLicense = "Login OAuth/SSO memerlukan lisensi berbayar (Server atau Enterprise). Silakan hubungi administrator untuk meningkatkan paket Anda." +saml2RequiresLicense = "Login SAML memerlukan lisensi berbayar (Server atau Enterprise). Silakan hubungi administrator untuk meningkatkan paket Anda." +maxUsersReached = "Jumlah pengguna maksimum untuk lisensi Anda saat ini telah tercapai. Silakan hubungi administrator untuk meningkatkan paket Anda atau menambah seat." oauth2RequestNotFound = "Permintaan otorisasi tidak ditemukan" oauth2InvalidUserInfoResponse = "Respons Info Pengguna Tidak Valid" oauth2invalidRequest = "Permintaan Tidak Valid" @@ -3533,7 +3552,7 @@ title = "PDF Ke Halaman Tunggal" header = "PDF Ke Halaman Tunggal" submit = "Konversi ke Halaman Tunggal" description = "Alat ini akan menggabungkan semua halaman PDF Anda menjadi satu halaman besar. Lebarnya akan tetap sama dengan halaman asli, tetapi tingginya merupakan penjumlahan dari semua tinggi halaman." -filenamePrefix = "single_page" +filenamePrefix = "halaman_tunggal" [pdfToSinglePage.files] placeholder = "Pilih file PDF di tampilan utama untuk memulai" @@ -3846,14 +3865,17 @@ fitToWidth = "Sesuaikan ke Lebar" actualSize = "Ukuran Asli" [viewer] +cannotPreviewFile = "Tidak dapat menampilkan pratinjau file" +dualPageView = "Tampilan Dua Halaman" firstPage = "Halaman Pertama" lastPage = "Halaman Terakhir" -previousPage = "Halaman Sebelumnya" nextPage = "Halaman Berikutnya" +onlyPdfSupported = "Penampil hanya mendukung file PDF. File ini tampaknya memiliki format yang berbeda." +previousPage = "Halaman Sebelumnya" +singlePageView = "Tampilan Satu Halaman" +unknownFile = "File tidak dikenal" zoomIn = "Perbesar" zoomOut = "Perkecil" -singlePageView = "Tampilan Satu Halaman" -dualPageView = "Tampilan Dua Halaman" [rightRail] closeSelected = "Tutup File Terpilih" @@ -3877,6 +3899,7 @@ toggleSidebar = "Alihkan Sidebar" exportSelected = "Ekspor Halaman Terpilih" toggleAnnotations = "Alihkan Visibilitas Anotasi" annotationMode = "Alihkan Mode Anotasi" +print = "Cetak PDF" draw = "Gambar" save = "Simpan" saveChanges = "Simpan Perubahan" @@ -4494,6 +4517,7 @@ description = "URL atau nama file untuk impressum (diperlukan di beberapa yurisd title = "Premium & Enterprise" description = "Konfigurasikan kunci lisensi premium atau enterprise Anda." license = "Konfigurasi Lisensi" +noInput = "Harap berikan kunci atau file lisensi" [admin.settings.premium.licenseKey] toggle = "Punya kunci lisensi atau file sertifikat?" @@ -4511,6 +4535,25 @@ line1 = "Menimpa kunci lisensi Anda saat ini tidak dapat dibatalkan." line2 = "Lisensi sebelumnya akan hilang permanen kecuali Anda mencadangkannya di tempat lain." line3 = "Penting: Jaga kunci lisensi tetap privat dan aman. Jangan pernah membagikannya secara publik." +[admin.settings.premium.inputMethod] +text = "Kunci Lisensi" +file = "File Sertifikat" + +[admin.settings.premium.file] +label = "File Sertifikat Lisensi" +description = "Unggah file lisensi .lic atau .cert Anda dari pembelian offline" +choose = "Pilih File Lisensi" +selected = "Dipilih: {{filename}} ({{size}})" +successMessage = "File lisensi berhasil diunggah dan diaktifkan. Tidak perlu restart." + +[admin.settings.premium.currentLicense] +title = "Lisensi Aktif" +file = "Sumber: File lisensi ({{path}})" +key = "Sumber: Kunci lisensi" +type = "Tipe: {{type}}" +noInput = "Harap berikan kunci lisensi atau unggah file sertifikat" +success = "Berhasil" + [admin.settings.premium.enabled] label = "Aktifkan Fitur Premium" description = "Aktifkan pemeriksaan kunci lisensi untuk fitur pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} dipilih" download = "Unduh" delete = "Hapus" unsupported = "Tidak didukung" +active = "Aktif" addToUpload = "Tambahkan ke Unggahan" +closeFile = "Tutup File" deleteAll = "Hapus Semua" loadingFiles = "Memuat file..." noFiles = "Tidak ada file tersedia" @@ -4938,13 +4983,13 @@ done = "Selesai" loading = "Memuat..." back = "Kembali" continue = "Lanjut" -error = "Error" +error = "Kesalahan" [config.overview] title = "Konfigurasi Aplikasi" description = "Pengaturan dan detail konfigurasi aplikasi saat ini." loading = "Memuat konfigurasi..." -error = "Error" +error = "Kesalahan" warning = "Peringatan Konfigurasi" [config.overview.sections] @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Setidaknya satu alamat email diperlukan" submit = "Kirim Undangan" success = "pengguna berhasil diundang" -partialSuccess = "Beberapa undangan gagal" +partialFailure = "Beberapa undangan gagal" allFailed = "Gagal mengundang pengguna" error = "Gagal mengirim undangan" @@ -5752,7 +5797,7 @@ label = "Pilih Server" description = "Server self-hosted" [setup.step3] -label = "Login" +label = "Masuk" description = "Masukkan kredensial" [setup.mode.saas] @@ -5793,10 +5838,17 @@ testFailed = "Tes koneksi gagal" title = "Masuk" subtitle = "Masukkan kredensial Anda untuk melanjutkan" connectingTo = "Menghubungkan ke:" -submit = "Login" +submit = "Masuk" signInWith = "Masuk dengan" oauthPending = "Membuka browser untuk autentikasi..." orContinueWith = "Atau lanjut dengan email" +serverRequirement = "Catatan: Server harus mengaktifkan login." +showInstructions = "Bagaimana cara mengaktifkannya?" +hideInstructions = "Sembunyikan instruksi" +instructions = "Untuk mengaktifkan login pada server Stirling PDF Anda:" +instructionsEnvVar = "Setel variabel lingkungan:" +instructionsOrYml = "Atau di settings.yml:" +instructionsRestart = "Kemudian mulai ulang server Anda agar perubahan diterapkan." [setup.login.username] label = "Nama pengguna" diff --git a/frontend/public/locales/it-IT/translation.toml b/frontend/public/locales/it-IT/translation.toml index ef9d94d83..806cfa571 100644 --- a/frontend/public/locales/it-IT/translation.toml +++ b/frontend/public/locales/it-IT/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Rimuovi dai preferiti" fullscreen = "Passa alla modalità a schermo intero" sidebar = "Passa alla modalità barra laterale" +[backendStartup] +notFoundTitle = "Backend non trovato" +retry = "Riprova" +unreachable = "L'applicazione al momento non riesce a connettersi al backend. Verificare lo stato del backend e la connettività di rete, quindi riprovare." + [zipWarning] title = "File ZIP di grandi dimensioni" message = "Questo ZIP contiene {{count}} file. Estrarre comunque?" @@ -339,7 +344,7 @@ popular = "Popolare" title = "Preferenze" [settings.workspace] -title = "Workspace" +title = "Area di lavoro" people = "Persone" teams = "Team" @@ -912,6 +917,9 @@ desc = "Crea flussi multi‑step concatenando azioni PDF. Ideale per attività r desc = "Sovrapponi un PDF sopra un altro" title = "Sovrapponi PDF" +[home.pdfTextEditor] +title = "Editor di testo PDF" +desc = "Modifica testo e immagini esistenti nei PDF" [home.addText] tags = "testo,annotazione,etichetta" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Firma disegnata" defaultImageLabel = "Firma caricata" defaultTextLabel = "Firma digitata" saveButton = "Salva firma" +savePersonal = "Salva come personale" +saveShared = "Salva come condivisa" saveUnavailable = "Crea prima una firma per salvarla." noChanges = "La firma corrente è già salvata." +tempStorageTitle = "Archiviazione temporanea del browser" +tempStorageDescription = "Le firme sono archiviate solo nel tuo browser. Verranno perse se cancelli i dati del browser o cambi browser." +personalHeading = "Firme personali" +sharedHeading = "Firme condivise" +personalDescription = "Solo tu puoi vedere queste firme." +sharedDescription = "Tutti gli utenti possono vedere e usare queste firme." [sign.saved.type] canvas = "Disegno" @@ -2841,8 +2857,8 @@ label = "Fattore di scala" [adjustPageScale.pageSize] label = "Dimensione pagina di destinazione" keep = "Mantieni dimensioni originali" -letter = "Letter" -legal = "Legal" +letter = "Lettera" +legal = "Legale" [adjustPageScale.error] failed = "Si è verificato un errore durante la regolazione della scala della pagina." @@ -3438,6 +3454,9 @@ signinTitle = "Per favore accedi" ssoSignIn = "Accedi tramite Single Sign-on" oAuth2AutoCreateDisabled = "Creazione automatica utente OAUTH2 DISABILITATA" oAuth2AdminBlockedUser = "La registrazione o l'accesso degli utenti non registrati è attualmente bloccata. Si prega di contattare l'amministratore." +oAuth2RequiresLicense = "L'accesso OAuth/SSO richiede una licenza a pagamento (Server o Enterprise). Contatta l'amministratore per aggiornare il tuo piano." +saml2RequiresLicense = "L'accesso SAML richiede una licenza a pagamento (Server o Enterprise). Contatta l'amministratore per aggiornare il tuo piano." +maxUsersReached = "Numero massimo di utenti raggiunto per la licenza corrente. Contatta l'amministratore per aggiornare il piano o aggiungere altri posti." oauth2RequestNotFound = "Richiesta di autorizzazione non trovata" oauth2InvalidUserInfoResponse = "Risposta relativa alle informazioni utente non valida" oauth2invalidRequest = "Richiesta non valida" @@ -3846,14 +3865,17 @@ fitToWidth = "Adatta alla larghezza" actualSize = "Dimensione reale" [viewer] +cannotPreviewFile = "Impossibile visualizzare l'anteprima del file" +dualPageView = "Vista doppia pagina" firstPage = "Prima pagina" lastPage = "Ultima pagina" -previousPage = "Pagina precedente" nextPage = "Pagina successiva" +onlyPdfSupported = "Il visualizzatore supporta solo file PDF. Questo file sembra essere in un formato diverso." +previousPage = "Pagina precedente" +singlePageView = "Vista pagina singola" +unknownFile = "File sconosciuto" zoomIn = "Ingrandisci" zoomOut = "Riduci" -singlePageView = "Vista pagina singola" -dualPageView = "Vista doppia pagina" [rightRail] closeSelected = "Chiudi file selezionati" @@ -3877,6 +3899,7 @@ toggleSidebar = "Mostra/Nascondi barra laterale" exportSelected = "Esporta pagine selezionate" toggleAnnotations = "Attiva/disattiva visibilità annotazioni" annotationMode = "Attiva/disattiva modalità annotazione" +print = "Stampa PDF" draw = "Disegna" save = "Salva" saveChanges = "Salva modifiche" @@ -3925,7 +3948,7 @@ files = "File" activity = "Attività" help = "Guida" account = "Account" -config = "Config" +config = "Configurazione" settings = "Opzioni" adminSettings = "Opzioni Admin" allTools = "Funzioni" @@ -4487,13 +4510,14 @@ label = "Informativa sui cookie" description = "URL o nome file della cookie policy" [admin.settings.legal.impressum] -label = "Impressum" +label = "Note legali" description = "URL o nome file dell'Impressum (richiesto in alcune giurisdizioni)" [admin.settings.premium] title = "Premium e Enterprise" description = "Configura la tua chiave di licenza premium o enterprise." license = "Configurazione licenza" +noInput = "Fornisci una chiave o un file di licenza" [admin.settings.premium.licenseKey] toggle = "Hai una chiave di licenza o un file di certificato?" @@ -4511,6 +4535,25 @@ line1 = "La sovrascrittura della licenza attuale non può essere annullata." line2 = "La tua licenza precedente andrà persa in modo permanente a meno che tu non l'abbia salvata altrove." line3 = "Importante: mantieni le chiavi di licenza private e sicure. Non condividerle mai pubblicamente." +[admin.settings.premium.inputMethod] +text = "Chiave di licenza" +file = "File del certificato" + +[admin.settings.premium.file] +label = "File del certificato di licenza" +description = "Carica il file di licenza .lic o .cert degli acquisti offline" +choose = "Scegli file di licenza" +selected = "Selezionato: {{filename}} ({{size}})" +successMessage = "File di licenza caricato e attivato con successo. Non è richiesto il riavvio." + +[admin.settings.premium.currentLicense] +title = "Licenza attiva" +file = "Origine: File di licenza ({{path}})" +key = "Origine: Chiave di licenza" +type = "Tipo: {{type}}" +noInput = "Fornisci una chiave di licenza o carica un file di certificato" +success = "Successo" + [admin.settings.premium.enabled] label = "Abilita funzionalità Premium" description = "Abilita i controlli della chiave di licenza per funzionalità pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} selezionati" download = "Salva" delete = "Elimina" unsupported = "Non supportato" +active = "Attivo" addToUpload = "Aggiungi al caricamento" +closeFile = "Chiudi file" deleteAll = "Elimina tutto" loadingFiles = "Caricamento file..." noFiles = "Nessun file disponibile" @@ -5194,7 +5239,7 @@ subtitle = "Digita o incolla le email qui sotto, separate da virgole. La tua are [workspace.people.actions] label = "Azioni" -upgrade = "Upgrade" +upgrade = "Aggiorna" [workspace.people.roleDescriptions] admin = "Può gestire impostazioni e invitare membri, con pieno accesso amministrativo." @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "È richiesto almeno un indirizzo email" submit = "Invia inviti" success = "utente/i invitato/i con successo" -partialSuccess = "Alcuni inviti non sono riusciti" +partialFailure = "Alcuni inviti non sono riusciti" allFailed = "Impossibile invitare gli utenti" error = "Invio inviti non riuscito" @@ -5752,7 +5797,7 @@ label = "Seleziona server" description = "Server self-hosted" [setup.step3] -label = "Login" +label = "Accesso" description = "Inserisci credenziali" [setup.mode.saas] @@ -5793,10 +5838,17 @@ testFailed = "Test di connessione non riuscito" title = "Accedi" subtitle = "Inserisci le credenziali per continuare" connectingTo = "Connessione a:" -submit = "Login" +submit = "Accedi" signInWith = "Accedi con" oauthPending = "Apertura del browser per l'autenticazione..." orContinueWith = "Oppure continua con email" +serverRequirement = "Nota: il server deve avere il login abilitato." +showInstructions = "Come abilitarlo?" +hideInstructions = "Nascondi istruzioni" +instructions = "Per abilitare il login sul tuo server Stirling PDF:" +instructionsEnvVar = "Imposta la variabile d'ambiente:" +instructionsOrYml = "Oppure in settings.yml:" +instructionsRestart = "Quindi riavvia il server affinché le modifiche abbiano effetto." [setup.login.username] label = "Nome utente" @@ -5840,7 +5892,7 @@ paragraph = "Pagina a paragrafi" sparse = "Testo sparso" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automatico" paragraph = "Paragrafo" singleLine = "Riga singola" diff --git a/frontend/public/locales/ja-JP/translation.toml b/frontend/public/locales/ja-JP/translation.toml index 90b5eeee4..bceb6975f 100644 --- a/frontend/public/locales/ja-JP/translation.toml +++ b/frontend/public/locales/ja-JP/translation.toml @@ -163,6 +163,11 @@ unfavorite = "お気に入りから削除" fullscreen = "フルスクリーンモードに切り替え" sidebar = "サイドバーモードに切り替え" +[backendStartup] +notFoundTitle = "バックエンドが見つかりません" +retry = "再試行" +unreachable = "現在、アプリケーションはバックエンドに接続できません。バックエンドの稼働状況とネットワーク接続を確認し、再度お試しください。" + [zipWarning] title = "大きな ZIP ファイル" message = "このZIPには{{count}}個のファイルが含まれています。展開しますか?" @@ -912,6 +917,9 @@ desc = "PDF アクションを連結して複数ステップのワークフロ desc = "1つのPDFを別のPDFの上に重ねます" title = "PDFを重ね合わせ" +[home.pdfTextEditor] +title = "PDFテキストエディタ" +desc = "PDF内の既存のテキストと画像を編集" [home.addText] tags = "テキスト,注釈,ラベル" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "開始するにはメインビューでファイルを settings = "設定" conversionCompleted = "変換が完了しました" results = "結果" -defaultFilename = "converted_file" +defaultFilename = "変換済みファイル" conversionResults = "変換結果" convertFrom = "変換元" convertTo = "変換先" @@ -1360,7 +1368,7 @@ title = "透かしの追加" desc = "PDF ファイルにテキストまたは画像の透かしを追加" completed = "透かしを追加しました" submit = "透かしを追加" -filenamePrefix = "watermarked" +filenamePrefix = "透かし入り" [watermark.error] failed = "PDF への透かし追加中にエラーが発生しました。" @@ -1635,7 +1643,7 @@ subtitle = "処理済みファイルをダウンロードするか、下で操 [removePages] tags = "ページを削除,ページ削除" title = "削除" -filenamePrefix = "pages_removed" +filenamePrefix = "ページ削除済み" submit = "削除" [removePages.pageNumbers] @@ -1837,7 +1845,7 @@ title = "フォームフィールドから読み取り専用を削除" header = "PDFフォームのロックを解除" submit = "Remove" description = "このツールは PDF フォームフィールドの読み取り専用制限を解除し、編集・入力可能にします。" -filenamePrefix = "unlocked_forms" +filenamePrefix = "フォームのロック解除済み" [unlockPDFForms.files] placeholder = "メインビューで PDF ファイルを選択して開始してください" @@ -1851,7 +1859,7 @@ title = "フォームのロック解除結果" [changeMetadata] header = "メタデータの変更" submit = "変更" -filenamePrefix = "metadata" +filenamePrefix = "メタデータ" [changeMetadata.settings] title = "メタデータ設定" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "手書き署名" defaultImageLabel = "アップロードした署名" defaultTextLabel = "入力した署名" saveButton = "署名を保存" +savePersonal = "個人用として保存" +saveShared = "共有用として保存" saveUnavailable = "まず署名を作成してから保存してください。" noChanges = "現在の署名はすでに保存済みです。" +tempStorageTitle = "ブラウザーの一時ストレージ" +tempStorageDescription = "署名はブラウザー内のみに保存されます。ブラウザーのデータを消去するか、別のブラウザーに切り替えると失われます。" +personalHeading = "個人用署名" +sharedHeading = "共有署名" +personalDescription = "これらの署名はあなただけが表示できます。" +sharedDescription = "すべてのユーザーがこれらの署名を表示して使用できます。" [sign.saved.type] canvas = "描画" @@ -2318,7 +2334,7 @@ title = "平坦化" header = "PDFを平坦化する" flattenOnlyForms = "フォームのみを平坦にする" submit = "平坦化" -filenamePrefix = "flattened" +filenamePrefix = "フラット化済み" [flatten.files] placeholder = "開始するにはメインビューで PDF ファイルを選択してください" @@ -2366,7 +2382,7 @@ title = "修復" header = "PDFを修復" submit = "修復" description = "このツールは破損または損傷した PDF ファイルの修復を試みます。追加の設定は不要です。" -filenamePrefix = "repaired" +filenamePrefix = "修復済み" [repair.files] placeholder = "開始するにはメイン画面で PDF ファイルを選択してください" @@ -2567,7 +2583,7 @@ stopButton = "比較を停止" [certSign] tags = "authenticate,PEM,P12,official,encrypt" title = "証明書による署名" -filenamePrefix = "signed" +filenamePrefix = "署名済み" chooseCertificate = "証明書ファイルを選択" chooseJksFile = "JKS ファイルを選択" chooseP12File = "PKCS12 ファイルを選択" @@ -2701,7 +2717,7 @@ header = "PDFから電子証明書を削除する" selectPDF = "PDFファイルの選択:" submit = "署名の削除" description = "このツールは PDF 文書からデジタル証明書署名を削除します。" -filenamePrefix = "unsigned" +filenamePrefix = "署名なし" [removeCertSign.files] placeholder = "開始するにはメイン画面で PDF ファイルを選択してください" @@ -3438,6 +3454,9 @@ signinTitle = "サインインしてください" ssoSignIn = "シングルサインオンでログイン" oAuth2AutoCreateDisabled = "OAuth 2自動作成ユーザーが無効" oAuth2AdminBlockedUser = "現在、未登録ユーザーの登録またはログインはブロックされています。管理者にお問い合わせください。" +oAuth2RequiresLicense = "OAuth/SSO ログインには有料ライセンス(Server または Enterprise)が必要です。プランのアップグレードについては管理者にお問い合わせください。" +saml2RequiresLicense = "SAML ログインには有料ライセンス(Server または Enterprise)が必要です。プランのアップグレードについては管理者にお問い合わせください。" +maxUsersReached = "現在のライセンスのユーザー数上限に達しました。プランのアップグレードまたはシート数の追加について、管理者にお問い合わせください。" oauth2RequestNotFound = "認証リクエストが見つかりません" oauth2InvalidUserInfoResponse = "無効なユーザー情報の応答" oauth2invalidRequest = "無効なリクエスト" @@ -3533,7 +3552,7 @@ title = "PDFを単一ページに変換" header = "PDFを単一ページに変換" submit = "単一ページに変換" description = "このツールは PDF の全ページを 1 つの大きな単一ページに結合します。幅は元のページと同じで、高さは全ページの高さの合計になります。" -filenamePrefix = "single_page" +filenamePrefix = "単一ページ" [pdfToSinglePage.files] placeholder = "開始するにはメイン画面で PDF ファイルを選択してください" @@ -3846,14 +3865,17 @@ fitToWidth = "幅に合わせる" actualSize = "原寸" [viewer] +cannotPreviewFile = "ファイルをプレビューできません" +dualPageView = "見開き表示" firstPage = "最初のページ" lastPage = "最後のページ" -previousPage = "前のページ" nextPage = "次のページ" +onlyPdfSupported = "このビューアは PDF ファイルのみをサポートしています。このファイルは別の形式のようです。" +previousPage = "前のページ" +singlePageView = "単一ページ表示" +unknownFile = "不明なファイル" zoomIn = "拡大" zoomOut = "縮小" -singlePageView = "単一ページ表示" -dualPageView = "見開き表示" [rightRail] closeSelected = "選択したファイルを閉じる" @@ -3877,6 +3899,7 @@ toggleSidebar = "サイドバーを切り替え" exportSelected = "選択したページを書き出し" toggleAnnotations = "注釈の表示を切り替え" annotationMode = "注釈モードを切り替え" +print = "PDFを印刷" draw = "描画" save = "保存" saveChanges = "変更を保存" @@ -4231,15 +4254,15 @@ label = "プロバイダ" description = "認証に使用する OAuth2 プロバイダ" [admin.settings.connections.oauth2.issuer] -label = "Issuer URL" +label = "発行者 URL" description = "OAuth2 プロバイダの Issuer URL" [admin.settings.connections.oauth2.clientId] -label = "Client ID" +label = "クライアント ID" description = "プロバイダから発行された OAuth2 の Client ID" [admin.settings.connections.oauth2.clientSecret] -label = "Client Secret" +label = "クライアント シークレット" description = "プロバイダから発行された OAuth2 の Client Secret" [admin.settings.connections.oauth2.useAsUsername] @@ -4270,7 +4293,7 @@ label = "プロバイダ" description = "SAML2 プロバイダ名" [admin.settings.connections.saml2.registrationId] -label = "Registration ID" +label = "登録 ID" description = "SAML2 の登録識別子" [admin.settings.connections.saml2.autoCreateUser] @@ -4407,7 +4430,7 @@ description = "より広範なシステム一時ディレクトリをクリー label = "プロセス実行制限" description = "各プロセス実行器のセッション上限とタイムアウトを設定" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDF を HTML に" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4494,6 +4517,7 @@ description = "インプリントへの URL またはファイル名(地域に title = "プレミアムとエンタープライズ" description = "プレミアムまたはエンタープライズのライセンスキーを構成します。" license = "ライセンス設定" +noInput = "ライセンスキーまたはファイルを入力してください" [admin.settings.premium.licenseKey] toggle = "ライセンスキーまたは証明書ファイルをお持ちですか?" @@ -4511,6 +4535,25 @@ line1 = "現在のライセンスキーを上書きすると元に戻せませ line2 = "別途バックアップしていない限り、以前のライセンスは永久に失われます。" line3 = "重要: ライセンスキーは秘密に安全に保管してください。公開で共有しないでください。" +[admin.settings.premium.inputMethod] +text = "ライセンスキー" +file = "証明書ファイル" + +[admin.settings.premium.file] +label = "ライセンス証明書ファイル" +description = "オフライン購入の .lic または .cert ライセンスファイルをアップロードしてください" +choose = "ライセンスファイルを選択" +selected = "選択済み: {{filename}} ({{size}})" +successMessage = "ライセンスファイルをアップロードして有効化しました。再起動は不要です。" + +[admin.settings.premium.currentLicense] +title = "有効なライセンス" +file = "ソース: ライセンスファイル ({{path}})" +key = "ソース: ライセンスキー" +type = "種類: {{type}}" +noInput = "ライセンスキーを入力するか、証明書ファイルをアップロードしてください" +success = "成功" + [admin.settings.premium.enabled] label = "プレミアム機能を有効化" description = "Pro/Enterprise 機能のライセンスキー検証を有効化" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} 件選択" download = "ダウンロード" delete = "削除" unsupported = "未対応" +active = "アクティブ" addToUpload = "アップロードに追加" +closeFile = "ファイルを閉じる" deleteAll = "すべて削除" loadingFiles = "ファイルを読み込み中..." noFiles = "ファイルはありません" @@ -4669,7 +4714,7 @@ title = "サニタイズ" desc = "PDF ファイルから潜在的に有害な要素を削除します。" submit = "PDFをサニタイズ" completed = "サニタイズが正常に完了しました" -filenamePrefix = "sanitised" +filenamePrefix = "サニタイズ済み" sanitizationResults = "サニタイズ結果" [sanitize.error] @@ -4717,7 +4762,7 @@ title = "パスワードの追加" desc = "パスワードで PDF 文書を暗号化します。" completed = "パスワード保護を適用しました" submit = "暗号化" -filenamePrefix = "encrypted" +filenamePrefix = "暗号化済み" [addPassword.error] failed = "PDF の暗号化中にエラーが発生しました。" @@ -4812,7 +4857,7 @@ text = "これらの権限を変更不可にするには、パスワード追加 title = "パスワードの削除" desc = "PDFからパスワードの削除します。" tags = "セキュア,復号,セキュリティ,パスワード解除,パスワード削除" -filenamePrefix = "decrypted" +filenamePrefix = "復号済み" submit = "削除" [removePassword.password] @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "少なくとも1件のメールアドレスが必要です" submit = "招待を送信" success = "ユーザーを招待しました" -partialSuccess = "一部の招待に失敗しました" +partialFailure = "一部の招待に失敗しました" allFailed = "ユーザーの招待に失敗しました" error = "招待の送信に失敗しました" @@ -5797,13 +5842,20 @@ submit = "ログイン" signInWith = "でサインイン" oauthPending = "認証のためブラウザーを開いています..." orContinueWith = "またはメールで続行" +serverRequirement = "注: サーバーでログインを有効にする必要があります。" +showInstructions = "有効化するには?" +hideInstructions = "手順を非表示" +instructions = "Stirling PDF サーバーでログインを有効にするには:" +instructionsEnvVar = "環境変数を設定:" +instructionsOrYml = "または settings.yml で:" +instructionsRestart = "その後、サーバーを再起動して変更を反映させてください。" [setup.login.username] label = "ユーザー名" placeholder = "ユーザー名を入力" [setup.login.email] -label = "Email" +label = "メールアドレス" placeholder = "メールアドレスを入力" [setup.login.password] diff --git a/frontend/public/locales/ko-KR/translation.toml b/frontend/public/locales/ko-KR/translation.toml index f63fd82c6..3dcd0c237 100644 --- a/frontend/public/locales/ko-KR/translation.toml +++ b/frontend/public/locales/ko-KR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "즐겨찾기에서 제거" fullscreen = "전체 화면 모드로 전환" sidebar = "사이드바 모드로 전환" +[backendStartup] +notFoundTitle = "백엔드를 찾을 수 없음" +retry = "재시도" +unreachable = "현재 애플리케이션이 백엔드에 연결할 수 없습니다. 백엔드 상태와 네트워크 연결을 확인한 후 다시 시도하세요." + [zipWarning] title = "큰 ZIP 파일" message = "이 ZIP에는 {{count}}개의 파일이 포함되어 있습니다. 그래도 압축을 해제하시겠습니까?" @@ -912,6 +917,9 @@ desc = "PDF 작업을 연결하여 다단계 워크플로를 구성하세요. desc = "PDF를 다른 PDF 위에 오버레이" title = "PDF 오버레이" +[home.pdfTextEditor] +title = "PDF 텍스트 편집기" +desc = "PDF 내부의 기존 텍스트와 이미지를 편집합니다" [home.addText] tags = "텍스트,주석,레이블" @@ -1901,8 +1909,8 @@ placeholder = "수정 날짜" [changeMetadata.trapped] label = "트래핑 상태" unknown = "알 수 없음" -true = "True" -false = "False" +true = "참" +false = "거짓" [changeMetadata.advanced] title = "고급 옵션" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "그린 서명" defaultImageLabel = "업로드된 서명" defaultTextLabel = "입력한 서명" saveButton = "서명 저장" +savePersonal = "개인용으로 저장" +saveShared = "공유용으로 저장" saveUnavailable = "먼저 서명을 만든 후 저장하세요." noChanges = "현재 서명이 이미 저장되어 있습니다." +tempStorageTitle = "임시 브라우저 저장소" +tempStorageDescription = "서명은 브라우저에만 저장됩니다. 브라우저 데이터를 삭제하거나 브라우저를 변경하면 사라집니다." +personalHeading = "개인 서명" +sharedHeading = "공유 서명" +personalDescription = "이 서명은 본인만 볼 수 있습니다." +sharedDescription = "모든 사용자가 이 서명을 보고 사용할 수 있습니다." [sign.saved.type] canvas = "그리기" @@ -3438,6 +3454,9 @@ signinTitle = "로그인해 주세요" ssoSignIn = "단일 로그인으로 로그인" oAuth2AutoCreateDisabled = "OAuth2 사용자 자동 생성이 비활성화되었습니다" oAuth2AdminBlockedUser = "현재 미등록 사용자의 등록 또는 로그인이 차단되어 있습니다. 관리자에게 문의하세요." +oAuth2RequiresLicense = "OAuth/SSO 로그인은 유료 라이선스(서버 또는 엔터프라이즈)가 필요합니다. 플랜 업그레이드를 위해 관리자에게 문의하세요." +saml2RequiresLicense = "SAML 로그인은 유료 라이선스(서버 또는 엔터프라이즈)가 필요합니다. 플랜 업그레이드를 위해 관리자에게 문의하세요." +maxUsersReached = "현재 라이선스에서 허용된 최대 사용자 수에 도달했습니다. 플랜 업그레이드 또는 시트 추가를 위해 관리자에게 문의하세요." oauth2RequestNotFound = "인증 요청을 찾을 수 없습니다" oauth2InvalidUserInfoResponse = "잘못된 사용자 정보 응답" oauth2invalidRequest = "잘못된 요청" @@ -3846,14 +3865,17 @@ fitToWidth = "너비에 맞추기" actualSize = "실제 크기" [viewer] +cannotPreviewFile = "파일을 미리보기할 수 없습니다" +dualPageView = "두 페이지 보기" firstPage = "첫 페이지" lastPage = "마지막 페이지" -previousPage = "이전 페이지" nextPage = "다음 페이지" +onlyPdfSupported = "뷰어는 PDF 파일만 지원합니다. 이 파일은 다른 형식인 것으로 보입니다." +previousPage = "이전 페이지" +singlePageView = "단일 페이지 보기" +unknownFile = "알 수 없는 파일" zoomIn = "확대" zoomOut = "축소" -singlePageView = "단일 페이지 보기" -dualPageView = "두 페이지 보기" [rightRail] closeSelected = "선택한 파일 닫기" @@ -3877,6 +3899,7 @@ toggleSidebar = "사이드바 전환" exportSelected = "선택한 페이지 내보내기" toggleAnnotations = "주석 가시성 전환" annotationMode = "주석 모드 전환" +print = "PDF 인쇄" draw = "그리기" save = "저장" saveChanges = "변경 내용 저장" @@ -4153,7 +4176,7 @@ description = "컴플라이언스 및 보안 모니터링을 위해 사용자 [admin.settings.security.audit.level] label = "감사 수준" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=끄기, 1=기본, 2=표준, 3=상세" [admin.settings.security.audit.retentionDays] label = "감사 로그 보존 기간(일)" @@ -4407,7 +4430,7 @@ description = "더 넓은 시스템 임시 디렉터리를 정리할지 여부( label = "프로세스 실행기 제한" description = "각 프로세스 실행기의 세션 제한 및 시간 제한을 구성합니다" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDF를 HTML로" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4487,13 +4510,14 @@ label = "쿠키 정책" description = "쿠키 정책의 URL 또는 파일 이름" [admin.settings.legal.impressum] -label = "Impressum" +label = "법적 고지" description = "Impressum의 URL 또는 파일 이름(일부 관할권에서 필수)" [admin.settings.premium] title = "프리미엄 및 엔터프라이즈" description = "프리미엄 또는 엔터프라이즈 라이선스 키를 구성합니다." license = "라이선스 구성" +noInput = "라이선스 키 또는 파일을 입력해 주세요" [admin.settings.premium.licenseKey] toggle = "라이선스 키나 인증서 파일이 있나요?" @@ -4511,6 +4535,25 @@ line1 = "현재 라이선스 키를 덮어쓰면 되돌릴 수 없습니다." line2 = "다른 곳에 백업하지 않았다면 이전 라이선스는 영구적으로 손실됩니다." line3 = "중요: 라이선스 키는 개인적으로 안전하게 보관하세요. 공개적으로 공유하지 마세요." +[admin.settings.premium.inputMethod] +text = "라이선스 키" +file = "인증서 파일" + +[admin.settings.premium.file] +label = "라이선스 인증서 파일" +description = "오프라인 구매 시 받은 .lic 또는 .cert 라이선스 파일을 업로드하세요" +choose = "라이선스 파일 선택" +selected = "선택됨: {{filename}} ({{size}})" +successMessage = "라이선스 파일이 업로드되어 성공적으로 활성화되었습니다. 재시작은 필요하지 않습니다." + +[admin.settings.premium.currentLicense] +title = "활성 라이선스" +file = "소스: 라이선스 파일 ({{path}})" +key = "소스: 라이선스 키" +type = "유형: {{type}}" +noInput = "라이선스 키를 입력하거나 인증서 파일을 업로드해 주세요" +success = "성공" + [admin.settings.premium.enabled] label = "프리미엄 기능 활성화" description = "프로/엔터프라이즈 기능에 대한 라이선스 키 확인 활성화" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}}개 선택됨" download = "다운로드" delete = "삭제" unsupported = "지원되지 않음" +active = "활성" addToUpload = "업로드에 추가" +closeFile = "파일 닫기" deleteAll = "모두 삭제" loadingFiles = "파일 불러오는 중..." noFiles = "사용 가능한 파일이 없습니다" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "이메일 주소를 최소 한 개 이상 입력해야 합니다" submit = "초대장 보내기" success = "사용자 초대가 완료되었습니다" -partialSuccess = "일부 초대가 실패했습니다" +partialFailure = "일부 초대가 실패했습니다" allFailed = "사용자 초대에 실패했습니다" error = "초대장 전송에 실패했습니다" @@ -5797,6 +5842,13 @@ submit = "로그인" signInWith = "다음으로 로그인" oauthPending = "인증을 위해 브라우저를 여는 중..." orContinueWith = "또는 이메일로 계속" +serverRequirement = "참고: 서버에서 로그인 기능이 활성화되어 있어야 합니다." +showInstructions = "활성화 방법" +hideInstructions = "지침 숨기기" +instructions = "Stirling PDF 서버에서 로그인 기능을 활성화하려면:" +instructionsEnvVar = "다음 환경 변수를 설정하세요:" +instructionsOrYml = "또는 settings.yml에서:" +instructionsRestart = "그런 다음 변경 사항을 적용하려면 서버를 재시작하세요." [setup.login.username] label = "사용자 이름" diff --git a/frontend/public/locales/ml-ML/translation.toml b/frontend/public/locales/ml-ML/translation.toml index b7f97c3c2..92106dd93 100644 --- a/frontend/public/locales/ml-ML/translation.toml +++ b/frontend/public/locales/ml-ML/translation.toml @@ -131,7 +131,7 @@ unsupported = "പിന്തുണയില്ല" [toolPanel] placeholder = "തുടങ്ങാൻ ഒരു ടൂൾ തിരഞ്ഞെടുക്കുക" -alpha = "Alpha" +alpha = "ആൽഫ" premiumFeature = "പ്രീമിയം ഫീച്ചർ:" comingSoon = "വരുന്നു:" @@ -163,6 +163,11 @@ unfavorite = "പ്രിയപ്പെട്ടവയിൽ നിന്ന fullscreen = "ഫുൾസ്ക്രീൻ മോഡിലേക്കു മാറ്റുക" sidebar = "സൈഡ്ബാർ മോഡിലേക്കു മാറ്റുക" +[backendStartup] +notFoundTitle = "ബാക്ക്‌എൻഡ് കണ്ടെത്താനായില്ല" +retry = "വീണ്ടും ശ്രമിക്കുക" +unreachable = "ഈ ആപ്പ്ലിക്കേഷൻ നിലവിൽ ബാക്ക്‌എൻഡുമായി കണക്റ്റ് ചെയ്യാൻ കഴിയുന്നില്ല. ബാക്ക്‌എൻഡിന്റെ നിലയും നെറ്റ്‌വർക്ക് കണക്റ്റിവിറ്റിയും പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക." + [zipWarning] title = "വലിയ ZIP ഫയൽ" message = "ഈ ZIP-ൽ {{count}} ഫയലുകൾ ഉണ്ട്. എങ്കിലും എക്സ്ട്രാക്റ്റ് ചെയ്യട്ടേ?" @@ -369,7 +374,7 @@ privacy = "സ്വകാര്യത" [settings.developer] title = "ഡെവലപ്പർ" -apiKeys = "API Keys" +apiKeys = "API കീകൾ" [settings.tooltips] enableLoginFirst = "ആദ്യം ലോഗിൻ മോഡ് സജീവമാക്കുക" @@ -709,7 +714,7 @@ title = "പരത്തുക" desc = "ഒരു PDF-ൽ നിന്ന് എല്ലാ ഇന്ററാക്ടീവ് ഘടകങ്ങളും ഫോമുകളും നീക്കം ചെയ്യുക" [home.certSign] -tags = "authenticate,PEM,P12,official,encrypt,sign,certificate,PKCS12,JKS,server,manual,auto" +tags = "പ്രാമാണീകരണം,PEM,P12,ഔദ്യോഗികം,എൻക്രിപ്റ്റ്,സൈൻ,സർട്ടിഫിക്കറ്റ്,PKCS12,JKS,സെർവർ,മാനുവൽ,ഓട്ടോ" title = "സർട്ടിഫിക്കറ്റ് ഉപയോഗിച്ച് ഒപ്പിടുക" desc = "ഒരു സർട്ടിഫിക്കറ്റ്/കീ (PEM/P12) ഉപയോഗിച്ച് ഒരു PDF ഒപ്പിടുന്നു" @@ -794,7 +799,7 @@ title = "ഒരൊറ്റ വലിയ പേജ്" desc = "എല്ലാ PDF പേജുകളും ഒരൊറ്റ വലിയ പേജിലേക്ക് ലയിപ്പിക്കുന്നു" [home.showJS] -tags = "javascript,code,script" +tags = "javascript,കോഡ്,സ്ക്രിപ്റ്റ്" title = "ജാവാസ്ക്രിപ്റ്റ് കാണിക്കുക" desc = "ഒരു PDF-ൽ കുത്തിവച്ച ഏതെങ്കിലും JS തിരയുകയും പ്രദർശിപ്പിക്കുകയും ചെയ്യുന്നു" @@ -912,9 +917,12 @@ desc = "PDF പ്രവർത്തനങ്ങൾ ബന്ധിപ്പി desc = "മറ്റൊരു PDF-ന് മുകളിൽ PDF-കൾ ഓവർലേ ചെയ്യുന്നു" title = "PDF-കൾ ഓവർലേ ചെയ്യുക" +[home.pdfTextEditor] +title = "PDF ടെക്സ്റ്റ് എഡിറ്റർ" +desc = "PDFകളിലെ നിലവിലുള്ള ടെക്സ്റ്റും ചിത്രങ്ങളും തിരുത്തുക" [home.addText] -tags = "text,annotation,label" +tags = "ടെക്സ്റ്റ്,അനോട്ടേഷൻ,ലേബൽ" title = "ടെക്സ്റ്റ് ചേർക്കുക" desc = "നിങ്ങളുടെ PDF-ൽ എവിടെയിലും കസ്റ്റം ടെക്സ്റ്റ് ചേർക്കുക" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "വരച്ച ഒപ്പ്" defaultImageLabel = "അപ്‌ലോഡ് ചെയ്ത ഒപ്പ്" defaultTextLabel = "ടൈപ്പ് ചെയ്ത ഒപ്പ്" saveButton = "ഒപ്പ് സേവ് ചെയ്യുക" +savePersonal = "വ്യക്തിപരമായി സംരക്ഷിക്കുക" +saveShared = "പങ്കിട്ടതായി സംരക്ഷിക്കുക" saveUnavailable = "സേവ് ചെയ്യാൻ ആദ്യം ഒരു ഒപ്പ് സൃഷ്ടിക്കുക." noChanges = "നിലവിലെ ഒപ്പ് ഇതിനകം സേവ് ചെയ്തിട്ടുണ്ട്." +tempStorageTitle = "താൽക്കാലിക ബ്രൗസർ സ്റ്റോറേജ്" +tempStorageDescription = "ഒപ്പുകൾ നിങ്ങളുടെ ബ്രൗസറിൽ മാത്രം സംഭരിക്കപ്പെടും. ബ്രൗസർ ഡാറ്റ നീക്കം ചെയ്താൽ അല്ലെങ്കിൽ ബ്രൗസർ മാറ്റിയാൽ അവ നഷ്ടപ്പെടും." +personalHeading = "വ്യക്തിഗത ഒപ്പുകൾ" +sharedHeading = "പങ്കിട്ട ഒപ്പുകൾ" +personalDescription = "ഈ ഒപ്പുകൾ നിങ്ങള്ക്ക് മാത്രമേ കാണാനാകൂ." +sharedDescription = "എല്ലാ ഉപയോക്താക്കളും ഈ ഒപ്പുകൾ കാണുകയും ഉപയോഗിക്കുകയും ചെയ്യാം." [sign.saved.type] canvas = "ഡ്രോയിംഗ്" @@ -2731,7 +2747,7 @@ submit = "സമർപ്പിക്കുക" failed = "മൾട്ടി-പേജ് ലേഔട്ട് സൃഷ്ടിക്കുമ്പോൾ പിശക് സംഭവിച്ചു." [bookletImposition] -tags = "booklet,imposition,printing,binding,folding,signature" +tags = "ബുക്ക്‌ലെറ്റ്,ഇംപോസിഷൻ,പ്രിന്റിംഗ്,ബൈൻഡിംഗ്,മടക്കൽ,സിഗ്നേച്ചർ" title = "ബുക്ക്ലെറ്റ് ഇംപോസിഷൻ" header = "ബുക്ക്ലെറ്റ് ഇംപോസിഷൻ" submit = "ബുക്ക്ലെറ്റ് സൃഷ്ടിക്കുക" @@ -2830,7 +2846,7 @@ scaleFactor = "ഒരു പേജിന്റെ സൂം നില (ക്ര submit = "സമർപ്പിക്കുക" [adjustPageScale] -tags = "resize,modify,dimension,adapt" +tags = "വലിപ്പമാറ്റം,ഭേദഗതി,പരിമാണം,അനുസൃതമാക്കൽ" title = "പേജ് സ്കെയിൽ ക്രമപ്പെടുത്തുക" header = "പേജ് സ്കെയിൽ ക്രമപ്പെടുത്തുക" submit = "പേജ് സ്കെയിൽ ക്രമപ്പെടുത്തുക" @@ -2841,8 +2857,8 @@ label = "സ്കെയിൽ ഫാക്ടർ" [adjustPageScale.pageSize] label = "ടാർഗറ്റ് പേജ് വലിപ്പം" keep = "അസൽ വലിപ്പം നിലനിർത്തുക" -letter = "Letter" -legal = "Legal" +letter = "ലറ്റർ" +legal = "ലീഗൽ" [adjustPageScale.error] failed = "പേജ് സ്കെയിൽ ക്രമപ്പെടുത്തുന്നതിനിടെ പിശക് സംഭവിച്ചു." @@ -3380,7 +3396,7 @@ certHint = "കസ്റ്റം ട്രസ്റ്റ് സോഴ്‌സ title = "സ്ഥിരീകരണ സെറ്റിങ്ങുകൾ" [replaceColor] -tags = "Replace Colour,Page operations,Back end,server side" +tags = "നിറം പകരുക,പേജ് പ്രവർത്തനങ്ങൾ,ബാക്ക്‌എൻഡ്,സെർവർ-സൈഡ്" [replaceColor.labels] settings = "സെറ്റിങ്ങുകൾ" @@ -3438,6 +3454,9 @@ signinTitle = "ദയവായി സൈൻ ഇൻ ചെയ്യുക" ssoSignIn = "സിംഗിൾ സൈൻ-ഓൺ വഴി ലോഗിൻ ചെയ്യുക" oAuth2AutoCreateDisabled = "OAUTH2 ഓട്ടോ-ക്രിയേറ്റ് യൂസർ പ്രവർത്തനരഹിതമാക്കി" oAuth2AdminBlockedUser = "രജിസ്റ്റർ ചെയ്യാത്ത ഉപയോക്താക്കളുടെ രജിസ്ട്രേഷനോ ലോഗിൻ ചെയ്യുന്നതോ നിലവിൽ തടഞ്ഞിരിക്കുന്നു. ദയവായി അഡ്മിനിസ്ട്രേറ്ററുമായി ബന്ധപ്പെടുക." +oAuth2RequiresLicense = "OAuth/SSO ലോഗിനിന് ഒരു പെയ്ഡ് ലൈസൻസ് (Server അല്ലെങ്കിൽ Enterprise) ആവശ്യമാണ്. നിങ്ങളുടെ പ്ലാൻ അപ്‌ഗ്രേഡ് ചെയ്യാൻ അഡ്മിനിസ്ട്രേറ്ററുമായി ബന്ധപ്പെടുക." +saml2RequiresLicense = "SAML ലോഗിനിന് ഒരു പെയ്ഡ് ലൈസൻസ് (Server അല്ലെങ്കിൽ Enterprise) ആവശ്യമാണ്. നിങ്ങളുടെ പ്ലാൻ അപ്‌ഗ്രേഡ് ചെയ്യാൻ അഡ്മിനിസ്ട്രേറ്ററുമായി ബന്ധപ്പെടുക." +maxUsersReached = "നിലവിലുള്ള ലൈസൻസിലെ പരമാവധി ഉപയോക്താക്കൾ എത്തിച്ചേർന്നു. നിങ്ങളുടെ പ്ലാൻ അപ്‌ഗ്രേഡ് ചെയ്യുകയോ കൂടുതൽ സീറ്റുകൾ ചേർക്കുകയോ ചെയ്യാൻ അഡ്മിനിസ്ട്രേറ്ററുമായി ബന്ധപ്പെടുക." oauth2RequestNotFound = "അംഗീകാര അഭ്യർത്ഥന കണ്ടെത്തിയില്ല" oauth2InvalidUserInfoResponse = "അസാധുവായ ഉപയോക്തൃ വിവര പ്രതികരണം" oauth2invalidRequest = "അസാധുവായ അഭ്യർത്ഥന" @@ -3771,7 +3790,7 @@ version = "നിലവിലെ റിലീസ്" title = "API ഡോക്യുമെന്റേഷൻ" header = "API ഡോക്യുമെന്റേഷൻ" desc = "Stirling PDF API എൻഡ്പോയിന്റുകൾ കാണുകയും പരിശോധിക്കുകയും ചെയ്യുക" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,ഡോക്യുമെന്റേഷൻ,swagger,എൻഡ്പോയിന്റുകൾ,വികസനം" [cookieBanner.popUp] title = "ഞങ്ങൾ കുക്കികൾ എങ്ങനെ ഉപയോഗിക്കുന്നു" @@ -3846,14 +3865,17 @@ fitToWidth = "വീതിക്ക് ഒത്താക്കുക" actualSize = "യഥാർത്ഥ വലിപ്പം" [viewer] +cannotPreviewFile = "ഫയൽ പ്രിവ്യൂ ചെയ്യാൻ കഴിയില്ല" +dualPageView = "രണ്ടുപേജ് ദൃശ്യം" firstPage = "ആദ്യ പേജ്" lastPage = "അവസാന പേജ്" -previousPage = "മുൻപത്തെ പേജ്" nextPage = "അടുത്ത പേജ്" +onlyPdfSupported = "വ്യൂവറിന് PDF ഫയലുകൾ മാത്രം പിന്തുണയ്ക്കാം. ഈ ഫയൽ വേറെ ഒരു ഫോർമാറ്റാണെന്ന് തോന്നുന്നു." +previousPage = "മുൻപത്തെ പേജ്" +singlePageView = "ഒറ്റ പേജ് ദൃശ്യം" +unknownFile = "അപരിചിതമായ ഫയൽ" zoomIn = "സൂം ഇൻ" zoomOut = "സൂം ഔട്ട്" -singlePageView = "ഒറ്റ പേജ് ദൃശ്യം" -dualPageView = "രണ്ടുപേജ് ദൃശ്യം" [rightRail] closeSelected = "തിരഞ്ഞെടുത്ത ഫയലുകൾ അടയ്‌ക്കുക" @@ -3877,6 +3899,7 @@ toggleSidebar = "സൈഡ്ബാർ മാറ്റുക" exportSelected = "തിരഞ്ഞെടുത്ത പേജുകൾ എക്സ്പോർട്ട് ചെയ്യുക" toggleAnnotations = "അനോട്ടേഷൻ ദൃശ്യമാനം മാറ്റുക" annotationMode = "അനോട്ടേഷൻ മോഡ് മാറ്റുക" +print = "PDF അച്ചടിക്കുക" draw = "വരയ്ക്കുക" save = "സംരക്ഷിക്കുക" saveChanges = "മാറ്റങ്ങൾ സംരക്ഷിക്കുക" @@ -4231,7 +4254,7 @@ label = "പ്രൊവൈഡർ" description = "ഓതന്റിക്കേഷനായി ഉപയോഗിക്കുന്ന OAuth2 പ്രൊവൈഡർ" [admin.settings.connections.oauth2.issuer] -label = "Issuer URL" +label = "ഇഷ്യൂവർ URL" description = "OAuth2 പ്രൊവൈഡറിന്റെ issuer URL" [admin.settings.connections.oauth2.clientId] @@ -4255,7 +4278,7 @@ label = "രജിസ്‌ട്രേഷൻ തടയുക" description = "OAuth2 വഴി പുതിയ ഉപയോക്തൃ രജിസ്‌ട്രേഷൻ തടയുക" [admin.settings.connections.oauth2.scopes] -label = "OAuth2 Scopes" +label = "OAuth2 സ്കോപ്പുകൾ" description = "OAuth2 സ്കോപ്പുകളുടെ കോമ ഉപയോഗിച്ച് വേർതിരിച്ച പട്ടിക (ഉദാ., openid, profile, email)" [admin.settings.connections.saml2] @@ -4494,6 +4517,7 @@ description = "Impressum-ലേക്ക് URL അല്ലെങ്കിൽ title = "പ്രീമിയം & എന്റർപ്രൈസ്" description = "നിങ്ങളുടെ പ്രീമിയം അല്ലെങ്കിൽ എന്റർപ്രൈസ് ലൈസൻസ് കീ ക്രമീകരിക്കുക." license = "ലൈസൻസ് കോൺഫിഗറേഷൻ" +noInput = "ദയവായി ഒരു ലൈസന്റ്‌സ് കീ അല്ലെങ്കിൽ ഫയൽ നൽകുക" [admin.settings.premium.licenseKey] toggle = "ലൈസൻസ് കീ അല്ലെങ്കിൽ സർട്ടിഫിക്കറ്റ് ഫയൽ ഉണ്ടോ?" @@ -4511,6 +4535,25 @@ line1 = "നിലവിലെ ലൈസൻസ് കീ ഓവർറൈറ് line2 = "നിങ്ങൾ മറ്റെവിടെയെങ്കിലും ബാക്കപ്പ് എടുത്തിട്ടില്ലെങ്കിൽ നിങ്ങളുടെ പഴയ ലൈസൻസ് സ്ഥിരമായി നഷ്ടപ്പെടും." line3 = "പ്രധാനപ്പെട്ടത്: ലൈസൻസ് കീകൾ സ്വകാര്യവും സുരക്ഷിതവുമാക്കി സൂക്ഷിക്കുക. ഒരിക്കലും അവ പൊതു വേദിയിൽ പങ്കുവെക്കരുത്." +[admin.settings.premium.inputMethod] +text = "ലൈസൻസ് കീ" +file = "സർട്ടിഫിക്കറ്റ് ഫയൽ" + +[admin.settings.premium.file] +label = "ലൈസൻസ് സർട്ടിഫിക്കറ്റ് ഫയൽ" +description = "നിങ്ങളുടെ ഓഫ്ലൈൻ വാങ്ങലുകളിൽ നിന്നുള്ള .lic അല്ലെങ്കിൽ .cert ലൈസൻസ് ഫയൽ അപ്‌ലോഡ് ചെയ്യുക" +choose = "ലൈസൻസ് ഫയൽ തിരഞ്ഞെടുക്കുക" +selected = "തിരഞ്ഞെടുക്കിയത്: {{filename}} ({{size}})" +successMessage = "ലൈസൻസ് ഫയൽ അപ്‌ലോഡ് ചെയ്തു വിജയകരമായി സജീവമാക്കിയിരിക്കുന്നു. റീസ്റ്റാർട്ട് ആവശ്യമില്ല." + +[admin.settings.premium.currentLicense] +title = "സജീവ ലൈസൻസ്" +file = "ഉറവിടം: ലൈസൻസ് ഫയൽ ({{path}})" +key = "ഉറവിടം: ലൈസൻസ് കീ" +type = "തരം: {{type}}" +noInput = "ദയവായി ഒരു ലൈസൻസ് കീ നൽകുകയോ ഒരു സർട്ടിഫിക്കറ്റ് ഫയൽ അപ്‌ലോഡ് ചെയ്യുകയോ ചെയ്യുക" +success = "വിജയം" + [admin.settings.premium.enabled] label = "പ్రీമിയം സവിശേഷതകൾ പ്രാപ്തമാക്കുക" description = "പ്രോ/എന്റർപ്രൈസ് സവിശേഷതകൾക്കായി ലൈസൻസ് കീ പരിശോധനകൾ പ്രാപ്തമാക്കുക" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} തിരഞ്ഞെടുക്കപ്പെട download = "ഡൗൺലോഡ്" delete = "ഇല്ലാതാക്കുക" unsupported = "പിന്തുണയില്ല" +active = "സജീവം" addToUpload = "അപ്‌ലോഡിലേക്ക് ചേർക്കുക" +closeFile = "ഫയൽ അടയ്ക്കുക" deleteAll = "എല്ലാം ഇല്ലാതാക്കുക" loadingFiles = "ഫയലുകൾ ലോഡുചെയ്യുന്നു..." noFiles = "ഫയലുകളൊന്നും ലഭ്യമല്ല" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "കുറഞ്ഞത് ഒരു ഇമെയിൽ വിലാസമെങ്കിലും ആവശ്യമാണ്" submit = "ക്ഷണങ്ങൾ അയയ്ക്കുക" success = "ഉപയോക്താക്കളെ വിജയകരമായി ക്ഷണിച്ചു" -partialSuccess = "ചില ക്ഷണങ്ങൾ പരാജയപ്പെട്ടു" +partialFailure = "ചില ക്ഷണങ്ങൾ പരാജയപ്പെട്ടു" allFailed = "ഉപയോക്താക്കളെ ക്ഷണിക്കൽ പരാജയപ്പെട്ടു" error = "ക്ഷണങ്ങൾ അയയ്ക്കൽ പരാജയപ്പെട്ടു" @@ -5797,6 +5842,13 @@ submit = "ലോഗിൻ" signInWith = "ഇതുപയോഗിച്ച് സൈൻ ഇൻ ചെയ്യുക" oauthPending = "ഓതന്റിക്കേഷനായി ബ്രൗസർ തുറക്കുന്നു..." orContinueWith = "അല്ലെങ്കിൽ ഇമെയിലോടെ തുടരുക" +serverRequirement = "ശ്രദ്ധിക്കുക: സെർവറിൽ ലോഗിൻ പ്രവർത്തനക്ഷമമാക്കിയിരിക്കണം." +showInstructions = "എങ്ങനെ പ്രവർത്തനക്ഷമമാക്കാം?" +hideInstructions = "നിർദ്ദേശങ്ങൾ മറയ്ക്കുക" +instructions = "നിങ്ങളുടെ Stirling PDF സെർവറിൽ ലോഗിൻ പ്രവർത്തനക്ഷമമാക്കാൻ:" +instructionsEnvVar = "Environment variable സജ്ജമാക്കുക:" +instructionsOrYml = "അല്ലെങ്കിൽ settings.yml-ൽ:" +instructionsRestart = "തുടർന്ന് മാറ്റങ്ങൾ പ്രാബല്യത്തിൽ വരാൻ നിങ്ങളുടെ സെർവർ റീസ്റ്റാർട്ട് ചെയ്യുക." [setup.login.username] label = "യൂസർനെയിം" @@ -5847,7 +5899,7 @@ singleLine = "സിംഗിൾ ലൈൻ" [pdfTextEditor.badges] unsaved = "എഡിറ്റ് ചെയ്തു" modified = "എഡിറ്റ് ചെയ്തു" -earlyAccess = "Early Access" +earlyAccess = "എർലി ആക്‌സസ്" [pdfTextEditor.actions] reset = "മാറ്റങ്ങൾ റീസെറ്റ് ചെയ്യുക" diff --git a/frontend/public/locales/nl-NL/translation.toml b/frontend/public/locales/nl-NL/translation.toml index 321acd475..b5c5cf99b 100644 --- a/frontend/public/locales/nl-NL/translation.toml +++ b/frontend/public/locales/nl-NL/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Uit favorieten verwijderen" fullscreen = "Overschakelen naar volledig scherm" sidebar = "Overschakelen naar zijbalkmodus" +[backendStartup] +notFoundTitle = "Backend niet gevonden" +retry = "Opnieuw proberen" +unreachable = "De applicatie kan momenteel geen verbinding maken met de backend. Controleer de status van de backend en de netwerkverbinding en probeer het vervolgens opnieuw." + [zipWarning] title = "Groot ZIP-bestand" message = "Dit ZIP-bestand bevat {{count}} bestanden. Toch uitpakken?" @@ -347,7 +352,7 @@ teams = "Teams" title = "Configuratie" systemSettings = "Systeeminstellingen" features = "Functies" -endpoints = "Endpoints" +endpoints = "Eindpunten" database = "Database" advanced = "Geavanceerd" @@ -556,7 +561,7 @@ totalEndpoints = "Totaal aantal endpoints" totalVisits = "Totaal aantal bezoeken" showing = "Weergeven" selectedVisits = "Geselecteerde bezoeken" -endpoint = "Endpoint" +endpoint = "Eindpunt" visits = "Bezoeken" percentage = "Percentage" loading = "Laden..." @@ -912,6 +917,9 @@ desc = "Bouw workflows met meerdere stappen door PDF-acties te koppelen. Ideaal desc = "Plaatst PDF's over een andere PDF heen" title = "PDF's overlappen" +[home.pdfTextEditor] +title = "PDF-teksteditor" +desc = "Bewerk bestaande tekst en afbeeldingen in PDF's" [home.addText] tags = "tekst,annotatie,label" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Getekende handtekening" defaultImageLabel = "Geüploade handtekening" defaultTextLabel = "Getypte handtekening" saveButton = "Handtekening opslaan" +savePersonal = "Als persoonlijk opslaan" +saveShared = "Als gedeeld opslaan" saveUnavailable = "Maak eerst een handtekening om deze op te slaan." noChanges = "De huidige handtekening is al opgeslagen." +tempStorageTitle = "Tijdelijke browseropslag" +tempStorageDescription = "Handtekeningen worden alleen in je browser opgeslagen. Ze gaan verloren als je je browsergegevens wist of van browser wisselt." +personalHeading = "Persoonlijke handtekeningen" +sharedHeading = "Gedeelde handtekeningen" +personalDescription = "Alleen jij kunt deze handtekeningen zien." +sharedDescription = "Alle gebruikers kunnen deze handtekeningen zien en gebruiken." [sign.saved.type] canvas = "Tekening" @@ -3438,6 +3454,9 @@ signinTitle = "Gelieve in te loggen" ssoSignIn = "Inloggen via Single Sign-on" oAuth2AutoCreateDisabled = "OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld" oAuth2AdminBlockedUser = "Registratie of inloggen van niet-registreerde gebruikers is helaas momenteel geblokkeerd. Neem contact op met de beheerder." +oAuth2RequiresLicense = "OAuth/SSO-inloggen vereist een betaalde licentie (Server of Enterprise). Neem contact op met de beheerder om uw abonnement te upgraden." +saml2RequiresLicense = "SAML-inloggen vereist een betaalde licentie (Server of Enterprise). Neem contact op met de beheerder om uw abonnement te upgraden." +maxUsersReached = "Het maximumaantal gebruikers voor uw huidige licentie is bereikt. Neem contact op met de beheerder om uw abonnement te upgraden of extra plaatsen toe te voegen." oauth2RequestNotFound = "Autorisatieverzoek niet gevonden" oauth2InvalidUserInfoResponse = "Ongeldige reactie op gebruikersinfo" oauth2invalidRequest = "Ongeldig verzoek" @@ -3805,7 +3824,7 @@ description = "These cookies are essential for the website to function properly. 2 = "Altijd ingeschakeld" [cookieBanner.preferencesModal.analytics] -title = "Analytics" +title = "Analyse" description = "Deze cookies helpen ons te begrijpen hoe onze tools worden gebruikt, zodat we ons kunnen richten op het bouwen van de functies die onze community het meest waardeert. Wees gerust—Stirling PDF kan niet en zal nooit de inhoud van de documenten waarmee je werkt volgen." [cookieBanner.services] @@ -3846,14 +3865,17 @@ fitToWidth = "Passend op breedte" actualSize = "Werkelijke grootte" [viewer] +cannotPreviewFile = "Kan voorbeeld van bestand niet weergeven" +dualPageView = "Dubbele paginaweergave" firstPage = "Eerste pagina" lastPage = "Laatste pagina" -previousPage = "Vorige pagina" nextPage = "Volgende pagina" +onlyPdfSupported = "De viewer ondersteunt alleen PDF-bestanden. Dit bestand lijkt een ander formaat te hebben." +previousPage = "Vorige pagina" +singlePageView = "Enkele paginaweergave" +unknownFile = "Onbekend bestand" zoomIn = "Inzoomen" zoomOut = "Uitzoomen" -singlePageView = "Enkele paginaweergave" -dualPageView = "Dubbele paginaweergave" [rightRail] closeSelected = "Geselecteerde bestanden sluiten" @@ -3877,6 +3899,7 @@ toggleSidebar = "Zijbalk tonen/verbergen" exportSelected = "Geselecteerde pagina's exporteren" toggleAnnotations = "Annotaties tonen/verbergen" annotationMode = "Annotatiemodus schakelen" +print = "PDF afdrukken" draw = "Tekenen" save = "Opslaan" saveChanges = "Wijzigingen opslaan" @@ -4343,7 +4366,7 @@ features = "Feature-flags" processing = "Verwerking" [admin.settings.advanced.endpoints] -label = "Endpoints" +label = "Eindpunten" manage = "API-endpoints beheren" description = "Endpointbeheer wordt geconfigureerd via YAML. Zie de documentatie voor details over het in-/uitschakelen van specifieke endpoints." @@ -4494,6 +4517,7 @@ description = "URL of bestandsnaam van het impressum (in sommige jurisdicties ve title = "Premium & Enterprise" description = "Configureer je premium- of enterprise-licentiesleutel." license = "Licentieconfiguratie" +noInput = "Geef een licentiesleutel of bestand op" [admin.settings.premium.licenseKey] toggle = "Heb je een licentiesleutel of certificaatbestand?" @@ -4511,6 +4535,25 @@ line1 = "Het overschrijven van je huidige licentiesleutel kan niet ongedaan word line2 = "Je vorige licentie gaat permanent verloren, tenzij je er elders een back-up van hebt." line3 = "Belangrijk: houd licentiesleutels privé en veilig. Deel ze nooit openbaar." +[admin.settings.premium.inputMethod] +text = "Licentiesleutel" +file = "Certificaatbestand" + +[admin.settings.premium.file] +label = "Licentiecertificaatbestand" +description = "Upload je .lic- of .cert-licentiebestand van offline aankopen" +choose = "Kies licentiebestand" +selected = "Geselecteerd: {{filename}} ({{size}})" +successMessage = "Licentiebestand succesvol geüpload en geactiveerd. Herstarten niet vereist." + +[admin.settings.premium.currentLicense] +title = "Actieve licentie" +file = "Bron: licentiebestand ({{path}})" +key = "Bron: licentiesleutel" +type = "Type: {{type}}" +noInput = "Geef een licentiesleutel op of upload een certificaatbestand" +success = "Succes" + [admin.settings.premium.enabled] label = "Premiumfuncties inschakelen" description = "Licentiesleutelcontrole inschakelen voor pro-/enterprise-functies" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} geselecteerd" download = "Downloaden" delete = "Verwijderen" unsupported = "Niet ondersteund" +active = "Actief" addToUpload = "Aan upload toevoegen" +closeFile = "Bestand sluiten" deleteAll = "Alles verwijderen" loadingFiles = "Bestanden laden..." noFiles = "Geen bestanden beschikbaar" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Er is minstens één e-mailadres vereist" submit = "Uitnodigingen verzenden" success = "Gebruiker(s) succesvol uitgenodigd" -partialSuccess = "Sommige uitnodigingen zijn mislukt" +partialFailure = "Sommige uitnodigingen zijn mislukt" allFailed = "Uitnodigen van gebruikers is mislukt" error = "Uitnodigingen verzenden is mislukt" @@ -5709,7 +5754,7 @@ title = "Grafiek van endpointgebruik" [usage.table] title = "Gedetailleerde statistieken" -endpoint = "Endpoint" +endpoint = "Eindpunt" visits = "Bezoeken" percentage = "Percentage" noData = "Geen gegevens beschikbaar" @@ -5797,6 +5842,13 @@ submit = "Inloggen" signInWith = "Inloggen met" oauthPending = "Browser wordt geopend voor authenticatie..." orContinueWith = "Of ga verder met e-mail" +serverRequirement = "Let op: op de server moet inloggen zijn ingeschakeld." +showInstructions = "Hoe inschakelen?" +hideInstructions = "Instructies verbergen" +instructions = "Om inloggen op uw Stirling PDF-server in te schakelen:" +instructionsEnvVar = "Stel de omgevingsvariabele in:" +instructionsOrYml = "Of in settings.yml:" +instructionsRestart = "Start vervolgens uw server opnieuw zodat de wijzigingen van kracht worden." [setup.login.username] label = "Gebruikersnaam" diff --git a/frontend/public/locales/no-NB/translation.toml b/frontend/public/locales/no-NB/translation.toml index 21b873f01..7dc8b431a 100644 --- a/frontend/public/locales/no-NB/translation.toml +++ b/frontend/public/locales/no-NB/translation.toml @@ -131,7 +131,7 @@ unsupported = "Ikke støttet" [toolPanel] placeholder = "Velg et verktøy for å komme i gang" -alpha = "Alpha" +alpha = "Alfa" premiumFeature = "Premium-funksjon:" comingSoon = "Kommer snart:" @@ -163,6 +163,11 @@ unfavorite = "Fjern fra favoritter" fullscreen = "Bytt til fullskjerm-modus" sidebar = "Bytt til sidepanel-modus" +[backendStartup] +notFoundTitle = "Backend ikke funnet" +retry = "Prøv igjen" +unreachable = "Programmet kan for øyeblikket ikke koble til backend. Kontroller backend-status og nettverkstilkobling, og prøv igjen." + [zipWarning] title = "Stor ZIP-fil" message = "Denne ZIP-en inneholder {{count}} filer. Pakk ut likevel?" @@ -912,6 +917,9 @@ desc = "Bygg flertrinns arbeidsflyter ved å lenke sammen PDF-handlinger. Ideelt desc = "Legger PDF-er over hverandre" title = "Overlay PDF-er" +[home.pdfTextEditor] +title = "PDF-teksteditor" +desc = "Rediger eksisterende tekst og bilder i PDF-filer" [home.addText] tags = "tekst,merknad,etikett" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Tegnet signatur" defaultImageLabel = "Opplastet signatur" defaultTextLabel = "Tekstsignatur" saveButton = "Lagre signatur" +savePersonal = "Lagre personlig" +saveShared = "Lagre delt" saveUnavailable = "Opprett en signatur først for å lagre den." noChanges = "Gjeldende signatur er allerede lagret." +tempStorageTitle = "Midlertidig nettleserlagring" +tempStorageDescription = "Signaturer lagres bare i nettleseren din. De går tapt hvis du sletter nettleserdata eller bytter nettleser." +personalHeading = "Personlige signaturer" +sharedHeading = "Delte signaturer" +personalDescription = "Bare du kan se disse signaturene." +sharedDescription = "Alle brukere kan se og bruke disse signaturene." [sign.saved.type] canvas = "Tegning" @@ -3438,6 +3454,9 @@ signinTitle = "Vennligst logg inn" ssoSignIn = "Logg inn via Enkel Pålogging" oAuth2AutoCreateDisabled = "OAUTH2 Auto-Opretting av bruker deaktivert" oAuth2AdminBlockedUser = "Registrering eller pålogging for ikke-registrerte brukere er for øyeblikket blokkert. Vennligst kontakt administrator" +oAuth2RequiresLicense = "OAuth/SSO-pålogging krever en betalt lisens (Server eller Enterprise). Kontakt administratoren for å oppgradere planen din." +saml2RequiresLicense = "SAML-pålogging krever en betalt lisens (Server eller Enterprise). Kontakt administratoren for å oppgradere planen din." +maxUsersReached = "Maksimalt antall brukere er nådd for din nåværende lisens. Kontakt administratoren for å oppgradere planen din eller legge til flere brukerplasser." oauth2RequestNotFound = "Autentiseringsforespørsel ikke funnet" oauth2InvalidUserInfoResponse = "Ugyldig brukerinforespons" oauth2invalidRequest = "Ugyldig forespørsel" @@ -3846,14 +3865,17 @@ fitToWidth = "Tilpass til bredde" actualSize = "Faktisk størrelse" [viewer] +cannotPreviewFile = "Kan ikke forhåndsvise fil" +dualPageView = "Dobbelsidevisning" firstPage = "Første side" lastPage = "Siste side" -previousPage = "Forrige side" nextPage = "Neste side" +onlyPdfSupported = "Visningsprogrammet støtter bare PDF-filer. Denne filen ser ut til å ha et annet format." +previousPage = "Forrige side" +singlePageView = "Enkeltsidevisning" +unknownFile = "Ukjent fil" zoomIn = "Zoom inn" zoomOut = "Zoom ut" -singlePageView = "Enkeltsidevisning" -dualPageView = "Dobbelsidevisning" [rightRail] closeSelected = "Lukk valgte filer" @@ -3877,6 +3899,7 @@ toggleSidebar = "Vis/skjul sidepanel" exportSelected = "Eksporter valgte sider" toggleAnnotations = "Vis/skjul merknader" annotationMode = "Veksle merknadsmodus" +print = "Skriv ut PDF" draw = "Tegn" save = "Lagre" saveChanges = "Lagre endringer" @@ -4153,7 +4176,7 @@ description = "Spor brukerhandlinger og systemhendelser for etterlevelse og sikk [admin.settings.security.audit.level] label = "Revisjonsnivå" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=AV, 1=GRUNNLEGGENDE, 2=STANDARD, 3=DETALJERT" [admin.settings.security.audit.retentionDays] label = "Bevaring av revisjon (dager)" @@ -4494,6 +4517,7 @@ description = "URL eller filnavn til impressum (påkrevd i noen jurisdiksjoner)" title = "Premium og Enterprise" description = "Konfigurer din premium- eller enterprise-lisensnøkkel." license = "Lisenskonfigurasjon" +noInput = "Oppgi en lisensnøkkel eller fil" [admin.settings.premium.licenseKey] toggle = "Har du en lisensnøkkel eller sertifikatfil?" @@ -4511,6 +4535,25 @@ line1 = "Å overskrive gjeldende lisensnøkkel kan ikke angres." line2 = "Den forrige lisensen vil gå tapt permanent med mindre du har sikkerhetskopiert den et annet sted." line3 = "Viktig: Hold lisensnøkler private og sikre. Del dem aldri offentlig." +[admin.settings.premium.inputMethod] +text = "Lisensnøkkel" +file = "Sertifikatfil" + +[admin.settings.premium.file] +label = "Lisenssertifikatfil" +description = "Last opp .lic- eller .cert-lisensfilen din fra offline-kjøp" +choose = "Velg lisensfil" +selected = "Valgt: {{filename}} ({{size}})" +successMessage = "Lisensfilen ble lastet opp og aktivert. Omstart er ikke nødvendig." + +[admin.settings.premium.currentLicense] +title = "Aktiv lisens" +file = "Kilde: Lisensfil ({{path}})" +key = "Kilde: Lisensnøkkel" +type = "Type: {{type}}" +noInput = "Oppgi en lisensnøkkel eller last opp en sertifikatfil" +success = "Vellykket" + [admin.settings.premium.enabled] label = "Aktiver premiumfunksjoner" description = "Aktiver lisensnøkkelkontroller for pro-/enterprise-funksjoner" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} valgt" download = "Last ned" delete = "Slett" unsupported = "Ikke støttet" +active = "Aktiv" addToUpload = "Legg til i opplasting" +closeFile = "Lukk fil" deleteAll = "Slett alt" loadingFiles = "Laster filer..." noFiles = "Ingen filer tilgjengelig" @@ -5059,7 +5104,7 @@ title = "Erstatt-Inverter-Farge" [replace-color.options] fill = "Fyllfarge" -gradient = "Gradient" +gradient = "Fargeovergang" [replace-color.selectText] 1 = "Erstatt eller Inverter farge alternativer" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Minst én e-postadresse er påkrevd" submit = "Send invitasjoner" success = "bruker(e) invitert" -partialSuccess = "Noen invitasjoner mislyktes" +partialFailure = "Noen invitasjoner mislyktes" allFailed = "Kunne ikke invitere brukere" error = "Kunne ikke sende invitasjoner" @@ -5797,6 +5842,13 @@ submit = "Logg inn" signInWith = "Logg inn med" oauthPending = "Åpner nettleser for autentisering..." orContinueWith = "Eller fortsett med e-post" +serverRequirement = "Merk: Serveren må ha pålogging aktivert." +showInstructions = "Hvordan aktivere?" +hideInstructions = "Skjul instruksjoner" +instructions = "Slik aktiverer du pålogging på din Stirling PDF-server:" +instructionsEnvVar = "Sett miljøvariabelen:" +instructionsOrYml = "Eller i settings.yml:" +instructionsRestart = "Start deretter serveren på nytt for at endringene skal tre i kraft." [setup.login.username] label = "Brukernavn" @@ -5840,7 +5892,7 @@ paragraph = "Avsnittsside" sparse = "Sparsom tekst" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automatisk" paragraph = "Avsnitt" singleLine = "Én linje" diff --git a/frontend/public/locales/pl-PL/translation.toml b/frontend/public/locales/pl-PL/translation.toml index bbde87022..e652c88d2 100644 --- a/frontend/public/locales/pl-PL/translation.toml +++ b/frontend/public/locales/pl-PL/translation.toml @@ -131,7 +131,7 @@ unsupported = "Nieobsługiwane" [toolPanel] placeholder = "Wybierz narzędzie, aby zacząć" -alpha = "Alpha" +alpha = "Alfa" premiumFeature = "Funkcja premium:" comingSoon = "Wkrótce:" @@ -163,6 +163,11 @@ unfavorite = "Usuń z ulubionych" fullscreen = "Przełącz na tryb pełnoekranowy" sidebar = "Przełącz na tryb paska bocznego" +[backendStartup] +notFoundTitle = "Nie znaleziono backendu" +retry = "Spróbuj ponownie" +unreachable = "Aplikacja nie może obecnie połączyć się z backendem. Sprawdź stan backendu i łączność sieciową, a następnie spróbuj ponownie." + [zipWarning] title = "Duży plik ZIP" message = "Ten ZIP zawiera {{count}} plików. Mimo to rozpakować?" @@ -912,6 +917,9 @@ desc = "Buduj wieloetapowe przepływy, łącząc akcje PDF. Idealne do powtarzaj desc = "Nakłada dokumenty PDF na siebie" title = "Nałóż PDFa" +[home.pdfTextEditor] +title = "Edytor tekstu PDF" +desc = "Edytuj istniejący tekst i obrazy w plikach PDF" [home.addText] tags = "tekst,adnotacja,etykieta" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Podpis rysowany" defaultImageLabel = "Przesłany podpis" defaultTextLabel = "Podpis wpisany" saveButton = "Zapisz podpis" +savePersonal = "Zapisz osobiste" +saveShared = "Zapisz udostępnione" saveUnavailable = "Najpierw utwórz podpis, aby go zapisać." noChanges = "Bieżący podpis jest już zapisany." +tempStorageTitle = "Tymczasowe przechowywanie w przeglądarce" +tempStorageDescription = "Podpisy są przechowywane tylko w Twojej przeglądarce. Zostaną utracone po wyczyszczeniu danych przeglądarki lub zmianie przeglądarki." +personalHeading = "Osobiste podpisy" +sharedHeading = "Udostępnione podpisy" +personalDescription = "Tylko Ty widzisz te podpisy." +sharedDescription = "Wszyscy użytkownicy mogą widzieć i używać tych podpisów." [sign.saved.type] canvas = "Rysunek" @@ -3438,6 +3454,9 @@ signinTitle = "Zaloguj się" ssoSignIn = "Zaloguj się za pomocą logowania jednokrotnego" oAuth2AutoCreateDisabled = "Wyłączono automatyczne tworzenie użytkownika OAUTH2" oAuth2AdminBlockedUser = "Rejestracja lub logowanie niezarejestrowanych użytkowników jest obecnie zablokowane. Prosimy o kontakt z administratorem." +oAuth2RequiresLicense = "Logowanie OAuth/SSO wymaga płatnej licencji (Server lub Enterprise). Skontaktuj się z administratorem, aby uaktualnić swój plan." +saml2RequiresLicense = "Logowanie SAML wymaga płatnej licencji (Server lub Enterprise). Skontaktuj się z administratorem, aby uaktualnić swój plan." +maxUsersReached = "Osiągnięto maksymalną liczbę użytkowników dla Twojej obecnej licencji. Skontaktuj się z administratorem, aby uaktualnić plan lub dodać więcej miejsc." oauth2RequestNotFound = "Błąd logowania OAuth2" oauth2InvalidUserInfoResponse = "Niewłaściwe dane logowania" oauth2invalidRequest = "Nieprawidłowe żądanie" @@ -3533,7 +3552,7 @@ title = "PDF do pojedyńczej strony" header = "PDF do pojedyńczej strony" submit = "Zapisz dokument jako PDF z jedną stroną" description = "To narzędzie scali wszystkie strony Twojego PDF w jedną dużą stronę. Szerokość pozostanie taka jak w oryginalnych stronach, a wysokość będzie sumą wysokości wszystkich stron." -filenamePrefix = "single_page" +filenamePrefix = "pojedyncza_strona" [pdfToSinglePage.files] placeholder = "Wybierz plik PDF w widoku głównym, aby rozpocząć" @@ -3846,14 +3865,17 @@ fitToWidth = "Dopasuj do szerokości" actualSize = "Rzeczywisty rozmiar" [viewer] +cannotPreviewFile = "Nie można wyświetlić podglądu pliku" +dualPageView = "Widok dwóch stron" firstPage = "Pierwsza strona" lastPage = "Ostatnia strona" -previousPage = "Poprzednia strona" nextPage = "Następna strona" +onlyPdfSupported = "Przeglądarka obsługuje tylko pliki PDF. Ten plik wydaje się mieć inny format." +previousPage = "Poprzednia strona" +singlePageView = "Widok pojedynczej strony" +unknownFile = "Nieznany plik" zoomIn = "Powiększ" zoomOut = "Pomniejsz" -singlePageView = "Widok pojedynczej strony" -dualPageView = "Widok dwóch stron" [rightRail] closeSelected = "Zamknij wybrane pliki" @@ -3877,6 +3899,7 @@ toggleSidebar = "Przełącz panel boczny" exportSelected = "Eksportuj wybrane strony" toggleAnnotations = "Przełącz widoczność adnotacji" annotationMode = "Przełącz tryb adnotacji" +print = "Drukuj PDF" draw = "Rysuj" save = "Zapisz" saveChanges = "Zapisz zmiany" @@ -4153,7 +4176,7 @@ description = "Śledź działania użytkowników i zdarzenia systemowe na potrze [admin.settings.security.audit.level] label = "Poziom audytu" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=WYŁ., 1=PODSTAWOWY, 2=STANDARDOWY, 3=SZCZEGÓŁOWY" [admin.settings.security.audit.retentionDays] label = "Przechowywanie audytu (dni)" @@ -4494,6 +4517,7 @@ description = "URL lub nazwa pliku do impressum (wymagane w niektórych jurysdyk title = "Premium i Enterprise" description = "Skonfiguruj swój klucz licencyjny premium lub enterprise." license = "Konfiguracja licencji" +noInput = "Podaj klucz licencyjny lub plik" [admin.settings.premium.licenseKey] toggle = "Masz klucz licencyjny lub plik certyfikatu?" @@ -4511,6 +4535,25 @@ line1 = "Nadpisania bieżącego klucza licencyjnego nie można cofnąć." line2 = "Poprzednia licencja zostanie trwale utracona, jeśli nie masz jej kopii zapasowej." line3 = "Ważne: przechowuj klucze licencyjne prywatnie i bezpiecznie. Nigdy nie udostępniaj ich publicznie." +[admin.settings.premium.inputMethod] +text = "Klucz licencyjny" +file = "Plik certyfikatu" + +[admin.settings.premium.file] +label = "Plik certyfikatu licencji" +description = "Prześlij swój plik licencji .lic lub .cert z zakupów offline" +choose = "Wybierz plik licencji" +selected = "Wybrano: {{filename}} ({{size}})" +successMessage = "Plik licencji przesłano i pomyślnie aktywowano. Ponowne uruchomienie nie jest wymagane." + +[admin.settings.premium.currentLicense] +title = "Aktywna licencja" +file = "Źródło: plik licencji ({{path}})" +key = "Źródło: klucz licencyjny" +type = "Typ: {{type}}" +noInput = "Podaj klucz licencyjny lub prześlij plik certyfikatu" +success = "Sukces" + [admin.settings.premium.enabled] label = "Włącz funkcje premium" description = "Włącz weryfikację klucza licencyjnego dla funkcji pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} wybrane" download = "Pobierz" delete = "usuń" unsupported = "Nieobsługiwane" +active = "Aktywny" addToUpload = "Dodaj do przesyłania" +closeFile = "Zamknij plik" deleteAll = "Usuń wszystko" loadingFiles = "Ładowanie plików..." noFiles = "Brak dostępnych plików" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Wymagany jest co najmniej jeden adres e‑mail" submit = "Wyślij zaproszenia" success = "Pomyślnie zaproszono użytkowników" -partialSuccess = "Niektóre zaproszenia nie powiodły się" +partialFailure = "Niektóre zaproszenia nie powiodły się" allFailed = "Nie udało się zaprosić użytkowników" error = "Nie udało się wysłać zaproszeń" @@ -5797,6 +5842,13 @@ submit = "Zaloguj" signInWith = "Zaloguj przez" oauthPending = "Otwieranie przeglądarki do uwierzytelnienia..." orContinueWith = "Lub kontynuuj e‑mailem" +serverRequirement = "Uwaga: Na serwerze musi być włączone logowanie." +showInstructions = "Jak włączyć?" +hideInstructions = "Ukryj instrukcje" +instructions = "Aby włączyć logowanie na swoim serwerze Stirling PDF:" +instructionsEnvVar = "Ustaw zmienną środowiskową:" +instructionsOrYml = "Lub w settings.yml:" +instructionsRestart = "Następnie uruchom ponownie serwer, aby zmiany zaczęły obowiązywać." [setup.login.username] label = "Nazwa użytkownika" @@ -5840,7 +5892,7 @@ paragraph = "Strona akapitowa" sparse = "Rzadki tekst" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automatycznie" paragraph = "Akapit" singleLine = "Pojedyncza linia" diff --git a/frontend/public/locales/pt-BR/translation.toml b/frontend/public/locales/pt-BR/translation.toml index 76dff8f2d..baaa4215b 100644 --- a/frontend/public/locales/pt-BR/translation.toml +++ b/frontend/public/locales/pt-BR/translation.toml @@ -131,7 +131,7 @@ unsupported = "Não suportado" [toolPanel] placeholder = "Escolha uma ferramenta para começar" -alpha = "Alpha" +alpha = "Alfa" premiumFeature = "Recurso premium:" comingSoon = "Em breve:" @@ -163,6 +163,11 @@ unfavorite = "Remover dos favoritos" fullscreen = "Alternar para modo tela cheia" sidebar = "Alternar para modo barra lateral" +[backendStartup] +notFoundTitle = "Backend não encontrado" +retry = "Tentar novamente" +unreachable = "No momento, o aplicativo não consegue se conectar ao backend. Verifique o status do backend e a conectividade de rede e tente novamente." + [zipWarning] title = "Arquivo ZIP grande" message = "Este ZIP contém {{count}} arquivos. Extrair mesmo assim?" @@ -912,6 +917,9 @@ desc = "Crie fluxos de trabalho de várias etapas encadeando ações de PDF. Ide desc = "Sobrepor um PDF sobre outro" title = "Sobrepor PDFs" +[home.pdfTextEditor] +title = "Editor de Texto em PDF" +desc = "Edite texto e imagens existentes em PDFs" [home.addText] tags = "texto,anotação,rótulo" @@ -1217,7 +1225,7 @@ odtExt = "Texto OpenDocument (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "Apresentação OpenDocument (.odp)" txtExt = "Texto simples (.txt)" -rtfExt = "Rich Text Format (.rtf)" +rtfExt = "Formato Rich Text (.rtf)" selectedFiles = "Arquivos selecionados" noFileSelected = "Nenhum arquivo selecionado. Use o painel de arquivos para adicionar arquivos." convertFiles = "Converter arquivos" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Assinatura desenhada" defaultImageLabel = "Assinatura enviada" defaultTextLabel = "Assinatura digitada" saveButton = "Salvar assinatura" +savePersonal = "Salvar pessoal" +saveShared = "Salvar compartilhado" saveUnavailable = "Crie uma assinatura primeiro para salvá-la." noChanges = "A assinatura atual já está salva." +tempStorageTitle = "Armazenamento temporário do navegador" +tempStorageDescription = "As assinaturas são armazenadas apenas no seu navegador. Elas serão perdidas se você limpar os dados do navegador ou trocar de navegador." +personalHeading = "Assinaturas pessoais" +sharedHeading = "Assinaturas compartilhadas" +personalDescription = "Somente você pode ver essas assinaturas." +sharedDescription = "Todos os usuários podem ver e usar essas assinaturas." [sign.saved.type] canvas = "Desenho" @@ -3438,6 +3454,9 @@ signinTitle = "Por favor, inicie a sessão" ssoSignIn = "Iniciar sessão através de login único (SSO)" oAuth2AutoCreateDisabled = "Auto-Criar Usuário OAUTH2 Desativado" oAuth2AdminBlockedUser = "O registro ou login de usuários não registrados está atualmente bloqueado. Entre em contato com o administrador." +oAuth2RequiresLicense = "O login via OAuth/SSO requer uma licença paga (Server ou Enterprise). Entre em contato com o administrador para atualizar seu plano." +saml2RequiresLicense = "O login via SAML requer uma licença paga (Server ou Enterprise). Entre em contato com o administrador para atualizar seu plano." +maxUsersReached = "Número máximo de usuários atingido para sua licença atual. Entre em contato com o administrador para atualizar seu plano ou adicionar mais assentos." oauth2RequestNotFound = "Solicitação de autorização não encontrada" oauth2InvalidUserInfoResponse = "Resposta de informação de usuário inválida" oauth2invalidRequest = "Requisição Inválida" @@ -3846,14 +3865,17 @@ fitToWidth = "Ajustar à largura" actualSize = "Tamanho real" [viewer] +cannotPreviewFile = "Não é possível visualizar o arquivo" +dualPageView = "Visualização de duas páginas" firstPage = "Primeira página" lastPage = "Última página" -previousPage = "Página anterior" nextPage = "Próxima página" +onlyPdfSupported = "O visualizador oferece suporte apenas a arquivos PDF. Este arquivo parece estar em um formato diferente." +previousPage = "Página anterior" +singlePageView = "Visualização de página única" +unknownFile = "Arquivo desconhecido" zoomIn = "Ampliar" zoomOut = "Reduzir" -singlePageView = "Visualização de página única" -dualPageView = "Visualização de duas páginas" [rightRail] closeSelected = "Fechar arquivos selecionados" @@ -3877,6 +3899,7 @@ toggleSidebar = "Alternar barra lateral" exportSelected = "Exportar páginas selecionadas" toggleAnnotations = "Alternar visibilidade das anotações" annotationMode = "Alternar modo de anotação" +print = "Imprimir PDF" draw = "Desenhar" save = "Salvar" saveChanges = "Salvar alterações" @@ -3925,7 +3948,7 @@ files = "Arquivos" activity = "Ativ." help = "Ajuda" account = "Conta" -config = "Config" +config = "Configurações" settings = "Ajustes" adminSettings = "Ajustes admin" allTools = "Ferram." @@ -4153,7 +4176,7 @@ description = "Rastrear ações do usuário e eventos do sistema para conformida [admin.settings.security.audit.level] label = "Nível de auditoria" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=DESLIGADO, 1=BÁSICO, 2=PADRÃO, 3=DETALHADO" [admin.settings.security.audit.retentionDays] label = "Retenção de auditoria (dias)" @@ -4235,11 +4258,11 @@ label = "URL do emissor" description = "A URL do emissor do provedor OAuth2" [admin.settings.connections.oauth2.clientId] -label = "Client ID" +label = "ID do cliente" description = "O Client ID do OAuth2 do seu provedor" [admin.settings.connections.oauth2.clientSecret] -label = "Client Secret" +label = "Segredo do cliente" description = "O Client Secret do OAuth2 do seu provedor" [admin.settings.connections.oauth2.useAsUsername] @@ -4494,6 +4517,7 @@ description = "URL ou nome de arquivo do impressum (exigido em algumas jurisdiç title = "Premium e Enterprise" description = "Configurar sua chave de licença premium ou enterprise." license = "Configuração de licença" +noInput = "Forneça uma chave ou arquivo de licença" [admin.settings.premium.licenseKey] toggle = "Tem uma chave de licença ou arquivo de certificado?" @@ -4511,6 +4535,25 @@ line1 = "Substituir sua chave de licença atual não pode ser desfeito." line2 = "Sua licença anterior será perdida permanentemente, a menos que você tenha um backup em outro lugar." line3 = "Importante: mantenha chaves de licença privadas e seguras. Nunca as compartilhe publicamente." +[admin.settings.premium.inputMethod] +text = "Chave de licença" +file = "Arquivo de certificado" + +[admin.settings.premium.file] +label = "Arquivo de certificado de licença" +description = "Faça upload do seu arquivo de licença .lic ou .cert de compras offline" +choose = "Escolher arquivo de licença" +selected = "Selecionado: {{filename}} ({{size}})" +successMessage = "Arquivo de licença enviado e ativado com sucesso. Não é necessário reiniciar." + +[admin.settings.premium.currentLicense] +title = "Licença ativa" +file = "Origem: arquivo de licença ({{path}})" +key = "Origem: chave de licença" +type = "Tipo: {{type}}" +noInput = "Forneça uma chave de licença ou envie um arquivo de certificado" +success = "Sucesso" + [admin.settings.premium.enabled] label = "Habilitar recursos Premium" description = "Habilitar verificação de chave de licença para recursos pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} selecionado(s)" download = "Baixar (JSON)" delete = "Apagar" unsupported = "Não suportado" +active = "Ativo" addToUpload = "Adicionar ao upload" +closeFile = "Fechar arquivo" deleteAll = "Excluir tudo" loadingFiles = "Carregando arquivos..." noFiles = "Nenhum arquivo disponível" @@ -5178,7 +5223,7 @@ active = "Ativo" disabled = "Desativado" activeSession = "Sessão ativa" member = "Membro" -admin = "Admin" +admin = "Administrador" editRole = "Editar função" enable = "Ativar" disable = "Desativar" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Ao menos um endereço de email é obrigatório" submit = "Enviar convites" success = "usuário(s) convidado(s) com sucesso" -partialSuccess = "Alguns convites falharam" +partialFailure = "Alguns convites falharam" allFailed = "Falha ao convidar usuários" error = "Falha ao enviar convites" @@ -5797,13 +5842,20 @@ submit = "Login" signInWith = "Entrar com" oauthPending = "Abrindo o navegador para autenticação..." orContinueWith = "Ou continue com e-mail" +serverRequirement = "Observação: o servidor deve ter o login ativado." +showInstructions = "Como ativar?" +hideInstructions = "Ocultar instruções" +instructions = "Para ativar o login no seu servidor Stirling PDF:" +instructionsEnvVar = "Defina a variável de ambiente:" +instructionsOrYml = "Ou em settings.yml:" +instructionsRestart = "Em seguida, reinicie o servidor para que as alterações entrem em vigor." [setup.login.username] label = "Usuário" placeholder = "Digite seu usuário" [setup.login.email] -label = "Email" +label = "E-mail" placeholder = "Digite seu e-mail" [setup.login.password] @@ -5840,7 +5892,7 @@ paragraph = "Página de parágrafos" sparse = "Texto esparso" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automático" paragraph = "Parágrafo" singleLine = "Linha única" diff --git a/frontend/public/locales/pt-PT/translation.toml b/frontend/public/locales/pt-PT/translation.toml index e530345e6..0691f5f35 100644 --- a/frontend/public/locales/pt-PT/translation.toml +++ b/frontend/public/locales/pt-PT/translation.toml @@ -131,7 +131,7 @@ unsupported = "Não suportado" [toolPanel] placeholder = "Escolha uma ferramenta para começar" -alpha = "Alpha" +alpha = "Alfa" premiumFeature = "Funcionalidade premium:" comingSoon = "Em breve:" @@ -163,6 +163,11 @@ unfavorite = "Remover dos favoritos" fullscreen = "Mudar para modo de ecrã inteiro" sidebar = "Mudar para modo de barra lateral" +[backendStartup] +notFoundTitle = "Backend não encontrado" +retry = "Tentar novamente" +unreachable = "A aplicação não consegue ligar-se ao backend neste momento. Verifique o estado do backend e a conectividade de rede e tente novamente." + [zipWarning] title = "Ficheiro ZIP grande" message = "Este ZIP contém {{count}} ficheiros. Extrair mesmo assim?" @@ -364,12 +369,12 @@ usageAnalytics = "Análise de utilização" [settings.policiesPrivacy] title = "Políticas e Privacidade" -legal = "Legal" +legal = "Jurídico" privacy = "Privacidade" [settings.developer] title = "Programador" -apiKeys = "API Keys" +apiKeys = "Chaves de API" [settings.tooltips] enableLoginFirst = "Ative primeiro o modo de login" @@ -912,6 +917,9 @@ desc = "Crie fluxos de trabalho de vários passos encadeando ações de PDF. Ide desc = "Sobrepõe PDFs em cima de outro PDF" title = "Sobrepor PDFs" +[home.pdfTextEditor] +title = "Editor de texto de PDF" +desc = "Edite texto e imagens existentes dentro de PDFs" [home.addText] tags = "texto,anotação,etiqueta" @@ -1217,7 +1225,7 @@ odtExt = "Texto OpenDocument (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "Apresentação OpenDocument (.odp)" txtExt = "Texto simples (.txt)" -rtfExt = "Rich Text Format (.rtf)" +rtfExt = "Formato de Texto Enriquecido (.rtf)" selectedFiles = "Ficheiros selecionados" noFileSelected = "Nenhum ficheiro selecionado. Use o painel de ficheiros para adicionar ficheiros." convertFiles = "Converter ficheiros" @@ -1360,7 +1368,7 @@ title = "Adicionar Marca de Água" desc = "Adicionar marcas de água de texto ou imagem a ficheiros PDF" completed = "Marca de água adicionada" submit = "Adicionar Marca de Água" -filenamePrefix = "watermarked" +filenamePrefix = "com-marca-de-água" [watermark.error] failed = "Ocorreu um erro ao adicionar a marca de água ao PDF." @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Assinatura desenhada" defaultImageLabel = "Assinatura carregada" defaultTextLabel = "Assinatura digitada" saveButton = "Guardar assinatura" +savePersonal = "Guardar como pessoal" +saveShared = "Guardar como partilhada" saveUnavailable = "Crie primeiro uma assinatura para a guardar." noChanges = "A assinatura atual já está guardada." +tempStorageTitle = "Armazenamento temporário do navegador" +tempStorageDescription = "As assinaturas são armazenadas apenas no seu navegador. Serão perdidas se limpar os dados do navegador ou mudar de navegador." +personalHeading = "Assinaturas pessoais" +sharedHeading = "Assinaturas partilhadas" +personalDescription = "Apenas você pode ver estas assinaturas." +sharedDescription = "Todos os utilizadores podem ver e usar estas assinaturas." [sign.saved.type] canvas = "Desenho" @@ -2841,7 +2857,7 @@ label = "Fator de escala" [adjustPageScale.pageSize] label = "Tamanho da página de destino" keep = "Manter tamanho original" -letter = "Letter" +letter = "Carta" legal = "Legal" [adjustPageScale.error] @@ -3438,6 +3454,9 @@ signinTitle = "Por favor inicie sessão" ssoSignIn = "Iniciar sessão via Single Sign-On" oAuth2AutoCreateDisabled = "Criação Automática de Utilizador OAUTH2 Desativada" oAuth2AdminBlockedUser = "O registo ou login de utilizadores não registados está atualmente bloqueado. Por favor contacte o administrador." +oAuth2RequiresLicense = "O início de sessão via OAuth/SSO requer uma licença paga (Server ou Enterprise). Contacte o administrador para atualizar o seu plano." +saml2RequiresLicense = "O início de sessão SAML requer uma licença paga (Server ou Enterprise). Contacte o administrador para atualizar o seu plano." +maxUsersReached = "Foi atingido o número máximo de utilizadores da sua licença atual. Contacte o administrador para atualizar o seu plano ou adicionar mais lugares." oauth2RequestNotFound = "Pedido de autorização não encontrado" oauth2InvalidUserInfoResponse = "Resposta de Informação de Utilizador Inválida" oauth2invalidRequest = "Pedido Inválido" @@ -3846,14 +3865,17 @@ fitToWidth = "Ajustar à largura" actualSize = "Tamanho real" [viewer] +cannotPreviewFile = "Não é possível pré-visualizar o ficheiro" +dualPageView = "Vista de duas páginas" firstPage = "Primeira página" lastPage = "Última página" -previousPage = "Página anterior" nextPage = "Página seguinte" +onlyPdfSupported = "O visualizador só suporta ficheiros PDF. Este ficheiro parece ter um formato diferente." +previousPage = "Página anterior" +singlePageView = "Vista de página única" +unknownFile = "Ficheiro desconhecido" zoomIn = "Ampliar" zoomOut = "Reduzir" -singlePageView = "Vista de página única" -dualPageView = "Vista de duas páginas" [rightRail] closeSelected = "Fechar ficheiros selecionados" @@ -3877,6 +3899,7 @@ toggleSidebar = "Alternar barra lateral" exportSelected = "Exportar páginas selecionadas" toggleAnnotations = "Alternar visibilidade das anotações" annotationMode = "Alternar modo de anotação" +print = "Imprimir PDF" draw = "Desenhar" save = "Guardar" saveChanges = "Guardar alterações" @@ -4494,6 +4517,7 @@ description = "URL ou nome de ficheiro para o impressum (obrigatório em algumas title = "Premium e Enterprise" description = "Configurar a sua chave de licença premium ou enterprise." license = "Configuração de licença" +noInput = "Forneça uma chave ou ficheiro de licença" [admin.settings.premium.licenseKey] toggle = "Tem uma chave de licença ou ficheiro de certificado?" @@ -4511,6 +4535,25 @@ line1 = "Sobrescrever a sua chave de licença atual não pode ser anulado." line2 = "A sua licença anterior será perdida permanentemente, a menos que a tenha guardado noutro local." line3 = "Importante: mantenha as chaves de licença privadas e seguras. Nunca as partilhe publicamente." +[admin.settings.premium.inputMethod] +text = "Chave de licença" +file = "Ficheiro de certificado" + +[admin.settings.premium.file] +label = "Ficheiro de certificado de licença" +description = "Carregue o seu ficheiro de licença .lic ou .cert de compras offline" +choose = "Escolher ficheiro de licença" +selected = "Selecionado: {{filename}} ({{size}})" +successMessage = "Ficheiro de licença carregado e ativado com sucesso. Não é necessário reiniciar." + +[admin.settings.premium.currentLicense] +title = "Licença ativa" +file = "Origem: ficheiro de licença ({{path}})" +key = "Origem: chave de licença" +type = "Tipo: {{type}}" +noInput = "Forneça uma chave de licença ou carregue um ficheiro de certificado" +success = "Sucesso" + [admin.settings.premium.enabled] label = "Ativar funcionalidades premium" description = "Ativar verificações de chave de licença para funcionalidades pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} selecionado(s)" download = "Transferir" delete = "Eliminar" unsupported = "Não suportado" +active = "Ativo" addToUpload = "Adicionar ao carregamento" +closeFile = "Fechar ficheiro" deleteAll = "Eliminar tudo" loadingFiles = "A carregar ficheiros..." noFiles = "Não há ficheiros disponíveis" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "É necessário pelo menos um endereço de email" submit = "Enviar convites" success = "utilizador(es) convidado(s) com sucesso" -partialSuccess = "Alguns convites falharam" +partialFailure = "Alguns convites falharam" allFailed = "Falha ao convidar utilizadores" error = "Falha ao enviar convites" @@ -5282,7 +5327,7 @@ submit = "Gerar link de convite" [workspace.people.inviteMode] username = "Nome de utilizador" email = "Email" -link = "Link" +link = "Ligação" emailDisabled = "Convites por email requerem configuração de SMTP e mail.enableInvites=true nas definições" [workspace.people.license] @@ -5797,6 +5842,13 @@ submit = "Iniciar sessão" signInWith = "Iniciar sessão com" oauthPending = "A abrir o navegador para autenticação..." orContinueWith = "Ou continuar com email" +serverRequirement = "Nota: O servidor deve ter o início de sessão ativado." +showInstructions = "Como ativar?" +hideInstructions = "Ocultar instruções" +instructions = "Para ativar o início de sessão no seu servidor Stirling PDF:" +instructionsEnvVar = "Defina a variável de ambiente:" +instructionsOrYml = "Ou em settings.yml:" +instructionsRestart = "Em seguida, reinicie o servidor para que as alterações tenham efeito." [setup.login.username] label = "Nome de utilizador" @@ -5840,7 +5892,7 @@ paragraph = "Página de parágrafos" sparse = "Texto disperso" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automático" paragraph = "Parágrafo" singleLine = "Linha única" @@ -5932,7 +5984,7 @@ warnings = "Avisos" suggestions = "Notas" currentPageFonts = "Fontes nesta página" allFonts = "Todas as fontes" -fallback = "fallback" +fallback = "alternativa" missing = "em falta" perfectMessage = "Todas as fontes podem ser reproduzidas na perfeição." warningMessage = "Algumas fontes podem não ser renderizadas corretamente." diff --git a/frontend/public/locales/ro-RO/translation.toml b/frontend/public/locales/ro-RO/translation.toml index 57c2ce481..c323b3354 100644 --- a/frontend/public/locales/ro-RO/translation.toml +++ b/frontend/public/locales/ro-RO/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Eliminați din favorite" fullscreen = "Comutați la modul ecran complet" sidebar = "Comutați la modul bară laterală" +[backendStartup] +notFoundTitle = "Backend negăsit" +retry = "Reîncearcă" +unreachable = "Aplicația nu se poate conecta în prezent la backend. Verificați starea backend-ului și conexiunea la rețea, apoi încercați din nou." + [zipWarning] title = "Fișier ZIP mare" message = "Acest ZIP conține {{count}} fișiere. Extrageți oricum?" @@ -912,6 +917,9 @@ desc = "Construiți fluxuri cu mai mulți pași legând acțiuni PDF. Ideal pent desc = "Suprapune PDF-uri peste alt PDF" title = "Suprapune PDF-uri" +[home.pdfTextEditor] +title = "Editor de text PDF" +desc = "Editați textul și imaginile existente în PDF-uri" [home.addText] tags = "text,anotare,etichetă" @@ -1213,11 +1221,11 @@ pdfaDigitalSignatureWarning = "PDF-ul conține o semnătură digitală. Aceasta fileFormat = "Format fișier" wordDoc = "Document Word" wordDocExt = "Document Word (.docx)" -odtExt = "OpenDocument Text (.odt)" +odtExt = "Text OpenDocument (.odt)" pptExt = "PowerPoint (.pptx)" -odpExt = "OpenDocument Presentation (.odp)" +odpExt = "Prezentare OpenDocument (.odp)" txtExt = "Text simplu (.txt)" -rtfExt = "Rich Text Format (.rtf)" +rtfExt = "Format Rich Text (.rtf)" selectedFiles = "Fișiere selectate" noFileSelected = "Niciun fișier selectat. Folosiți panoul de fișiere pentru a adăuga fișiere." convertFiles = "Convertiți fișiere" @@ -1395,7 +1403,7 @@ height = "Spațiere pe înălțime" width = "Spațiere pe lățime" [watermark.alphabet] -roman = "Roman/Latin" +roman = "Romano/Latin" arabic = "Arabă" japanese = "Japoneză" korean = "Coreeană" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Semnătură desenată" defaultImageLabel = "Semnătură încărcată" defaultTextLabel = "Semnătură tastată" saveButton = "Salvează semnătura" +savePersonal = "Salvați ca personal" +saveShared = "Salvați ca partajat" saveUnavailable = "Creează mai întâi o semnătură pentru a o salva." noChanges = "Semnătura curentă este deja salvată." +tempStorageTitle = "Stocare temporară în browser" +tempStorageDescription = "Semnăturile sunt stocate doar în browserul dvs. Vor fi pierdute dacă ștergeți datele browserului sau schimbați browserul." +personalHeading = "Semnături personale" +sharedHeading = "Semnături partajate" +personalDescription = "Doar dvs. puteți vedea aceste semnături." +sharedDescription = "Toți utilizatorii pot vedea și utiliza aceste semnături." [sign.saved.type] canvas = "Desen" @@ -3438,6 +3454,9 @@ signinTitle = "Te rugăm să te autentifici" ssoSignIn = "Conectare prin conectare unică" oAuth2AutoCreateDisabled = "OAUTH2 Creare automată utilizator dezactivată" oAuth2AdminBlockedUser = "Înregistrarea sau conectarea utilizatorilor neînregistrați este în prezent blocată. Te rugăm să contactezi administratorul." +oAuth2RequiresLicense = "Autentificarea OAuth/SSO necesită o licență plătită (Server sau Enterprise). Contactați administratorul pentru a vă actualiza planul." +saml2RequiresLicense = "Autentificarea SAML necesită o licență plătită (Server sau Enterprise). Contactați administratorul pentru a vă actualiza planul." +maxUsersReached = "Numărul maxim de utilizatori a fost atins pentru licența curentă. Contactați administratorul pentru a vă actualiza planul sau pentru a adăuga mai multe locuri." oauth2RequestNotFound = "Cererea de autorizare nu a fost găsită" oauth2InvalidUserInfoResponse = "Răspuns Invalid la Informațiile Utilizatorului" oauth2invalidRequest = "Cerere Invalidă" @@ -3846,14 +3865,17 @@ fitToWidth = "Potriviți la lățime" actualSize = "Dimensiune reală" [viewer] +cannotPreviewFile = "Nu se poate previzualiza fișierul" +dualPageView = "Vizualizare cu două pagini" firstPage = "Prima pagină" lastPage = "Ultima pagină" -previousPage = "Pagina anterioară" nextPage = "Pagina următoare" +onlyPdfSupported = "Vizualizatorul acceptă doar fișiere PDF. Acest fișier pare a fi într-un format diferit." +previousPage = "Pagina anterioară" +singlePageView = "Vizualizare cu o singură pagină" +unknownFile = "Fișier necunoscut" zoomIn = "Măriți" zoomOut = "Micșorați" -singlePageView = "Vizualizare cu o singură pagină" -dualPageView = "Vizualizare cu două pagini" [rightRail] closeSelected = "Închideți fișierele selectate" @@ -3877,6 +3899,7 @@ toggleSidebar = "Comutați bara laterală" exportSelected = "Exportați paginile selectate" toggleAnnotations = "Comutați vizibilitatea adnotărilor" annotationMode = "Comutați modul de adnotare" +print = "Imprimați PDF" draw = "Desenați" save = "Salvați" saveChanges = "Salvați modificările" @@ -4494,6 +4517,7 @@ description = "URL sau nume de fișier către impressum (necesar în unele juris title = "Premium și Enterprise" description = "Configurați cheia de licență premium sau enterprise." license = "Configurare licență" +noInput = "Vă rugăm să furnizați o cheie sau un fișier de licență" [admin.settings.premium.licenseKey] toggle = "Ai o cheie de licență sau un fișier certificat?" @@ -4511,6 +4535,25 @@ line1 = "Suprascrierea cheii de licență curente nu poate fi anulată." line2 = "Licența anterioară va fi pierdută definitiv dacă nu ai o copie de rezervă." line3 = "Important: Păstrează cheile de licență private și în siguranță. Nu le distribui public." +[admin.settings.premium.inputMethod] +text = "Cheie de licență" +file = "Fișier de certificat" + +[admin.settings.premium.file] +label = "Fișier certificat de licență" +description = "Încărcați fișierul de licență .lic sau .cert din achizițiile offline" +choose = "Alegeți fișierul de licență" +selected = "Selectat: {{filename}} ({{size}})" +successMessage = "Fișierul de licență a fost încărcat și activat cu succes. Nu este necesară repornirea." + +[admin.settings.premium.currentLicense] +title = "Licență activă" +file = "Sursă: Fișier de licență ({{path}})" +key = "Sursă: Cheie de licență" +type = "Tip: {{type}}" +noInput = "Vă rugăm să furnizați o cheie de licență sau să încărcați un fișier de certificat" +success = "Succes" + [admin.settings.premium.enabled] label = "Activează funcțiile Premium" description = "Activează verificările cheii de licență pentru funcțiile pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} selectate" download = "Descarcă" delete = "Șterge" unsupported = "Nesuportat" +active = "Activ" addToUpload = "Adăugați la încărcare" +closeFile = "Închide fișierul" deleteAll = "Ștergeți tot" loadingFiles = "Se încarcă fișierele..." noFiles = "Nu există fișiere disponibile" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Este necesară cel puțin o adresă de email" submit = "Trimiteți invitații" success = "utilizator(i) invitați cu succes" -partialSuccess = "Unele invitații au eșuat" +partialFailure = "Unele invitații au eșuat" allFailed = "Invitarea utilizatorilor a eșuat" error = "Trimiterea invitațiilor a eșuat" @@ -5380,7 +5425,7 @@ submit = "Schimbă echipa" currency = "Monedă" popular = "Popular" current = "Plan curent" -upgrade = "Upgrade" +upgrade = "Actualizează" contact = "Contactează-ne" customPricing = "Personalizat" showComparison = "Compară toate funcțiile" @@ -5797,6 +5842,13 @@ submit = "Autentificare" signInWith = "Autentifică-te cu" oauthPending = "Se deschide browserul pentru autentificare..." orContinueWith = "Sau continuă cu email" +serverRequirement = "Notă: Serverul trebuie să aibă autentificarea activată." +showInstructions = "Cum se activează?" +hideInstructions = "Ascunde instrucțiunile" +instructions = "Pentru a activa autentificarea pe serverul dvs. Stirling PDF:" +instructionsEnvVar = "Setați variabila de mediu:" +instructionsOrYml = "Sau în settings.yml:" +instructionsRestart = "Apoi reporniți serverul pentru ca modificările să intre în vigoare." [setup.login.username] label = "Utilizator" diff --git a/frontend/public/locales/ru-RU/translation.toml b/frontend/public/locales/ru-RU/translation.toml index 359bb5783..b72009fa6 100644 --- a/frontend/public/locales/ru-RU/translation.toml +++ b/frontend/public/locales/ru-RU/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Удалить из избранного" fullscreen = "Переключиться в полноэкранный режим" sidebar = "Переключиться в режим боковой панели" +[backendStartup] +notFoundTitle = "Серверная часть не найдена" +retry = "Повторить" +unreachable = "Приложение сейчас не может подключиться к серверной части. Проверьте состояние серверной части и подключение к сети, затем повторите попытку." + [zipWarning] title = "Большой ZIP-файл" message = "Этот ZIP содержит {{count}} файлов. Все равно извлечь?" @@ -912,6 +917,9 @@ desc = "Создавайте многошаговые процессы, связ desc = "Наложить один PDF поверх другого" title = "Наложение PDF" +[home.pdfTextEditor] +title = "Редактор текста PDF" +desc = "Редактируйте существующий текст и изображения внутри PDF-файлов" [home.addText] tags = "текст,аннотация,ярлык" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Рисованная подпись" defaultImageLabel = "Загруженная подпись" defaultTextLabel = "Введённая подпись" saveButton = "Сохранить подпись" +savePersonal = "Сохранить как личную" +saveShared = "Сохранить как общую" saveUnavailable = "Сначала создайте подпись, чтобы сохранить её." noChanges = "Текущая подпись уже сохранена." +tempStorageTitle = "Временное хранилище браузера" +tempStorageDescription = "Подписи сохраняются только в вашем браузере. Они будут потеряны, если вы очистите данные браузера или смените браузер." +personalHeading = "Личные подписи" +sharedHeading = "Общие подписи" +personalDescription = "Эти подписи видны только вам." +sharedDescription = "Все пользователи могут видеть и использовать эти подписи." [sign.saved.type] canvas = "Рисунок" @@ -3438,6 +3454,9 @@ signinTitle = "Пожалуйста, войдите" ssoSignIn = "Вход через единый вход" oAuth2AutoCreateDisabled = "Автоматическое создание пользователей OAuth2 отключено" oAuth2AdminBlockedUser = "Регистрация или вход незарегистрированных пользователей в настоящее время заблокированы. Обратитесь к администратору." +oAuth2RequiresLicense = "Вход через OAuth/SSO требует платную лицензию (Server или Enterprise). Пожалуйста, свяжитесь с администратором, чтобы обновить ваш план." +saml2RequiresLicense = "Вход через SAML требует платную лицензию (Server или Enterprise). Пожалуйста, свяжитесь с администратором, чтобы обновить ваш план." +maxUsersReached = "Достигнуто максимальное количество пользователей для вашей текущей лицензии. Пожалуйста, свяжитесь с администратором, чтобы обновить ваш план или добавить места." oauth2RequestNotFound = "Запрос авторизации не найден" oauth2InvalidUserInfoResponse = "Недействительный ответ с информацией о пользователе" oauth2invalidRequest = "Недействительный запрос" @@ -3846,14 +3865,17 @@ fitToWidth = "По ширине" actualSize = "Фактический размер" [viewer] +cannotPreviewFile = "Не удаётся просмотреть файл" +dualPageView = "Двухстраничный вид" firstPage = "Первая страница" lastPage = "Последняя страница" -previousPage = "Предыдущая страница" nextPage = "Следующая страница" +onlyPdfSupported = "Просмотрщик поддерживает только PDF-файлы. Похоже, этот файл другого формата." +previousPage = "Предыдущая страница" +singlePageView = "Одностраничный вид" +unknownFile = "Неизвестный файл" zoomIn = "Увеличить" zoomOut = "Уменьшить" -singlePageView = "Одностраничный вид" -dualPageView = "Двухстраничный вид" [rightRail] closeSelected = "Закрыть выбранные файлы" @@ -3877,6 +3899,7 @@ toggleSidebar = "Показать/скрыть боковую панель" exportSelected = "Экспортировать выбранные страницы" toggleAnnotations = "Показать/скрыть аннотации" annotationMode = "Переключить режим аннотаций" +print = "Печать PDF" draw = "Рисовать" save = "Сохранить" saveChanges = "Сохранить изменения" @@ -4487,13 +4510,14 @@ label = "Политика cookie" description = "URL или имя файла для политики cookie" [admin.settings.legal.impressum] -label = "Impressum" +label = "Юридическая информация" description = "URL или имя файла для impressum (требуется в некоторых юрисдикциях)" [admin.settings.premium] title = "Премиум и Enterprise" description = "Настройте ключ лицензии премиум или enterprise." license = "Конфигурация лицензии" +noInput = "Укажите лицензионный ключ или файл" [admin.settings.premium.licenseKey] toggle = "Есть лицензионный ключ или файл сертификата?" @@ -4511,6 +4535,25 @@ line1 = "Перезапись текущего лицензионного клю line2 = "Предыдущая лицензия будет безвозвратно утеряна, если вы не сделали резервную копию где‑то ещё." line3 = "Важно: храните лицензионные ключи в секрете и безопасности. Никогда не публикуйте их." +[admin.settings.premium.inputMethod] +text = "Лицензионный ключ" +file = "Файл сертификата" + +[admin.settings.premium.file] +label = "Файл лицензионного сертификата" +description = "Загрузите файл лицензии .lic или .cert из офлайн-покупки" +choose = "Выберите файл лицензии" +selected = "Выбрано: {{filename}} ({{size}})" +successMessage = "Файл лицензии успешно загружен и активирован. Перезапуск не требуется." + +[admin.settings.premium.currentLicense] +title = "Активная лицензия" +file = "Источник: файл лицензии ({{path}})" +key = "Источник: лицензионный ключ" +type = "Тип: {{type}}" +noInput = "Укажите лицензионный ключ или загрузите файл сертификата" +success = "Успешно" + [admin.settings.premium.enabled] label = "Включить премиум-функции" description = "Включить проверку лицензии для pro/enterprise функций" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} выбрано" download = "Скачать" delete = "Удалить" unsupported = "Не поддерживается" +active = "Активный" addToUpload = "Добавить к загрузке" +closeFile = "Закрыть файл" deleteAll = "Удалить все" loadingFiles = "Загрузка файлов..." noFiles = "Нет доступных файлов" @@ -4964,7 +5009,7 @@ description = "Привяжите аккаунт, чтобы сохранить socialLogin = "Обновить через соцсеть" linkWith = "Привязать к" emailPassword = "или введите email и пароль" -email = "Email" +email = "Эл. почта" emailPlaceholder = "Введите ваш email" password = "Пароль (необязательно)" passwordPlaceholder = "Задайте пароль" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Требуется хотя бы один адрес email" submit = "Отправить приглашения" success = "Пользователи успешно приглашены" -partialSuccess = "Некоторые приглашения не отправлены" +partialFailure = "Некоторые приглашения не удалось отправить" allFailed = "Не удалось пригласить пользователей" error = "Не удалось отправить приглашения" @@ -5797,13 +5842,20 @@ submit = "Войти" signInWith = "Войти через" oauthPending = "Открываем браузер для аутентификации..." orContinueWith = "Или продолжить по email" +serverRequirement = "Примечание: на сервере должен быть включён вход в систему." +showInstructions = "Как включить?" +hideInstructions = "Скрыть инструкции" +instructions = "Чтобы включить вход в систему на вашем сервере Stirling PDF:" +instructionsEnvVar = "Установите переменную окружения:" +instructionsOrYml = "Или в settings.yml:" +instructionsRestart = "Затем перезапустите сервер, чтобы изменения вступили в силу." [setup.login.username] label = "Имя пользователя" placeholder = "Введите имя пользователя" [setup.login.email] -label = "Email" +label = "Эл. почта" placeholder = "Введите email" [setup.login.password] diff --git a/frontend/public/locales/sk-SK/translation.toml b/frontend/public/locales/sk-SK/translation.toml index 0b6633ff2..183112a67 100644 --- a/frontend/public/locales/sk-SK/translation.toml +++ b/frontend/public/locales/sk-SK/translation.toml @@ -99,7 +99,7 @@ visitGithub = "Navštíviť GitHub repozitár" donate = "Darovať" color = "Farba" sponsor = "Sponzorovať" -info = "Info" +info = "Informácie" pro = "Pro" page = "Strana" pages = "Strany" @@ -163,6 +163,11 @@ unfavorite = "Odstrániť z obľúbených" fullscreen = "Prepnúť na režim celej obrazovky" sidebar = "Prepnúť na režim bočného panela" +[backendStartup] +notFoundTitle = "Backend sa nenašiel" +retry = "Skúsiť znova" +unreachable = "Aplikácia sa momentálne nedokáže pripojiť k backendu. Overte stav backendu a sieťové pripojenie, potom to skúste znova." + [zipWarning] title = "Veľký ZIP súbor" message = "Tento ZIP obsahuje {{count}} súborov. Aj tak rozbaliť?" @@ -274,7 +279,7 @@ iAgreeToThe = "Súhlasím so všetkými" terms = "Podmienkami používania" accessibility = "Prístupnosť" cookie = "Zásady používania súborov cookie" -impressum = "Impressum" +impressum = "Impresum" showCookieBanner = "Predvoľby súborov cookie" [pipeline] @@ -513,7 +518,7 @@ syncToAccount = "Synchronizovať účet <- Prehliadač" [adminUserSettings] title = "Nastavenia kontroly používateľov" header = "Admin nastavenia kontroly používateľov" -admin = "Admin" +admin = "Administrátor" user = "Používateľ" addUser = "Pridať nového používateľa" deleteUser = "Odstrániť používateľa" @@ -912,6 +917,9 @@ desc = "Stavať viacstupňové pracovné postupy spájaním akcií PDF. Ideálne desc = "Prekrýva PDF súbory na iný PDF" title = "Prekrývanie PDF" +[home.pdfTextEditor] +title = "Editor textu PDF" +desc = "Upravujte existujúci text a obrázky v PDF" [home.addText] tags = "text,anotácia,štítok" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Kreslený podpis" defaultImageLabel = "Nahraný podpis" defaultTextLabel = "Napísaný podpis" saveButton = "Uložiť podpis" +savePersonal = "Uložiť osobné" +saveShared = "Uložiť zdieľané" saveUnavailable = "Najprv vytvorte podpis, aby ste ho mohli uložiť." noChanges = "Aktuálny podpis je už uložený." +tempStorageTitle = "Dočasné úložisko prehliadača" +tempStorageDescription = "Podpisy sú uložené iba vo vašom prehliadači. Pri vymazaní údajov prehliadača alebo pri zmene prehliadača sa stratia." +personalHeading = "Osobné podpisy" +sharedHeading = "Zdieľané podpisy" +personalDescription = "Tieto podpisy vidíte iba vy." +sharedDescription = "Všetci používatelia môžu tieto podpisy vidieť a používať." [sign.saved.type] canvas = "Kresba" @@ -3438,6 +3454,9 @@ signinTitle = "Prosím, prihláste sa" ssoSignIn = "Prihlásiť sa cez Single Sign-on" oAuth2AutoCreateDisabled = "Vytváranie používateľa cez OAUTH2 je zakázané" oAuth2AdminBlockedUser = "Registrácia alebo prihlasovanie neregistrovaných používateľov je momentálne blokované. Kontaktujte administrátora." +oAuth2RequiresLicense = "Prihlásenie cez OAuth/SSO vyžaduje platenú licenciu (Server alebo Enterprise). Obráťte sa na administrátora, aby aktualizoval váš plán." +saml2RequiresLicense = "Prihlásenie cez SAML vyžaduje platenú licenciu (Server alebo Enterprise). Obráťte sa na administrátora, aby aktualizoval váš plán." +maxUsersReached = "Bol dosiahnutý maximálny počet používateľov pre vašu aktuálnu licenciu. Obráťte sa na administrátora, aby aktualizoval váš plán alebo pridal ďalšie miesta." oauth2RequestNotFound = "Požiadavka na autorizáciu sa nenašla" oauth2InvalidUserInfoResponse = "Neplatná odpoveď User Info" oauth2invalidRequest = "Neplatná požiadavka" @@ -3771,7 +3790,7 @@ version = "Aktuálne vydanie" title = "Dokumentácia API" header = "Dokumentácia API" desc = "Zobraziť a testovať API endpointy Stirling PDF" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,dokumentácia,swagger,endpointy,vývoj" [cookieBanner.popUp] title = "Ako používame súbory cookie" @@ -3846,14 +3865,17 @@ fitToWidth = "Prispôsobiť šírke" actualSize = "Skutočná veľkosť" [viewer] +cannotPreviewFile = "Nedá sa zobraziť náhľad súboru" +dualPageView = "Dvojstranové zobrazenie" firstPage = "Prvá strana" lastPage = "Posledná strana" -previousPage = "Predchádzajúca strana" nextPage = "Nasledujúca strana" +onlyPdfSupported = "Prehliadač podporuje iba súbory PDF. Tento súbor sa zdá byť iného formátu." +previousPage = "Predchádzajúca strana" +singlePageView = "Zobrazenie jednej strany" +unknownFile = "Neznámy súbor" zoomIn = "Priblížiť" zoomOut = "Oddialiť" -singlePageView = "Zobrazenie jednej strany" -dualPageView = "Dvojstranové zobrazenie" [rightRail] closeSelected = "Zavrieť vybrané súbory" @@ -3877,6 +3899,7 @@ toggleSidebar = "Prepnúť bočný panel" exportSelected = "Exportovať vybrané strany" toggleAnnotations = "Prepnúť zobrazenie anotácií" annotationMode = "Prepnúť režim anotácií" +print = "Vytlačiť PDF" draw = "Kresliť" save = "Uložiť" saveChanges = "Uložiť zmeny" @@ -4487,13 +4510,14 @@ label = "Zásady používania súborov cookie" description = "URL alebo názov súboru so zásadami používania súborov cookie" [admin.settings.legal.impressum] -label = "Impressum" +label = "Impresum" description = "URL alebo názov súboru k Impressu (požadované v niektorých jurisdikciách)" [admin.settings.premium] title = "Premium a Enterprise" description = "Nakonfigurujte svoj Premium alebo Enterprise licenčný kľúč." license = "Konfigurácia licencie" +noInput = "Zadajte licenčný kľúč alebo súbor" [admin.settings.premium.licenseKey] toggle = "Máte licenčný kľúč alebo súbor certifikátu?" @@ -4511,6 +4535,25 @@ line1 = "Prepísanie aktuálneho licenčného kľúča nemožno vrátiť späť. line2 = "Vaša predchádzajúca licencia bude natrvalo stratená, pokiaľ ju nemáte zálohovanú inde." line3 = "Dôležité: Licenčné kľúče uchovávajte súkromné a v bezpečí. Nikdy ich nezdieľajte verejne." +[admin.settings.premium.inputMethod] +text = "Licenčný kľúč" +file = "Súbor certifikátu" + +[admin.settings.premium.file] +label = "Súbor licenčného certifikátu" +description = "Nahrajte svoj licenčný súbor .lic alebo .cert z offline nákupu" +choose = "Vybrať licenčný súbor" +selected = "Vybrané: {{filename}} ({{size}})" +successMessage = "Licenčný súbor bol úspešne nahraný a aktivovaný. Reštart nie je potrebný." + +[admin.settings.premium.currentLicense] +title = "Aktívna licencia" +file = "Zdroj: Licenčný súbor ({{path}})" +key = "Zdroj: Licenčný kľúč" +type = "Typ: {{type}}" +noInput = "Zadajte licenčný kľúč alebo nahrajte súbor certifikátu" +success = "Úspech" + [admin.settings.premium.enabled] label = "Povoliť Premium funkcie" description = "Povoliť kontrolu licenčného kľúča pre pro/enterprise funkcie" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} vybraných" download = "Stiahnuť" delete = "Vymazať" unsupported = "Nepodporované" +active = "Aktívne" addToUpload = "Pridať na nahratie" +closeFile = "Zatvoriť súbor" deleteAll = "Odstrániť všetko" loadingFiles = "Načítavajú sa súbory..." noFiles = "Nie sú dostupné žiadne súbory" @@ -5178,7 +5223,7 @@ active = "Aktívny" disabled = "Zakázaný" activeSession = "Aktívna relácia" member = "Člen" -admin = "Admin" +admin = "Administrátor" editRole = "Upraviť rolu" enable = "Povoliť" disable = "Zakázať" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Vyžaduje sa aspoň jedna e-mailová adresa" submit = "Odoslať pozvánky" success = "Používatelia boli úspešne pozvaní" -partialSuccess = "Niektoré pozvánky zlyhali" +partialFailure = "Niektoré pozvánky zlyhali" allFailed = "Nepodarilo sa pozvať používateľov" error = "Nepodarilo sa odoslať pozvánky" @@ -5797,13 +5842,20 @@ submit = "Prihlásiť sa" signInWith = "Prihlásiť sa cez" oauthPending = "Otvára sa prehliadač na overenie..." orContinueWith = "Alebo pokračujte emailom" +serverRequirement = "Poznámka: Na serveri musí byť povolené prihlásenie." +showInstructions = "Ako povoliť?" +hideInstructions = "Skryť pokyny" +instructions = "Na povolenie prihlásenia na vašom serveri Stirling PDF:" +instructionsEnvVar = "Nastavte premennú prostredia:" +instructionsOrYml = "Alebo v súbore settings.yml:" +instructionsRestart = "Potom reštartujte server, aby sa zmeny prejavili." [setup.login.username] label = "Používateľské meno" placeholder = "Zadajte používateľské meno" [setup.login.email] -label = "Email" +label = "E-mail" placeholder = "Zadajte svoj email" [setup.login.password] @@ -5840,7 +5892,7 @@ paragraph = "Strana s odsekmi" sparse = "Riedky text" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automaticky" paragraph = "Odsek" singleLine = "Jeden riadok" diff --git a/frontend/public/locales/sl-SI/translation.toml b/frontend/public/locales/sl-SI/translation.toml index 36497b6a9..f8bc31492 100644 --- a/frontend/public/locales/sl-SI/translation.toml +++ b/frontend/public/locales/sl-SI/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Odstrani iz priljubljenih" fullscreen = "Preklopi na celozaslonski način" sidebar = "Preklopi na način stranske vrstice" +[backendStartup] +notFoundTitle = "Zaledje ni najdeno" +retry = "Poskusi znova" +unreachable = "Aplikacija se trenutno ne more povezati z zaledjem. Preverite stanje zaledja in omrežno povezavo, nato poskusite znova." + [zipWarning] title = "Velika datoteka ZIP" message = "Ta ZIP vsebuje {{count}} datotek. Vseeno razpakiram?" @@ -912,6 +917,9 @@ desc = "Sestavite večkorakovne poteke z veriženjem dejanj PDF. Idealno za pona desc = "Prekriva PDF-je na vrhu drugega PDF-ja" title = "Prekrivanje PDF-jev" +[home.pdfTextEditor] +title = "Urejevalnik besedila PDF" +desc = "Urejajte obstoječe besedilo in slike v PDF-jih" [home.addText] tags = "besedilo,pripomba,oznaka" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Narisan podpis" defaultImageLabel = "Naložen podpis" defaultTextLabel = "Vpisan podpis" saveButton = "Shrani podpis" +savePersonal = "Shrani osebno" +saveShared = "Shrani deljeno" saveUnavailable = "Najprej ustvarite podpis, da ga lahko shranite." noChanges = "Trenutni podpis je že shranjen." +tempStorageTitle = "Začasno shranjevanje v brskalniku" +tempStorageDescription = "Podpisi so shranjeni samo v vašem brskalniku. Izgubite jih, če počistite podatke brskalnika ali zamenjate brskalnik." +personalHeading = "Osebni podpisi" +sharedHeading = "Deljeni podpisi" +personalDescription = "Te podpise vidite samo vi." +sharedDescription = "Vsi uporabniki lahko te podpise vidijo in uporabljajo." [sign.saved.type] canvas = "Risba" @@ -3438,6 +3454,9 @@ signinTitle = "Prosim prijavite se" ssoSignIn = "Prijava prek enotne prijave" oAuth2AutoCreateDisabled = "OAUTH2 Samodejno ustvarjanje uporabnika onemogočeno" oAuth2AdminBlockedUser = "Registracija ali prijava neregistriranih uporabnikov je trenutno blokirana. Prosimo kontaktirajte skrbnika." +oAuth2RequiresLicense = "Prijava prek OAuth/SSO zahteva plačljivo licenco (Server ali Enterprise). Obrnite se na skrbnika, da nadgradi vaš načrt." +saml2RequiresLicense = "Prijava prek SAML zahteva plačljivo licenco (Server ali Enterprise). Obrnite se na skrbnika, da nadgradi vaš načrt." +maxUsersReached = "Doseženo je največje število uporabnikov za vašo trenutno licenco. Obrnite se na skrbnika, da nadgradi vaš načrt ali doda več mest." oauth2RequestNotFound = "Zahteva za avtorizacijo ni bila najdena" oauth2InvalidUserInfoResponse = "Neveljaven odgovor z informacijami o uporabniku" oauth2invalidRequest = "Neveljavna zahteva" @@ -3846,14 +3865,17 @@ fitToWidth = "Prilagodi širini" actualSize = "Dejanska velikost" [viewer] +cannotPreviewFile = "Predogled datoteke ni mogoč" +dualPageView = "Dvo-stranski pogled" firstPage = "Prva stran" lastPage = "Zadnja stran" -previousPage = "Prejšnja stran" nextPage = "Naslednja stran" +onlyPdfSupported = "Pregledovalnik podpira samo PDF datoteke. Ta datoteka je videti v drugačnem formatu." +previousPage = "Prejšnja stran" +singlePageView = "Enostranski pogled" +unknownFile = "Neznana datoteka" zoomIn = "Povečaj" zoomOut = "Pomanjšaj" -singlePageView = "Enostranski pogled" -dualPageView = "Dvo-stranski pogled" [rightRail] closeSelected = "Zapri izbrane datoteke" @@ -3877,6 +3899,7 @@ toggleSidebar = "Preklopi stransko vrstico" exportSelected = "Izvozi izbrane strani" toggleAnnotations = "Preklopi vidnost opomb" annotationMode = "Preklopi način opomb" +print = "Natisni PDF" draw = "Riši" save = "Shrani" saveChanges = "Shrani spremembe" @@ -4494,6 +4517,7 @@ description = "URL ali ime datoteke do impressuma (zahtevano v nekaterih jurisdi title = "Premium in Enterprise" description = "Konfigurirajte svoj ključ licence Premium ali Enterprise." license = "Konfiguracija licence" +noInput = "Navedite licenčni ključ ali datoteko" [admin.settings.premium.licenseKey] toggle = "Imate licenčni ključ ali potrdilno datoteko?" @@ -4511,6 +4535,25 @@ line1 = "Prepis trenutnega licenčnega ključa ni mogoče razveljaviti." line2 = "Prejšnja licenca bo trajno izgubljena, razen če ste jo varnostno kopirali drugje." line3 = "Pomembno: Licenčne ključe hranite zasebno in varno. Nikoli jih ne delite javno." +[admin.settings.premium.inputMethod] +text = "Licenčni ključ" +file = "Datoteka potrdila" + +[admin.settings.premium.file] +label = "Datoteka licenčnega potrdila" +description = "Naložite svojo licenčno datoteko .lic ali .cert iz nakupov brez povezave" +choose = "Izberite licenčno datoteko" +selected = "Izbrano: {{filename}} ({{size}})" +successMessage = "Licenčna datoteka je bila uspešno naložena in aktivirana. Ponovni zagon ni potreben." + +[admin.settings.premium.currentLicense] +title = "Aktivna licenca" +file = "Vir: licenčna datoteka ({{path}})" +key = "Vir: licenčni ključ" +type = "Vrsta: {{type}}" +noInput = "Navedite licenčni ključ ali naložite datoteko potrdila" +success = "Uspešno" + [admin.settings.premium.enabled] label = "Omogoči funkcije Premium" description = "Omogoči preverjanje licenčnega ključa za funkcije pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} izbranih" download = "Prenos" delete = "Izbriši" unsupported = "Nepodprto" +active = "Aktivno" addToUpload = "Dodaj k nalaganju" +closeFile = "Zapri datoteko" deleteAll = "Izbriši vse" loadingFiles = "Nalaganje datotek..." noFiles = "Ni razpoložljivih datotek" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Zahtevan je vsaj en e-poštni naslov" submit = "Pošlji povabila" success = "uporabnik(i) uspešno povabljen(i)" -partialSuccess = "Nekatera povabila niso uspela" +partialFailure = "Nekatera povabila niso uspela" allFailed = "Uporabnikov ni bilo mogoče povabiti" error = "Pošiljanje povabil ni uspelo" @@ -5797,6 +5842,13 @@ submit = "Prijava" signInWith = "Prijavite se z" oauthPending = "Odpiranje brskalnika za overjanje..." orContinueWith = "Ali nadaljujte z e-pošto" +serverRequirement = "Opomba: Strežnik mora imeti omogočeno prijavo." +showInstructions = "Kako omogočiti?" +hideInstructions = "Skrij navodila" +instructions = "Za omogočanje prijave na vašem strežniku Stirling PDF:" +instructionsEnvVar = "Nastavite okoljsko spremenljivko:" +instructionsOrYml = "Ali v settings.yml:" +instructionsRestart = "Nato znova zaženite strežnik, da spremembe začnejo veljati." [setup.login.username] label = "Uporabniško ime" diff --git a/frontend/public/locales/sr-LATN-RS/translation.toml b/frontend/public/locales/sr-LATN-RS/translation.toml index a24113123..fd433c25e 100644 --- a/frontend/public/locales/sr-LATN-RS/translation.toml +++ b/frontend/public/locales/sr-LATN-RS/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Ukloni iz omiljenog" fullscreen = "Prebaci na režim celog ekrana" sidebar = "Prebaci na režim bočne trake" +[backendStartup] +notFoundTitle = "Bekend nije pronađen" +retry = "Pokušaj ponovo" +unreachable = "Aplikacija trenutno ne može da se poveže sa bekendom. Proverite status bekenda i mrežnu povezanost, pa pokušajte ponovo." + [zipWarning] title = "Velika ZIP datoteka" message = "Ovaj ZIP sadrži {{count}} datoteka. Ipak raspakovati?" @@ -912,6 +917,9 @@ desc = "Gradite višekorake tokove rada povezivanjem PDF akcija. Idealno za pona desc = "Preklapa PDF-ove jedan preko drugog" title = "Preklapanje PDF-ova" +[home.pdfTextEditor] +title = "PDF uređivač teksta" +desc = "Uređujte postojeći tekst i slike unutar PDF-ova" [home.addText] tags = "tekst,anotacija,oznaka" @@ -1213,9 +1221,9 @@ pdfaDigitalSignatureWarning = "PDF sadrži digitalni potpis. Biće uklonjen u sl fileFormat = "Format datoteke" wordDoc = "Word dokument" wordDocExt = "Word dokument (.docx)" -odtExt = "OpenDocument Text (.odt)" +odtExt = "OpenDocument tekst (.odt)" pptExt = "PowerPoint (.pptx)" -odpExt = "OpenDocument Presentation (.odp)" +odpExt = "OpenDocument prezentacija (.odp)" txtExt = "Običan tekst (.txt)" rtfExt = "Rich Text Format (.rtf)" selectedFiles = "Izabrane datoteke" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Crtani potpis" defaultImageLabel = "Otpremljeni potpis" defaultTextLabel = "Ukucani potpis" saveButton = "Sačuvaj potpis" +savePersonal = "Sačuvaj lično" +saveShared = "Sačuvaj deljeno" saveUnavailable = "Prvo napravite potpis da biste ga sačuvali." noChanges = "Trenutni potpis je već sačuvan." +tempStorageTitle = "Privremeno skladište pregledača" +tempStorageDescription = "Potpisi se čuvaju samo u vašem pregledaču. Biće izgubljeni ako obrišete podatke pregledača ili promenite pregledač." +personalHeading = "Lični potpisi" +sharedHeading = "Deljeni potpisi" +personalDescription = "Samo vi možete da vidite ove potpise." +sharedDescription = "Svi korisnici mogu da vide i koriste ove potpise." [sign.saved.type] canvas = "Crtanje" @@ -2318,7 +2334,7 @@ title = "Ravnanje" header = "Ravnanje PDF fajlova" flattenOnlyForms = "Izravnaj samo forme" submit = "Ravnanje" -filenamePrefix = "flattened" +filenamePrefix = "spljošteno" [flatten.files] placeholder = "Izaberite PDF datoteku u glavnom prikazu da biste započeli" @@ -3438,6 +3454,9 @@ signinTitle = "Molimo vas da se prijavite" ssoSignIn = "Prijavite se putem jedinstvene prijave" oAuth2AutoCreateDisabled = "OAUTH2 automatsko kreiranje korisnika je onemogućeno" oAuth2AdminBlockedUser = "Registracija ili prijava neregistrovanog korisnika je trenutno onemogućeno. Kontaktirajte administratora." +oAuth2RequiresLicense = "Prijava putem OAuth/SSO zahteva plaćenu licencu (Server ili Enterprise). Kontaktirajte administratora da unapredi vaš plan." +saml2RequiresLicense = "Prijava putem SAML zahteva plaćenu licencu (Server ili Enterprise). Kontaktirajte administratora da unapredi vaš plan." +maxUsersReached = "Dostignut je maksimalni broj korisnika za vašu trenutnu licencu. Kontaktirajte administratora da unapredi vaš plan ili doda više mesta." oauth2RequestNotFound = "Zahtev za autorizaciju nije pronađen" oauth2InvalidUserInfoResponse = "Neispravan odgovor sa korisničkim informacijama" oauth2invalidRequest = "Neispravan zahtev" @@ -3846,14 +3865,17 @@ fitToWidth = "Uklopi po širini" actualSize = "Stvarna veličina" [viewer] +cannotPreviewFile = "Nije moguće pregledati datoteku" +dualPageView = "Prikaz dve stranice" firstPage = "Prva stranica" lastPage = "Poslednja stranica" -previousPage = "Prethodna stranica" nextPage = "Sledeća stranica" +onlyPdfSupported = "Prikazivač podržava samo PDF datoteke. Izgleda da je ova datoteka drugačijeg formata." +previousPage = "Prethodna stranica" +singlePageView = "Prikaz jedne stranice" +unknownFile = "Nepoznata datoteka" zoomIn = "Uvećaj" zoomOut = "Umanji" -singlePageView = "Prikaz jedne stranice" -dualPageView = "Prikaz dve stranice" [rightRail] closeSelected = "Zatvori izabrane fajlove" @@ -3877,6 +3899,7 @@ toggleSidebar = "Uključi/isključi bočnu traku" exportSelected = "Izvezi izabrane stranice" toggleAnnotations = "Uključi/isključi vidljivost anotacija" annotationMode = "Uključi/isključi režim anotacija" +print = "Štampaj PDF" draw = "Crtaj" save = "Sačuvaj" saveChanges = "Sačuvaj izmene" @@ -4494,6 +4517,7 @@ description = "URL ili naziv datoteke do impresuma (obavezno u nekim jurisdikcij title = "Premium i Enterprise" description = "Podesite svoj premium ili enterprise licencni ključ." license = "Konfiguracija licence" +noInput = "Navedite licencni ključ ili fajl" [admin.settings.premium.licenseKey] toggle = "Imate licencni ključ ili datoteku sertifikata?" @@ -4511,6 +4535,25 @@ line1 = "Prepisivanje vašeg trenutnog licencnog ključa ne može se opozvati." line2 = "Prethodna licenca će biti trajno izgubljena osim ako je niste sačuvali na drugom mestu." line3 = "Važno: Čuvajte licencne ključeve privatnim i bezbednim. Nikada ih javno ne delite." +[admin.settings.premium.inputMethod] +text = "Licencni ključ" +file = "Fajl sertifikata" + +[admin.settings.premium.file] +label = "Fajl licencnog sertifikata" +description = "Otpremite svoj .lic ili .cert licencni fajl iz offline kupovina" +choose = "Izaberite licencni fajl" +selected = "Izabrano: {{filename}} ({{size}})" +successMessage = "Licencni fajl je uspešno otpremljen i aktiviran. Restart nije potreban." + +[admin.settings.premium.currentLicense] +title = "Aktivna licenca" +file = "Izvor: licencni fajl ({{path}})" +key = "Izvor: licencni ključ" +type = "Tip: {{type}}" +noInput = "Navedite licencni ključ ili otpremite fajl sertifikata" +success = "Uspeh" + [admin.settings.premium.enabled] label = "Omogući premium funkcije" description = "Omogući provere licencnog ključa za pro/enterprise funkcije" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} izabrano" download = "Preuzmi" delete = "Obriši" unsupported = "Nepodržano" +active = "Aktivno" addToUpload = "Dodaj za otpremanje" +closeFile = "Zatvori datoteku" deleteAll = "Obriši sve" loadingFiles = "Učitavanje datoteka..." noFiles = "Nema dostupnih datoteka" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Potrebna je bar jedna email adresa" submit = "Pošalji pozive" success = "Korisnik(ci) uspešno pozvan(i)" -partialSuccess = "Neki pozivi nisu uspeli" +partialFailure = "Neki pozivi nisu uspeli" allFailed = "Pozivanje korisnika nije uspelo" error = "Slanje poziva nije uspelo" @@ -5797,6 +5842,13 @@ submit = "Prijavi se" signInWith = "Prijavite se sa" oauthPending = "Otvaranje pregledača za autentikaciju..." orContinueWith = "Ili nastavite uz email" +serverRequirement = "Napomena: Server mora imati omogućenu prijavu." +showInstructions = "Kako omogućiti?" +hideInstructions = "Sakrij uputstva" +instructions = "Da biste omogućili prijavu na svom Stirling PDF serveru:" +instructionsEnvVar = "Podesite promenljivu okruženja:" +instructionsOrYml = "Ili u settings.yml:" +instructionsRestart = "Zatim restartujte server da bi izmene stupile na snagu." [setup.login.username] label = "Korisničko ime" diff --git a/frontend/public/locales/sv-SE/translation.toml b/frontend/public/locales/sv-SE/translation.toml index 3cf3913ca..5c100fe78 100644 --- a/frontend/public/locales/sv-SE/translation.toml +++ b/frontend/public/locales/sv-SE/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Ta bort från favoriter" fullscreen = "Byt till helskärmsläge" sidebar = "Byt till sidopanelläge" +[backendStartup] +notFoundTitle = "Backend hittades inte" +retry = "Försök igen" +unreachable = "Applikationen kan för närvarande inte ansluta till backend. Kontrollera backendens status och nätverksanslutningen och försök sedan igen." + [zipWarning] title = "Stor ZIP-fil" message = "Denna ZIP innehåller {{count}} filer. Extrahera ändå?" @@ -912,6 +917,9 @@ desc = "Skapa flerstegade arbetsflöden genom att kedja ihop PDF‑åtgärder. P desc = "Överlagrar PDF:er ovanpå en annan PDF" title = "Överlagra PDF:er" +[home.pdfTextEditor] +title = "PDF-textredigerare" +desc = "Redigera befintlig text och bilder i PDF-filer" [home.addText] tags = "text,kommentar,etikett" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Ritad signatur" defaultImageLabel = "Uppladdad signatur" defaultTextLabel = "Skriven signatur" saveButton = "Spara signatur" +savePersonal = "Spara som personlig" +saveShared = "Spara som delad" saveUnavailable = "Skapa en signatur först för att kunna spara." noChanges = "Aktuell signatur är redan sparad." +tempStorageTitle = "Tillfällig lagring i webbläsaren" +tempStorageDescription = "Signaturer lagras endast i din webbläsare. De går förlorade om du rensar webbläsardata eller byter webbläsare." +personalHeading = "Personliga signaturer" +sharedHeading = "Delade signaturer" +personalDescription = "Endast du kan se dessa signaturer." +sharedDescription = "Alla användare kan se och använda dessa signaturer." [sign.saved.type] canvas = "Ritning" @@ -2281,7 +2297,7 @@ placeDesc = "Placera signaturen på din PDF" [sign.type] title = "Signaturtyp" draw = "Rita" -canvas = "Canvas" +canvas = "Rityta" image = "Bild" text = "Text" saved = "Sparad" @@ -3438,6 +3454,9 @@ signinTitle = "Vänligen logga in" ssoSignIn = "Logga in via enkel inloggning" oAuth2AutoCreateDisabled = "OAUTH2 Auto-skapa användare inaktiverad" oAuth2AdminBlockedUser = "Registrering eller inloggning av icke-registrerade användare är för närvarande blockerad. Kontakta administratören." +oAuth2RequiresLicense = "OAuth/SSO-inloggning kräver en betald licens (Server eller Enterprise). Kontakta administratören för att uppgradera din plan." +saml2RequiresLicense = "SAML-inloggning kräver en betald licens (Server eller Enterprise). Kontakta administratören för att uppgradera din plan." +maxUsersReached = "Maximalt antal användare har uppnåtts för din nuvarande licens. Kontakta administratören för att uppgradera din plan eller lägga till fler användarplatser." oauth2RequestNotFound = "Auktoriseringsbegäran hittades inte" oauth2InvalidUserInfoResponse = "Ogiltigt svar på användarinformation" oauth2invalidRequest = "Ogiltig begäran" @@ -3846,14 +3865,17 @@ fitToWidth = "Anpassa till bredd" actualSize = "Faktisk storlek" [viewer] +cannotPreviewFile = "Kan inte förhandsgranska filen" +dualPageView = "Dubbelsidig vy" firstPage = "Första sidan" lastPage = "Sista sidan" -previousPage = "Föregående sida" nextPage = "Nästa sida" +onlyPdfSupported = "Visaren stöder endast PDF-filer. Den här filen verkar vara i ett annat format." +previousPage = "Föregående sida" +singlePageView = "Ensidig vy" +unknownFile = "Okänd fil" zoomIn = "Zooma in" zoomOut = "Zooma ut" -singlePageView = "Ensidig vy" -dualPageView = "Dubbelsidig vy" [rightRail] closeSelected = "Stäng markerade filer" @@ -3877,6 +3899,7 @@ toggleSidebar = "Växla sidofält" exportSelected = "Exportera markerade sidor" toggleAnnotations = "Växla synlighet för anteckningar" annotationMode = "Växla anteckningsläge" +print = "Skriv ut PDF" draw = "Rita" save = "Spara" saveChanges = "Spara ändringar" @@ -4494,6 +4517,7 @@ description = "URL eller filnamn till impressum (krävs i vissa jurisdiktioner)" title = "Premium och Enterprise" description = "Konfigurera din premium- eller enterprise-licensnyckel." license = "Licenskonfiguration" +noInput = "Ange en licensnyckel eller fil" [admin.settings.premium.licenseKey] toggle = "Har du en licensnyckel eller certifikatfil?" @@ -4511,6 +4535,25 @@ line1 = "Att skriva över din nuvarande licensnyckel kan inte ångras." line2 = "Din tidigare licens går förlorad permanent om du inte har säkerhetskopierat den någon annanstans." line3 = "Viktigt: Håll licensnycklar privata och säkra. Dela dem aldrig offentligt." +[admin.settings.premium.inputMethod] +text = "Licensnyckel" +file = "Certifikatfil" + +[admin.settings.premium.file] +label = "Licenscertifikatfil" +description = "Ladda upp din .lic- eller .cert-licensfil från offlineköp" +choose = "Välj licensfil" +selected = "Vald: {{filename}} ({{size}})" +successMessage = "Licensfilen har laddats upp och aktiverats. Ingen omstart krävs." + +[admin.settings.premium.currentLicense] +title = "Aktiv licens" +file = "Källa: Licensfil ({{path}})" +key = "Källa: Licensnyckel" +type = "Typ: {{type}}" +noInput = "Ange en licensnyckel eller ladda upp en certifikatfil" +success = "Lyckat" + [admin.settings.premium.enabled] label = "Aktivera premiumfunktioner" description = "Aktivera licensnyckelkontroller för pro-/enterprise-funktioner" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} markerade" download = "Ladda ner" delete = "Radera" unsupported = "Stöds inte" +active = "Aktiv" addToUpload = "Lägg till i uppladdning" +closeFile = "Stäng fil" deleteAll = "Ta bort alla" loadingFiles = "Läser in filer..." noFiles = "Inga filer tillgängliga" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Minst en e-postadress krävs" submit = "Skicka inbjudningar" success = "Användare inbjudna" -partialSuccess = "Vissa inbjudningar misslyckades" +partialFailure = "Vissa inbjudningar misslyckades" allFailed = "Misslyckades med att bjuda in användare" error = "Misslyckades med att skicka inbjudningar" @@ -5797,6 +5842,13 @@ submit = "Logga in" signInWith = "Logga in med" oauthPending = "Öppnar webbläsaren för autentisering..." orContinueWith = "Eller fortsätt med e-post" +serverRequirement = "Observera: Servern måste ha inloggning aktiverad." +showInstructions = "Hur aktiverar man?" +hideInstructions = "Dölj instruktioner" +instructions = "För att aktivera inloggning på din Stirling PDF-server:" +instructionsEnvVar = "Ställ in miljövariabeln:" +instructionsOrYml = "Eller i settings.yml:" +instructionsRestart = "Starta sedan om servern för att ändringarna ska börja gälla." [setup.login.username] label = "Användarnamn" diff --git a/frontend/public/locales/th-TH/translation.toml b/frontend/public/locales/th-TH/translation.toml index bfd0077b2..386b699f8 100644 --- a/frontend/public/locales/th-TH/translation.toml +++ b/frontend/public/locales/th-TH/translation.toml @@ -163,6 +163,11 @@ unfavorite = "นำออกจากรายการโปรด" fullscreen = "สลับเป็นโหมดเต็มหน้าจอ" sidebar = "สลับเป็นโหมดแถบด้านข้าง" +[backendStartup] +notFoundTitle = "ไม่พบ Backend" +retry = "ลองอีกครั้ง" +unreachable = "ขณะนี้แอปพลิเคชันไม่สามารถเชื่อมต่อกับ Backend ได้ โปรดตรวจสอบสถานะของ Backend และการเชื่อมต่อเครือข่าย จากนั้นลองอีกครั้ง" + [zipWarning] title = "ไฟล์ ZIP ขนาดใหญ่" message = "ZIP นี้มี {{count}} ไฟล์ ต้องการแตกไฟล์ต่อหรือไม่?" @@ -347,7 +352,7 @@ teams = "ทีม" title = "การกำหนดค่า" systemSettings = "การตั้งค่าระบบ" features = "ฟีเจอร์" -endpoints = "Endpoints" +endpoints = "ปลายทาง" database = "ฐานข้อมูล" advanced = "ขั้นสูง" @@ -369,7 +374,7 @@ privacy = "ความเป็นส่วนตัว" [settings.developer] title = "นักพัฒนา" -apiKeys = "API Keys" +apiKeys = "คีย์ API" [settings.tooltips] enableLoginFirst = "เปิดใช้งานโหมดเข้าสู่ระบบก่อน" @@ -556,7 +561,7 @@ totalEndpoints = "จำนวน Endpoint ทั้งหมด" totalVisits = "จำนวนการเข้าชมทั้งหมด" showing = "กำลังแสดง" selectedVisits = "การเข้าชมที่เลือก" -endpoint = "Endpoint" +endpoint = "ปลายทาง" visits = "การเข้าชม" percentage = "เปอร์เซ็นต์" loading = "กำลังโหลด..." @@ -794,7 +799,7 @@ title = "รวมเป็น หน้าเดียว" desc = "รวมหน้าทั้งหมดของ PDF เป็นหน้าเดียวขนาดใหญ่" [home.showJS] -tags = "javascript,code,script" +tags = "javascript,โค้ด,สคริปต์" title = "แสดง Javascript" desc = "ค้นหาและแสดง Javascript ที่ฝังใน PDF" @@ -829,7 +834,7 @@ title = "ตรวจสอบลายเซ็น PDF" desc = "ตรวจสอบลายเซ็นดิจิทัลและใบรับรองในเอกสาร PDF" [home.swagger] -tags = "API,documentation,test" +tags = "API,เอกสารประกอบ,ทดสอบ" title = "เอกสาร API" desc = "ดูเอกสาร API และทดสอบเอ็นด์พอยต์" @@ -878,7 +883,7 @@ title = "แทนที่และกลับสี" desc = "แทนที่หรือกลับสีในเอกสาร PDF" [home.devApi] -tags = "API,development,documentation" +tags = "API,การพัฒนา,เอกสารประกอบ" title = "API" desc = "ลิงก์ไปยังเอกสาร API" @@ -912,9 +917,12 @@ desc = "สร้างเวิร์กโฟลว์หลายขั้น desc = "ซ้อนทับ PDF บน PDF อีกไฟล์หนึ่ง" title = "ซ้อนทับ PDF" +[home.pdfTextEditor] +title = "ตัวแก้ไขข้อความ PDF" +desc = "แก้ไขข้อความและรูปภาพที่มีอยู่ภายในไฟล์ PDF" [home.addText] -tags = "text,annotation,label" +tags = "ข้อความ,คำอธิบายประกอบ,ป้ายกำกับ" title = "เพิ่มข้อความ" desc = "เพิ่มข้อความที่กำหนดเองที่ใดก็ได้ใน PDF ของคุณ" @@ -1832,7 +1840,7 @@ title = "ขั้นสูง" tags = "ย่อ, เล็ก, จิ๋ว" [unlockPDFForms] -tags = "remove,delete,form,field,readonly" +tags = "เอาออก,ลบ,ฟอร์ม,ฟิลด์,อ่านอย่างเดียว" title = "ลบสถานะอ่านอย่างเดียวออกจากช่องฟอร์ม" header = "ปลดล็อกฟอร์ม PDF" submit = "Remove" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "ลายเซ็นแบบวาด" defaultImageLabel = "ลายเซ็นที่อัปโหลด" defaultTextLabel = "ลายเซ็นแบบพิมพ์" saveButton = "บันทึกลายเซ็น" +savePersonal = "บันทึกส่วนตัว" +saveShared = "บันทึกแบบใช้ร่วมกัน" saveUnavailable = "สร้างลายเซ็นก่อนเพื่อบันทึก" noChanges = "ลายเซ็นปัจจุบันถูกบันทึกไว้แล้ว" +tempStorageTitle = "พื้นที่จัดเก็บชั่วคราวบนเบราว์เซอร์" +tempStorageDescription = "ลายเซ็นจะถูกจัดเก็บไว้ในเบราว์เซอร์ของคุณเท่านั้น และจะหายไปหากคุณล้างข้อมูลเบราว์เซอร์หรือสลับไปใช้เบราว์เซอร์อื่น" +personalHeading = "ลายเซ็นส่วนตัว" +sharedHeading = "ลายเซ็นที่ใช้ร่วมกัน" +personalDescription = "มีเพียงคุณเท่านั้นที่มองเห็นลายเซ็นเหล่านี้" +sharedDescription = "ผู้ใช้ทุกคนสามารถเห็นและใช้ลายเซ็นเหล่านี้ได้" [sign.saved.type] canvas = "การวาด" @@ -2731,7 +2747,7 @@ submit = "ส่ง" failed = "เกิดข้อผิดพลาดขณะสร้างเลย์เอาต์หลายหน้า" [bookletImposition] -tags = "booklet,imposition,printing,binding,folding,signature" +tags = "หนังสือเย็บเล่ม,การจัดหน้า,การพิมพ์,การเข้าเล่ม,การพับ,ชุดพิมพ์" title = "การจัดหน้าสมุด" header = "การจัดหน้าสมุด" submit = "สร้างสมุด" @@ -2830,7 +2846,7 @@ scaleFactor = "ระดับการซูม (ครอบตัด) ขอ submit = "ส่ง" [adjustPageScale] -tags = "resize,modify,dimension,adapt" +tags = "ปรับขนาด,แก้ไข,ขนาด,ปรับให้เหมาะสม" title = "ปรับสเกลหน้า" header = "ปรับสเกลหน้า" submit = "ปรับสเกลหน้า" @@ -3438,6 +3454,9 @@ signinTitle = "กรุณาลงชื่อเข้าใช้" ssoSignIn = "เข้าสู่ระบบด้วย Single Sign-on" oAuth2AutoCreateDisabled = "การสร้างผู้ใช้ OAuth2 อัตโนมัติถูกปิดใช้งาน" oAuth2AdminBlockedUser = "ขณะนี้มีการบล็อกการลงทะเบียนหรือการเข้าสู่ระบบของผู้ใช้ที่ไม่ได้ลงทะเบียน โปรดติดต่อผู้ดูแลระบบ" +oAuth2RequiresLicense = "การเข้าสู่ระบบด้วย OAuth/SSO ต้องมีไลเซนส์แบบชำระเงิน (Server หรือ Enterprise) โปรดติดต่อผู้ดูแลระบบเพื่ออัปเกรดแผนของคุณ" +saml2RequiresLicense = "การเข้าสู่ระบบด้วย SAML ต้องมีไลเซนส์แบบชำระเงิน (Server หรือ Enterprise) โปรดติดต่อผู้ดูแลระบบเพื่ออัปเกรดแผนของคุณ" +maxUsersReached = "จำนวนผู้ใช้ถึงขีดสูงสุดสำหรับไลเซนส์ปัจจุบันของคุณ โปรดติดต่อผู้ดูแลระบบเพื่ออัปเกรดแผนหรือเพิ่มจำนวนที่นั่ง" oauth2RequestNotFound = "ไม่พบคำขอการอนุญาต" oauth2InvalidUserInfoResponse = "การตอบกลับข้อมูลผู้ใช้ไม่ถูกต้อง" oauth2invalidRequest = "คำขอไม่ถูกต้อง" @@ -3771,7 +3790,7 @@ version = "รุ่นปัจจุบัน" title = "เอกสาร API" header = "เอกสาร API" desc = "ดูและทดสอบจุดปลายทาง API ของ Stirling PDF" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,เอกสารประกอบ,swagger,ปลายทาง,การพัฒนา" [cookieBanner.popUp] title = "เราใช้คุกกี้อย่างไร" @@ -3846,14 +3865,17 @@ fitToWidth = "พอดีกับความกว้าง" actualSize = "ขนาดจริง" [viewer] +cannotPreviewFile = "ไม่สามารถแสดงตัวอย่างไฟล์ได้" +dualPageView = "มุมมองสองหน้า" firstPage = "หน้าแรก" lastPage = "หน้าสุดท้าย" -previousPage = "หน้าก่อนหน้า" nextPage = "หน้าถัดไป" +onlyPdfSupported = "ตัวแสดงผลรองรับเฉพาะไฟล์ PDF ไฟล์นี้ดูเหมือนจะเป็นรูปแบบอื่น" +previousPage = "หน้าก่อนหน้า" +singlePageView = "มุมมองหน้าเดียว" +unknownFile = "ไฟล์ไม่รู้จัก" zoomIn = "ซูมเข้า" zoomOut = "ซูมออก" -singlePageView = "มุมมองหน้าเดียว" -dualPageView = "มุมมองสองหน้า" [rightRail] closeSelected = "ปิดไฟล์ที่เลือก" @@ -3877,6 +3899,7 @@ toggleSidebar = "สลับแถบข้าง" exportSelected = "ส่งออกหน้าที่เลือก" toggleAnnotations = "สลับการแสดงคำอธิบายประกอบ" annotationMode = "สลับโหมดคำอธิบายประกอบ" +print = "พิมพ์ PDF" draw = "วาด" save = "บันทึก" saveChanges = "บันทึกการเปลี่ยนแปลง" @@ -4343,7 +4366,7 @@ features = "แฟลกฟีเจอร์" processing = "การประมวลผล" [admin.settings.advanced.endpoints] -label = "Endpoints" +label = "ปลายทาง" manage = "จัดการ API Endpoints" description = "การจัดการ Endpoint กำหนดค่าผ่าน YAML ดูเอกสารประกอบสำหรับรายละเอียดการเปิด/ปิดใช้งาน Endpoint เฉพาะ" @@ -4407,7 +4430,7 @@ description = "จะทำความสะอาดไดเรกทอร label = "ข้อจำกัดของตัวประมวลผลกระบวนการ" description = "กำหนดขีดจำกัดเซสชันและระยะหมดเวลาสำหรับตัวประมวลผลแต่ละตัว" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDF เป็น HTML" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4494,6 +4517,7 @@ description = "URL หรือชื่อไฟล์ไปยัง Impressum title = "พรีเมียมและเอนเตอร์ไพรส์" description = "กำหนดค่าคีย์ไลเซนส์พรีเมียมหรือเอนเตอร์ไพรส์ของคุณ" license = "การกำหนดค่าไลเซนส์" +noInput = "โปรดระบุคีย์หรือไฟล์ไลเซนส์" [admin.settings.premium.licenseKey] toggle = "มี license key หรือไฟล์ certificate ไหม?" @@ -4511,6 +4535,25 @@ line1 = "การเขียนทับ license key ปัจจุบัน line2 = "ไลเซนส์ก่อนหน้าของคุณจะสูญหายถาวร เว้นแต่คุณได้สำรองไว้ที่อื่น" line3 = "สำคัญ: เก็บ license keys ให้เป็นส่วนตัวและปลอดภัย ห้ามแชร์สาธารณะ" +[admin.settings.premium.inputMethod] +text = "คีย์ไลเซนส์" +file = "ไฟล์ใบรับรอง" + +[admin.settings.premium.file] +label = "ไฟล์ใบรับรองไลเซนส์" +description = "อัปโหลดไฟล์ไลเซนส์ .lic หรือ .cert จากการสั่งซื้อแบบออฟไลน์ของคุณ" +choose = "เลือกไฟล์ไลเซนส์" +selected = "ที่เลือก: {{filename}} ({{size}})" +successMessage = "อัปโหลดและเปิดใช้งานไฟล์ไลเซนส์สำเร็จ ไม่จำเป็นต้องเริ่มระบบใหม่" + +[admin.settings.premium.currentLicense] +title = "ไลเซนส์ที่ใช้งานอยู่" +file = "แหล่งที่มา: ไฟล์ไลเซนส์ ({{path}})" +key = "แหล่งที่มา: คีย์ไลเซนส์" +type = "ประเภท: {{type}}" +noInput = "โปรดระบุคีย์ไลเซนส์หรืออัปโหลดไฟล์ใบรับรอง" +success = "สำเร็จ" + [admin.settings.premium.enabled] label = "เปิดใช้งานฟีเจอร์พรีเมียม" description = "เปิดการตรวจสอบคีย์ไลเซนส์สำหรับฟีเจอร์แบบ Pro/Enterprise" @@ -4544,7 +4587,7 @@ label = "สร้างใหม่เมื่อเริ่มต้น" description = "สร้างใบรับรองใหม่ทุกครั้งที่แอปพลิเคชันเริ่มต้น" [admin.settings.endpoints] -title = "API Endpoints" +title = "ปลายทาง API" description = "ควบคุมว่า API Endpoints และกลุ่ม Endpoint ใดที่ใช้งานได้" management = "การจัดการ Endpoint" note = "หมายเหตุ: การปิดการใช้งาน endpoints จะจำกัดการเข้าถึง API แต่จะไม่ลบส่วนติดต่อผู้ใช้ ต้องรีสตาร์ทจึงจะมีผล" @@ -4644,7 +4687,9 @@ selectedCount = "เลือกแล้ว {{count}} รายการ" download = "ดาวน์โหลด" delete = "ลบ" unsupported = "ไม่รองรับ" +active = "ใช้งานอยู่" addToUpload = "เพิ่มไปยังอัปโหลด" +closeFile = "ปิดไฟล์" deleteAll = "ลบทั้งหมด" loadingFiles = "กำลังโหลดไฟล์..." noFiles = "ไม่มีไฟล์" @@ -4989,7 +5034,7 @@ chartAriaLabel = "การใช้เครดิต: ใช้แบบรว nextReset = "รีเซ็ตครั้งถัดไป" lastApiUse = "การใช้งาน API ล่าสุด" overlayMessage = "สร้างคีย์เพื่อดูเครดิตและเครดิตที่มีอยู่" -label = "API Key" +label = "คีย์ API" guestInfo = "ผู้ใช้แบบแขกจะไม่ได้รับ API key สร้างบัญชีเพื่อรับ API key สำหรับใช้งานในแอปพลิเคชันของคุณ" goToAccount = "ไปที่บัญชี" generateError = "ไม่สามารถสร้าง API key ของคุณได้" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "ต้องมีอย่างน้อยหนึ่งที่อยู่อีเมล" submit = "ส่งคำเชิญ" success = "เชิญผู้ใช้สำเร็จ" -partialSuccess = "บางคำเชิญล้มเหลว" +partialFailure = "คำเชิญบางรายการไม่สำเร็จ" allFailed = "เชิญผู้ใช้ไม่สำเร็จ" error = "ส่งคำเชิญไม่สำเร็จ" @@ -5709,7 +5754,7 @@ title = "แผนภูมิการใช้งาน Endpoint" [usage.table] title = "สถิติแบบละเอียด" -endpoint = "Endpoint" +endpoint = "ปลายทาง" visits = "การเข้าชม" percentage = "เปอร์เซ็นต์" noData = "ไม่มีข้อมูล" @@ -5797,6 +5842,13 @@ submit = "เข้าสู่ระบบ" signInWith = "ลงชื่อเข้าใช้ด้วย" oauthPending = "กำลังเปิดเบราว์เซอร์เพื่อยืนยันตัวตน..." orContinueWith = "หรือดำเนินการต่อด้วยอีเมล" +serverRequirement = "หมายเหตุ: เซิร์ฟเวอร์ต้องเปิดใช้งานการเข้าสู่ระบบ" +showInstructions = "เปิดใช้งานอย่างไร?" +hideInstructions = "ซ่อนคำแนะนำ" +instructions = "วิธีเปิดใช้งานการเข้าสู่ระบบบนเซิร์ฟเวอร์ Stirling PDF ของคุณ:" +instructionsEnvVar = "ตั้งค่าตัวแปรสภาพแวดล้อม:" +instructionsOrYml = "หรือใน settings.yml:" +instructionsRestart = "จากนั้นรีสตาร์ทเซิร์ฟเวอร์ของคุณเพื่อให้การเปลี่ยนแปลงมีผล" [setup.login.username] label = "ชื่อผู้ใช้" @@ -5932,13 +5984,13 @@ warnings = "คำเตือน" suggestions = "หมายเหตุ" currentPageFonts = "ฟอนต์บนหน้านี้" allFonts = "ฟอนต์ทั้งหมด" -fallback = "fallback" +fallback = "สำรอง" missing = "หายไป" perfectMessage = "สามารถทำซ้ำฟอนต์ทั้งหมดได้อย่างสมบูรณ์แบบ" warningMessage = "บางฟอนต์อาจแสดงผลไม่ถูกต้อง" infoMessage = "มีข้อมูลการทำซ้ำฟอนต์" perfect = "สมบูรณ์แบบ" -subset = "subset" +subset = "ซับเซ็ต" [pdfTextEditor.errors] invalidJson = "ไม่สามารถอ่านไฟล์ JSON โปรดตรวจสอบว่าไฟล์ถูกสร้างโดยเครื่องมือ PDF to JSON" @@ -5953,7 +6005,7 @@ insufficientPermissions = "คุณไม่มีสิทธิ์ในก [addText] title = "เพิ่มข้อความ" header = "เพิ่มข้อความลงใน PDF" -tags = "text,annotation,label" +tags = "ข้อความ,คำอธิบายประกอบ,ป้ายกำกับ" applySignatures = "ใช้ข้อความ" [addText.text] diff --git a/frontend/public/locales/tr-TR/translation.toml b/frontend/public/locales/tr-TR/translation.toml index a5bee2af7..52d46d7fe 100644 --- a/frontend/public/locales/tr-TR/translation.toml +++ b/frontend/public/locales/tr-TR/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Favorilerden kaldır" fullscreen = "Tam ekran moduna geç" sidebar = "Kenar çubuğu moduna geç" +[backendStartup] +notFoundTitle = "Arka uç bulunamadı" +retry = "Yeniden dene" +unreachable = "Uygulama şu anda arka uca bağlanamıyor. Lütfen arka uç durumunu ve ağ bağlantısını doğrulayın, ardından tekrar deneyin." + [zipWarning] title = "Büyük ZIP Dosyası" message = "Bu ZIP {{count}} dosya içeriyor. Yine de çıkartılsın mı?" @@ -912,6 +917,9 @@ desc = "PDF eylemlerini birbirine bağlayarak çok adımlı iş akışları olu desc = "PDF'leri başka bir PDF'nin üzerine bindirir" title = "PDF'leri Bindirme" +[home.pdfTextEditor] +title = "PDF Metin Düzenleyici" +desc = "PDF'lerin içindeki mevcut metinleri ve görselleri düzenleyin" [home.addText] tags = "metin,ek açıklama,etiket" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Çizim imzası" defaultImageLabel = "Yüklenen imza" defaultTextLabel = "Yazılmış imza" saveButton = "İmzayı kaydet" +savePersonal = "Kişisel Olarak Kaydet" +saveShared = "Paylaşılan Olarak Kaydet" saveUnavailable = "Kaydetmek için önce bir imza oluşturun." noChanges = "Geçerli imza zaten kaydedildi." +tempStorageTitle = "Geçici tarayıcı depolaması" +tempStorageDescription = "İmzalar yalnızca tarayıcınızda saklanır. Tarayıcı verilerini temizlerseniz veya tarayıcı değiştirirseniz kaybolurlar." +personalHeading = "Kişisel İmzalar" +sharedHeading = "Paylaşılan İmzalar" +personalDescription = "Bu imzaları yalnızca siz görebilirsiniz." +sharedDescription = "Tüm kullanıcılar bu imzaları görebilir ve kullanabilir." [sign.saved.type] canvas = "Çizim" @@ -3438,6 +3454,9 @@ signinTitle = "Lütfen giriş yapınız." ssoSignIn = "Tek Oturum Açma ile Giriş Yap" oAuth2AutoCreateDisabled = "OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı" oAuth2AdminBlockedUser = "Kayıtlı olmayan kullanıcıların kayıt veya giriş yapması şu anda engellenmiştir. Lütfen yöneticiyle iletişime geçin." +oAuth2RequiresLicense = "OAuth/SSO ile oturum açma ücretli bir lisans (Server veya Enterprise) gerektirir. Planınızı yükseltmek için lütfen yöneticiyle iletişime geçin." +saml2RequiresLicense = "SAML ile oturum açma ücretli bir lisans (Server veya Enterprise) gerektirir. Planınızı yükseltmek için lütfen yöneticiyle iletişime geçin." +maxUsersReached = "Mevcut lisansınız için azami kullanıcı sayısına ulaşıldı. Planınızı yükseltmek veya daha fazla koltuk eklemek için lütfen yöneticiyle iletişime geçin." oauth2RequestNotFound = "Yetkilendirme isteği bulunamadı" oauth2InvalidUserInfoResponse = "Geçersiz Kullanıcı Bilgisi Yanıtı" oauth2invalidRequest = "Geçersiz İstek" @@ -3846,14 +3865,17 @@ fitToWidth = "Genişliğe Sığdır" actualSize = "Gerçek Boyut" [viewer] +cannotPreviewFile = "Dosya önizlenemiyor" +dualPageView = "Çift Sayfa Görünümü" firstPage = "İlk Sayfa" lastPage = "Son Sayfa" -previousPage = "Önceki Sayfa" nextPage = "Sonraki Sayfa" +onlyPdfSupported = "Görüntüleyici yalnızca PDF dosyalarını destekler. Bu dosya farklı bir biçimde görünüyor." +previousPage = "Önceki Sayfa" +singlePageView = "Tek Sayfa Görünümü" +unknownFile = "Bilinmeyen dosya" zoomIn = "Yakınlaştır" zoomOut = "Uzaklaştır" -singlePageView = "Tek Sayfa Görünümü" -dualPageView = "Çift Sayfa Görünümü" [rightRail] closeSelected = "Seçilen Dosyaları Kapat" @@ -3877,6 +3899,7 @@ toggleSidebar = "Kenar Çubuğunu Aç/Kapat" exportSelected = "Seçilen Sayfaları Dışa Aktar" toggleAnnotations = "Açıklamaların Görünürlüğünü Değiştir" annotationMode = "Açıklama Modunu Değiştir" +print = "PDF'yi Yazdır" draw = "Çiz" save = "Kaydet" saveChanges = "Değişiklikleri Kaydet" @@ -4494,6 +4517,7 @@ description = "Impressum için URL veya dosya adı (bazı yargı bölgelerinde g title = "Premium ve Kurumsal" description = "Premium veya kurumsal lisans anahtarınızı yapılandırın." license = "Lisans Yapılandırması" +noInput = "Lütfen bir lisans anahtarı veya dosyası sağlayın" [admin.settings.premium.licenseKey] toggle = "Lisans anahtarınız veya sertifika dosyanız mı var?" @@ -4511,6 +4535,25 @@ line1 = "Mevcut lisans anahtarınızın üzerine yazma işlemi geri alınamaz." line2 = "Başka yerde yedeğiniz yoksa önceki lisansınız kalıcı olarak kaybolacaktır." line3 = "Önemli: Lisans anahtarlarını gizli ve güvenli tutun. Asla herkese açık şekilde paylaşmayın." +[admin.settings.premium.inputMethod] +text = "Lisans Anahtarı" +file = "Sertifika Dosyası" + +[admin.settings.premium.file] +label = "Lisans Sertifika Dosyası" +description = "Çevrimdışı satın alımlardan aldığınız .lic veya .cert lisans dosyanızı yükleyin" +choose = "Lisans Dosyası Seç" +selected = "Seçildi: {{filename}} ({{size}})" +successMessage = "Lisans dosyası başarıyla yüklendi ve etkinleştirildi. Yeniden başlatma gerekmez." + +[admin.settings.premium.currentLicense] +title = "Etkin Lisans" +file = "Kaynak: Lisans dosyası ({{path}})" +key = "Kaynak: Lisans anahtarı" +type = "Tür: {{type}}" +noInput = "Lütfen bir lisans anahtarı girin veya bir sertifika dosyası yükleyin" +success = "Başarılı" + [admin.settings.premium.enabled] label = "Premium Özellikleri Etkinleştir" description = "Pro/kurumsal özellikler için lisans anahtarı kontrollerini etkinleştir" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} seçildi" download = "İndir" delete = "Sil" unsupported = "Desteklenmiyor" +active = "Aktif" addToUpload = "Yüklemeye Ekle" +closeFile = "Dosyayı Kapat" deleteAll = "Tümünü Sil" loadingFiles = "Dosyalar yükleniyor..." noFiles = "Kullanılabilir dosya yok" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "En az bir e-posta adresi gereklidir" submit = "Davetleri Gönder" success = "kullanıcı(lar) başarıyla davet edildi" -partialSuccess = "Bazı davetler başarısız oldu" +partialFailure = "Bazı davetler başarısız oldu" allFailed = "Kullanıcılar davet edilemedi" error = "Davetler gönderilemedi" @@ -5797,6 +5842,13 @@ submit = "Oturum Aç" signInWith = "Şununla oturum aç" oauthPending = "Kimlik doğrulama için tarayıcı açılıyor..." orContinueWith = "Veya e-postayla devam edin" +serverRequirement = "Not: Sunucuda oturum açma etkin olmalıdır." +showInstructions = "Nasıl etkinleştirilir?" +hideInstructions = "Yönergeleri gizle" +instructions = "Stirling PDF sunucunuzda oturum açmayı etkinleştirmek için:" +instructionsEnvVar = "Ortam değişkenini ayarlayın:" +instructionsOrYml = "Veya settings.yml içinde:" +instructionsRestart = "Ardından değişikliklerin etkili olması için sunucunuzu yeniden başlatın." [setup.login.username] label = "Kullanıcı adı" diff --git a/frontend/public/locales/uk-UA/translation.toml b/frontend/public/locales/uk-UA/translation.toml index dbb957a6a..b261dc02a 100644 --- a/frontend/public/locales/uk-UA/translation.toml +++ b/frontend/public/locales/uk-UA/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Видалити з вибраного" fullscreen = "Переключитися на повноекранний режим" sidebar = "Переключитися на режим бічної панелі" +[backendStartup] +notFoundTitle = "Серверну частину не знайдено" +retry = "Повторити" +unreachable = "Застосунок наразі не може під’єднатися до серверної частини. Перевірте стан серверної частини та мережеве з’єднання, потім спробуйте ще раз." + [zipWarning] title = "Великий ZIP-файл" message = "Цей ZIP містить {{count}} файлів. Розпакувати попри це?" @@ -912,6 +917,9 @@ desc = "Створюйте багатокрокові робочі процес desc = "Накладення одного PDF поверх іншого PDF" title = "Накладення PDF" +[home.pdfTextEditor] +title = "Редактор тексту PDF" +desc = "Редагуйте наявний текст і зображення у PDF" [home.addText] tags = "текст,анотація,мітка" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Намальований підпис" defaultImageLabel = "Завантажений підпис" defaultTextLabel = "Набраний підпис" saveButton = "Зберегти підпис" +savePersonal = "Зберегти як особистий" +saveShared = "Зберегти як спільний" saveUnavailable = "Спочатку створіть підпис, щоб зберегти його." noChanges = "Поточний підпис вже збережено." +tempStorageTitle = "Тимчасове сховище браузера" +tempStorageDescription = "Підписи зберігаються лише у вашому браузері. Вони будуть втрачені, якщо ви очистите дані браузера або зміните браузер." +personalHeading = "Особисті підписи" +sharedHeading = "Спільні підписи" +personalDescription = "Лише ви можете бачити ці підписи." +sharedDescription = "Усі користувачі можуть бачити та використовувати ці підписи." [sign.saved.type] canvas = "Малювання" @@ -3438,6 +3454,9 @@ signinTitle = "Будь ласка, увійдіть" ssoSignIn = "Увійти через єдиний вхід" oAuth2AutoCreateDisabled = "Автоматичне створення користувача OAUTH2 ВИМКНЕНО" oAuth2AdminBlockedUser = "Реєстрація або вхід незареєстрованих користувачів наразі заборонено. Будь ласка, зв'яжіться з адміністратором." +oAuth2RequiresLicense = "Вхід через OAuth/SSO потребує платної ліцензії (Server або Enterprise). Зверніться до адміністратора, щоб оновити ваш план." +saml2RequiresLicense = "Вхід через SAML потребує платної ліцензії (Server або Enterprise). Зверніться до адміністратора, щоб оновити ваш план." +maxUsersReached = "Досягнуто максимальної кількості користувачів для вашої поточної ліцензії. Зверніться до адміністратора, щоб оновити план або додати місця." oauth2RequestNotFound = "Запит на авторизація не знайдено" oauth2InvalidUserInfoResponse = "Недійсна відповідь з інформацією користувача" oauth2invalidRequest = "Недійсний запит" @@ -3846,14 +3865,17 @@ fitToWidth = "Підігнати за шириною" actualSize = "Фактичний розмір" [viewer] +cannotPreviewFile = "Не вдається переглянути файл" +dualPageView = "Парний перегляд" firstPage = "Перша сторінка" lastPage = "Остання сторінка" -previousPage = "Попередня сторінка" nextPage = "Наступна сторінка" +onlyPdfSupported = "Переглядач підтримує лише файли PDF. Схоже, цей файл має інший формат." +previousPage = "Попередня сторінка" +singlePageView = "Одинарний перегляд" +unknownFile = "Невідомий файл" zoomIn = "Збільшити" zoomOut = "Зменшити" -singlePageView = "Одинарний перегляд" -dualPageView = "Парний перегляд" [rightRail] closeSelected = "Закрити вибрані файли" @@ -3877,6 +3899,7 @@ toggleSidebar = "Перемкнути бічну панель" exportSelected = "Експорт вибраних сторінок" toggleAnnotations = "Перемкнути видимість анотацій" annotationMode = "Перемкнути режим анотацій" +print = "Надрукувати PDF" draw = "Малювати" save = "Зберегти" saveChanges = "Зберегти зміни" @@ -4153,7 +4176,7 @@ description = "Відстежувати дії користувачів і си [admin.settings.security.audit.level] label = "Рівень аудиту" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=ВИМКНЕНО, 1=БАЗОВИЙ, 2=СТАНДАРТ, 3=ДОКЛАДНИЙ" [admin.settings.security.audit.retentionDays] label = "Зберігання аудиту (дні)" @@ -4407,7 +4430,7 @@ description = "Чи очищати ширший системний тимчас label = "Обмеження виконавця процесів" description = "Налаштуйте ліміти сеансів і тайм-аути для кожного виконавця процесів" libreOffice = "LibreOffice" -pdfToHtml = "PDF to HTML" +pdfToHtml = "PDF у HTML" qpdf = "QPDF" tesseract = "Tesseract OCR" pythonOpenCv = "Python OpenCV" @@ -4494,6 +4517,7 @@ description = "URL або назва файлу до імпресуму (пот title = "Преміум і Enterprise" description = "Налаштуйте свій преміум або корпоративний ліцензійний ключ." license = "Конфігурація ліцензії" +noInput = "Надайте ліцензійний ключ або файл" [admin.settings.premium.licenseKey] toggle = "Є ліцензійний ключ або файл сертифіката?" @@ -4511,6 +4535,25 @@ line1 = "Перезапис поточного ліцензійного ключ line2 = "Попередня ліцензія буде втрачена назавжди, якщо ви не маєте її резервної копії." line3 = "Важливо: зберігайте ліцензійні ключі приватними та безпечними. Ніколи не публікуйте їх." +[admin.settings.premium.inputMethod] +text = "Ліцензійний ключ" +file = "Файл сертифіката" + +[admin.settings.premium.file] +label = "Файл ліцензійного сертифіката" +description = "Завантажте свій ліцензійний файл .lic або .cert з офлайн-покупок" +choose = "Виберіть ліцензійний файл" +selected = "Вибрано: {{filename}} ({{size}})" +successMessage = "Ліцензійний файл успішно завантажено й активовано. Перезапуск не потрібен." + +[admin.settings.premium.currentLicense] +title = "Активна ліцензія" +file = "Джерело: ліцензійний файл ({{path}})" +key = "Джерело: ліцензійний ключ" +type = "Тип: {{type}}" +noInput = "Надайте ліцензійний ключ або завантажте файл сертифіката" +success = "Успішно" + [admin.settings.premium.enabled] label = "Увімкнути преміум-функції" description = "Увімкнути перевірку ліцензійного ключа для pro/enterprise функцій" @@ -4644,7 +4687,9 @@ selectedCount = "Вибрано {{count}}" download = "Завантажити" delete = "Видалити" unsupported = "Непідтримуваний" +active = "Активний" addToUpload = "Додати до завантаження" +closeFile = "Закрити файл" deleteAll = "Видалити все" loadingFiles = "Завантаження файлів..." noFiles = "Немає доступних файлів" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Потрібна щонайменше одна електронна адреса" submit = "Надіслати запрошення" success = "Користувача(ів) успішно запрошено" -partialSuccess = "Деякі запрошення не вдалося надіслати" +partialFailure = "Деякі запрошення не вдалося надіслати" allFailed = "Не вдалося запросити користувачів" error = "Не вдалося надіслати запрошення" @@ -5281,7 +5326,7 @@ submit = "Згенерувати посилання-запрошення" [workspace.people.inviteMode] username = "Ім’я користувача" -email = "Email" +email = "Електронна пошта" link = "Посилання" emailDisabled = "Запрошення електронною поштою потребують налаштування SMTP і mail.enableInvites=true в налаштуваннях" @@ -5797,13 +5842,20 @@ submit = "Увійти" signInWith = "Увійти через" oauthPending = "Відкриваємо браузер для автентифікації..." orContinueWith = "Або продовжити через email" +serverRequirement = "Примітка: на сервері має бути увімкнено вхід." +showInstructions = "Як увімкнути?" +hideInstructions = "Приховати інструкції" +instructions = "Щоб увімкнути вхід на вашому сервері Stirling PDF:" +instructionsEnvVar = "Задайте змінну середовища:" +instructionsOrYml = "Або у settings.yml:" +instructionsRestart = "Потім перезапустіть сервер, щоб зміни набрали чинності." [setup.login.username] label = "Ім’я користувача" placeholder = "Введіть ім’я користувача" [setup.login.email] -label = "Email" +label = "Електронна пошта" placeholder = "Введіть свій email" [setup.login.password] diff --git a/frontend/public/locales/vi-VN/translation.toml b/frontend/public/locales/vi-VN/translation.toml index 464407a2a..7e9860bb9 100644 --- a/frontend/public/locales/vi-VN/translation.toml +++ b/frontend/public/locales/vi-VN/translation.toml @@ -163,6 +163,11 @@ unfavorite = "Xóa khỏi Mục yêu thích" fullscreen = "Chuyển sang chế độ toàn màn hình" sidebar = "Chuyển sang chế độ thanh bên" +[backendStartup] +notFoundTitle = "Không tìm thấy Backend" +retry = "Thử lại" +unreachable = "Ứng dụng hiện không thể kết nối tới Backend. Hãy kiểm tra trạng thái Backend và kết nối mạng, sau đó thử lại." + [zipWarning] title = "Tệp ZIP lớn" message = "ZIP này chứa {{count}} tệp. Vẫn giải nén?" @@ -347,7 +352,7 @@ teams = "Nhóm" title = "Cấu hình" systemSettings = "Cài đặt hệ thống" features = "Tính năng" -endpoints = "Endpoints" +endpoints = "Điểm cuối" database = "Cơ sở dữ liệu" advanced = "Nâng cao" @@ -359,7 +364,7 @@ connections = "Kết nối" [settings.licensingAnalytics] title = "Giấy phép & Phân tích" plan = "Gói" -audit = "Audit" +audit = "Kiểm toán" usageAnalytics = "Phân tích sử dụng" [settings.policiesPrivacy] @@ -369,7 +374,7 @@ privacy = "Quyền riêng tư" [settings.developer] title = "Nhà phát triển" -apiKeys = "API Keys" +apiKeys = "Khóa API" [settings.tooltips] enableLoginFirst = "Bật chế độ đăng nhập trước" @@ -912,6 +917,9 @@ desc = "Xây dựng quy trình nhiều bước bằng cách xâu chuỗi các th desc = "Chồng lớp PDF lên trên PDF khác" title = "Chồng lớp PDF" +[home.pdfTextEditor] +title = "Trình chỉnh sửa văn bản PDF" +desc = "Chỉnh sửa văn bản và hình ảnh hiện có bên trong PDF" [home.addText] tags = "văn bản,chú thích,nhãn" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "Chọn tệp trong khung chính để bắt đầu" settings = "Cài đặt" conversionCompleted = "Hoàn tất chuyển đổi" results = "Kết quả" -defaultFilename = "converted_file" +defaultFilename = "tep_da_chuyen_doi" conversionResults = "Kết quả chuyển đổi" convertFrom = "Chuyển từ" convertTo = "Sang" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "Chữ ký vẽ" defaultImageLabel = "Chữ ký đã tải lên" defaultTextLabel = "Chữ ký nhập" saveButton = "Lưu chữ ký" +savePersonal = "Lưu cá nhân" +saveShared = "Lưu dùng chung" saveUnavailable = "Hãy tạo chữ ký trước để lưu." noChanges = "Chữ ký hiện tại đã được lưu." +tempStorageTitle = "Bộ nhớ tạm của trình duyệt" +tempStorageDescription = "Chữ ký chỉ được lưu trong trình duyệt của bạn. Chúng sẽ bị mất nếu bạn xóa dữ liệu trình duyệt hoặc đổi sang trình duyệt khác." +personalHeading = "Chữ ký cá nhân" +sharedHeading = "Chữ ký dùng chung" +personalDescription = "Chỉ mình bạn có thể xem các chữ ký này." +sharedDescription = "Tất cả người dùng đều có thể xem và sử dụng các chữ ký này." [sign.saved.type] canvas = "Vẽ" @@ -2567,7 +2583,7 @@ stopButton = "Dừng so sánh" [certSign] tags = "xác thực,PEM,P12,chính thức,mã hóa" title = "Ký bằng chứng chỉ" -filenamePrefix = "signed" +filenamePrefix = "da_ky" chooseCertificate = "Chọn tệp chứng chỉ" chooseJksFile = "Chọn tệp JKS" chooseP12File = "Chọn tệp PKCS12" @@ -2701,7 +2717,7 @@ header = "Xóa chứng chỉ số khỏi PDF" selectPDF = "Chọn một tệp PDF:" submit = "Xóa chữ ký" description = "Công cụ này sẽ xóa chữ ký chứng chỉ số khỏi tài liệu PDF của bạn." -filenamePrefix = "unsigned" +filenamePrefix = "chua_ky" [removeCertSign.files] placeholder = "Chọn một tệp PDF trong màn hình chính để bắt đầu" @@ -3438,6 +3454,9 @@ signinTitle = "Vui lòng đăng nhập" ssoSignIn = "Đăng nhập qua Single Sign-on" oAuth2AutoCreateDisabled = "Tự động tạo người dùng OAUTH2 bị vô hiệu hóa" oAuth2AdminBlockedUser = "Hiện đang chặn đăng ký hoặc đăng nhập người dùng chưa đăng ký. Vui lòng liên hệ quản trị viên." +oAuth2RequiresLicense = "Đăng nhập OAuth/SSO cần giấy phép trả phí (Server hoặc Enterprise). Vui lòng liên hệ quản trị viên để nâng cấp gói của bạn." +saml2RequiresLicense = "Đăng nhập SAML cần giấy phép trả phí (Server hoặc Enterprise). Vui lòng liên hệ quản trị viên để nâng cấp gói của bạn." +maxUsersReached = "Đã đạt số lượng người dùng tối đa cho giấy phép hiện tại của bạn. Vui lòng liên hệ quản trị viên để nâng cấp gói hoặc thêm suất." oauth2RequestNotFound = "Không tìm thấy yêu cầu ủy quyền" oauth2InvalidUserInfoResponse = "Phản hồi thông tin người dùng không hợp lệ" oauth2invalidRequest = "Yêu cầu không hợp lệ" @@ -3533,7 +3552,7 @@ title = "PDF thành một trang" header = "PDF thành một trang" submit = "Chuyển đổi thành một trang" description = "Công cụ này sẽ gộp tất cả các trang của PDF của bạn thành một trang đơn lớn. Chiều rộng giữ nguyên như các trang gốc, còn chiều cao sẽ bằng tổng chiều cao của tất cả các trang." -filenamePrefix = "single_page" +filenamePrefix = "mot_trang" [pdfToSinglePage.files] placeholder = "Chọn một tệp PDF ở màn hình chính để bắt đầu" @@ -3846,14 +3865,17 @@ fitToWidth = "Vừa chiều rộng" actualSize = "Kích thước thật" [viewer] +cannotPreviewFile = "Không thể xem trước tệp" +dualPageView = "Chế độ xem hai trang" firstPage = "Trang đầu" lastPage = "Trang cuối" -previousPage = "Trang trước" nextPage = "Trang tiếp" +onlyPdfSupported = "Trình xem chỉ hỗ trợ tệp PDF. Tệp này có vẻ là định dạng khác." +previousPage = "Trang trước" +singlePageView = "Chế độ xem trang đơn" +unknownFile = "Tệp không xác định" zoomIn = "Phóng to" zoomOut = "Thu nhỏ" -singlePageView = "Chế độ xem trang đơn" -dualPageView = "Chế độ xem hai trang" [rightRail] closeSelected = "Đóng các tệp đã chọn" @@ -3877,6 +3899,7 @@ toggleSidebar = "Chuyển đổi thanh bên" exportSelected = "Xuất các trang đã chọn" toggleAnnotations = "Chuyển đổi hiển thị chú thích" annotationMode = "Chuyển đổi chế độ chú thích" +print = "In PDF" draw = "Vẽ" save = "Lưu" saveChanges = "Lưu thay đổi" @@ -4494,6 +4517,7 @@ description = "URL hoặc tên tệp cho impressum (bắt buộc ở một số title = "Premium & Enterprise" description = "Cấu hình khóa giấy phép premium hoặc enterprise của bạn." license = "Cấu hình giấy phép" +noInput = "Vui lòng cung cấp khóa giấy phép hoặc tệp" [admin.settings.premium.licenseKey] toggle = "Có license key hoặc tệp chứng chỉ?" @@ -4511,6 +4535,25 @@ line1 = "Ghi đè license key hiện tại không thể hoàn tác." line2 = "License trước đó sẽ bị mất vĩnh viễn trừ khi bạn đã sao lưu ở nơi khác." line3 = "Quan trọng: Giữ license key riêng tư và an toàn. Không bao giờ chia sẻ công khai." +[admin.settings.premium.inputMethod] +text = "Khóa giấy phép" +file = "Tệp chứng chỉ" + +[admin.settings.premium.file] +label = "Tệp chứng chỉ giấy phép" +description = "Tải lên tệp giấy phép .lic hoặc .cert từ các lần mua ngoại tuyến của bạn" +choose = "Chọn tệp giấy phép" +selected = "Đã chọn: {{filename}} ({{size}})" +successMessage = "Tệp giấy phép đã được tải lên và kích hoạt thành công. Không cần khởi động lại." + +[admin.settings.premium.currentLicense] +title = "Giấy phép đang hoạt động" +file = "Nguồn: Tệp giấy phép ({{path}})" +key = "Nguồn: Khóa giấy phép" +type = "Loại: {{type}}" +noInput = "Vui lòng cung cấp khóa giấy phép hoặc tải lên tệp chứng chỉ" +success = "Thành công" + [admin.settings.premium.enabled] label = "Bật tính năng Premium" description = "Bật kiểm tra khóa giấy phép cho các tính năng pro/enterprise" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} đã chọn" download = "Tải xuống" delete = "Xóa" unsupported = "Không được hỗ trợ" +active = "Hoạt động" addToUpload = "Thêm vào tải lên" +closeFile = "Đóng tệp" deleteAll = "Xóa tất cả" loadingFiles = "Đang tải tệp..." noFiles = "Không có tệp nào" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "Yêu cầu ít nhất một địa chỉ email" submit = "Gửi lời mời" success = "Mời người dùng thành công" -partialSuccess = "Một số lời mời thất bại" +partialFailure = "Một số lời mời không thành công" allFailed = "Mời người dùng thất bại" error = "Gửi lời mời thất bại" @@ -5797,6 +5842,13 @@ submit = "Đăng nhập" signInWith = "Đăng nhập với" oauthPending = "Đang mở trình duyệt để xác thực..." orContinueWith = "Hoặc tiếp tục bằng email" +serverRequirement = "Lưu ý: Máy chủ phải bật đăng nhập." +showInstructions = "Cách bật?" +hideInstructions = "Ẩn hướng dẫn" +instructions = "Để bật đăng nhập trên máy chủ Stirling PDF của bạn:" +instructionsEnvVar = "Đặt biến môi trường:" +instructionsOrYml = "Hoặc trong settings.yml:" +instructionsRestart = "Sau đó khởi động lại máy chủ để các thay đổi có hiệu lực." [setup.login.username] label = "Tên người dùng" diff --git a/frontend/public/locales/zh-BO/translation.toml b/frontend/public/locales/zh-BO/translation.toml index efbc9cb91..847e423d0 100644 --- a/frontend/public/locales/zh-BO/translation.toml +++ b/frontend/public/locales/zh-BO/translation.toml @@ -163,6 +163,11 @@ unfavorite = "从收藏中移除" fullscreen = "切换到全屏模式" sidebar = "切换到侧边栏模式" +[backendStartup] +notFoundTitle = "未找到后端" +retry = "重试" +unreachable = "应用目前无法连接到后端。请检查后端状态和网络连接,然后重试。" + [zipWarning] title = "大型 ZIP 文件" message = "此 ZIP 包含 {{count}} 个文件。仍要解压吗?" @@ -912,6 +917,9 @@ desc = "通过串联 PDF 动作构建多步工作流。适合重复性任务。" desc = "PDF གཞན་ཞིག་གི་སྟེང་དུ་ PDF བརྩེགས་པ།" title = "PDF སྟེང་བརྩེགས།" +[home.pdfTextEditor] +title = "PDF 文本编辑器" +desc = "编辑 PDF 中的现有文本和图像" [home.addText] tags = "文本,注释,标签" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "手写签名" defaultImageLabel = "已上传的签名" defaultTextLabel = "键入的签名" saveButton = "保存签名" +savePersonal = "保存为个人" +saveShared = "保存为共享" saveUnavailable = "请先创建签名再保存。" noChanges = "当前签名已保存。" +tempStorageTitle = "浏览器临时存储" +tempStorageDescription = "签名仅存储在您的浏览器中。若清除浏览器数据或更换浏览器,这些签名将会丢失。" +personalHeading = "个人签名" +sharedHeading = "共享签名" +personalDescription = "只有您可以看到这些签名。" +sharedDescription = "所有用户都可以查看并使用这些签名。" [sign.saved.type] canvas = "绘制" @@ -3438,6 +3454,9 @@ signinTitle = "ནང་འཛུལ་གནང་རོགས།" ssoSignIn = "གཅིག་གྱུར་ནང་འཛུལ་བརྒྱུད་ནས་ནང་འཛུལ།" oAuth2AutoCreateDisabled = "OAUTH2 རང་འགུལ་སྤྱོད་མཁན་གསར་བཟོ་བཀག་སྡོམ་བྱས་ཟིན།" oAuth2AdminBlockedUser = "ད་ལྟ་ཐོ་འགོད་མ་བྱས་པའི་སྤྱོད་མཁན་གྱི་ཐོ་འགོད་དང་ནང་འཛུལ་བཀག་སྡོམ་བྱས་ཡོད། དོ་དམ་པར་འབྲེལ་བ་གནང་རོགས།" +oAuth2RequiresLicense = "使用 OAuth/SSO 登录需要付费许可(Server 或 Enterprise)。请联系管理员升级您的方案。" +saml2RequiresLicense = "使用 SAML 登录需要付费许可(Server 或 Enterprise)。请联系管理员升级您的方案。" +maxUsersReached = "您当前的许可已达到最大用户数。请联系管理员升级您的方案或增加席位。" oauth2RequestNotFound = "དབང་སྤྲོད་རེ་ཞུ་རྙེད་མ་བྱུང་།" oauth2InvalidUserInfoResponse = "སྤྱོད་མཁན་གྱི་གནས་ཚུལ་ལན་འདེབས་ནོར་འཁྲུལ།" oauth2invalidRequest = "རེ་ཞུ་ནོར་འཁྲུལ།" @@ -3846,14 +3865,17 @@ fitToWidth = "适应宽度" actualSize = "实际大小" [viewer] +cannotPreviewFile = "无法预览文件" +dualPageView = "双页视图" firstPage = "第一页" lastPage = "最后一页" -previousPage = "上一页" nextPage = "下一页" +onlyPdfSupported = "此查看器仅支持 PDF 文件。该文件似乎为其他格式。" +previousPage = "上一页" +singlePageView = "单页视图" +unknownFile = "未知文件" zoomIn = "放大" zoomOut = "缩小" -singlePageView = "单页视图" -dualPageView = "双页视图" [rightRail] closeSelected = "关闭所选文件" @@ -3877,6 +3899,7 @@ toggleSidebar = "切换侧边栏" exportSelected = "导出所选页面" toggleAnnotations = "切换注释可见性" annotationMode = "切换注释模式" +print = "打印 PDF" draw = "绘制" save = "保存" saveChanges = "保存更改" @@ -4494,6 +4517,7 @@ description = "Impressum 的 URL 或文件名(某些司法管辖区要求)" title = "高级与企业版" description = "配置你的高级或企业许可证密钥。" license = "许可证配置" +noInput = "请提供许可证密钥或文件" [admin.settings.premium.licenseKey] toggle = "有许可证密钥或证书文件?" @@ -4511,6 +4535,25 @@ line1 = "覆盖当前许可证密钥后将无法撤销。" line2 = "除非另有备份,否则之前的许可证将被永久丢失。" line3 = "重要:请妥善保管许可证密钥,切勿公开分享。" +[admin.settings.premium.inputMethod] +text = "许可证密钥" +file = "证书文件" + +[admin.settings.premium.file] +label = "许可证证书文件" +description = "上传您线下购买的 .lic 或 .cert 许可证文件" +choose = "选择许可证文件" +selected = "已选择:{{filename}}({{size}})" +successMessage = "许可证文件上传并激活成功。无需重启。" + +[admin.settings.premium.currentLicense] +title = "已激活的许可证" +file = "来源:许可证文件({{path}})" +key = "来源:许可证密钥" +type = "类型:{{type}}" +noInput = "请提供许可证密钥或上传证书文件" +success = "成功" + [admin.settings.premium.enabled] label = "启用高级功能" description = "为专业/企业功能启用许可证密钥检查" @@ -4644,7 +4687,9 @@ selectedCount = "已选 {{count}} 个" download = "下载" delete = "删除" unsupported = "不支持" +active = "已启用" addToUpload = "添加到上传" +closeFile = "关闭文件" deleteAll = "全部删除" loadingFiles = "正在加载文件..." noFiles = "暂无文件" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "至少需要一个邮箱地址" submit = "发送邀请" success = "已成功邀请用户" -partialSuccess = "部分邀请失败" +partialFailure = "部分邀请发送失败" allFailed = "邀请用户失败" error = "发送邀请失败" @@ -5797,6 +5842,13 @@ submit = "登录" signInWith = "登录方式" oauthPending = "正在打开浏览器进行认证..." orContinueWith = "或使用邮箱继续" +serverRequirement = "注意:服务器必须启用登录功能。" +showInstructions = "如何启用?" +hideInstructions = "隐藏说明" +instructions = "在您的 Stirling PDF 服务器上启用登录功能:" +instructionsEnvVar = "设置环境变量:" +instructionsOrYml = "或在 settings.yml 中:" +instructionsRestart = "然后重启服务器以使更改生效。" [setup.login.username] label = "用户名" diff --git a/frontend/public/locales/zh-CN/translation.toml b/frontend/public/locales/zh-CN/translation.toml index 2d166272c..fed6c1d60 100644 --- a/frontend/public/locales/zh-CN/translation.toml +++ b/frontend/public/locales/zh-CN/translation.toml @@ -163,6 +163,11 @@ unfavorite = "从收藏中移除" fullscreen = "切换到全屏模式" sidebar = "切换到侧边栏模式" +[backendStartup] +notFoundTitle = "未找到后端" +retry = "重试" +unreachable = "应用程序当前无法连接到后端。请检查后端状态和网络连接,然后重试。" + [zipWarning] title = "大型 ZIP 文件" message = "此 ZIP 包含 {{count}} 个文件。仍要解压?" @@ -912,6 +917,9 @@ desc = "通过串联 PDF 操作构建多步工作流。适合重复性任务。" desc = "将一个 PDF 叠加在另一个之上" title = "叠加 PDF" +[home.pdfTextEditor] +title = "PDF 文本编辑器" +desc = "编辑 PDF 中的现有文本和图像" [home.addText] tags = "文本,注释,标签" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "手写签名" defaultImageLabel = "已上传签名" defaultTextLabel = "键入签名" saveButton = "保存签名" +savePersonal = "保存到个人" +saveShared = "保存到共享" saveUnavailable = "请先创建签名再保存。" noChanges = "当前签名已保存。" +tempStorageTitle = "临时浏览器存储" +tempStorageDescription = "签名仅存储在您的浏览器中。清除浏览器数据或更换浏览器后将会丢失。" +personalHeading = "个人签名" +sharedHeading = "共享签名" +personalDescription = "只有您可以看到这些签名。" +sharedDescription = "所有用户都可以查看并使用这些签名。" [sign.saved.type] canvas = "手写" @@ -2574,7 +2590,7 @@ chooseP12File = "选择 PKCS12 文件" choosePfxFile = "选择 PFX 文件" choosePrivateKey = "选择私钥文件" location = "位置" -logoTitle = "Logo" +logoTitle = "徽标" name = "名称" noLogo = "无 Logo" pageNumber = "页码" @@ -3438,6 +3454,9 @@ signinTitle = "请登录" ssoSignIn = "通过单点登录登录" oAuth2AutoCreateDisabled = "OAuth2 自动创建用户已禁用" oAuth2AdminBlockedUser = "目前已阻止未注册用户的注册或登录。请联系管理员。" +oAuth2RequiresLicense = "OAuth/SSO 登录需要付费许可(Server 或 Enterprise)。请联系管理员以升级您的计划。" +saml2RequiresLicense = "SAML 登录需要付费许可(Server 或 Enterprise)。请联系管理员以升级您的计划。" +maxUsersReached = "您当前的许可已达到用户数量上限。请联系管理员以升级您的计划或增加席位。" oauth2RequestNotFound = "找不到验证请求" oauth2InvalidUserInfoResponse = "无效的用户信息响应" oauth2invalidRequest = "无效请求" @@ -3846,14 +3865,17 @@ fitToWidth = "适配宽度" actualSize = "实际大小" [viewer] +cannotPreviewFile = "无法预览文件" +dualPageView = "双页视图" firstPage = "第一页" lastPage = "最后一页" -previousPage = "上一页" nextPage = "下一页" +onlyPdfSupported = "该查看器仅支持 PDF 文件。此文件似乎是其他格式。" +previousPage = "上一页" +singlePageView = "单页视图" +unknownFile = "未知文件" zoomIn = "放大" zoomOut = "缩小" -singlePageView = "单页视图" -dualPageView = "双页视图" [rightRail] closeSelected = "关闭所选文件" @@ -3877,6 +3899,7 @@ toggleSidebar = "切换侧边栏" exportSelected = "导出所选页面" toggleAnnotations = "切换注释可见性" annotationMode = "切换注释模式" +print = "打印 PDF" draw = "绘制" save = "保存" saveChanges = "保存更改" @@ -4494,6 +4517,7 @@ description = "Impressum 的 URL 或文件名(某些司法辖区要求)" title = "高级版与企业版" description = "配置您的高级版或企业版许可证密钥。" license = "许可证配置" +noInput = "请提供许可证密钥或文件" [admin.settings.premium.licenseKey] toggle = "有许可证密钥或证书文件吗?" @@ -4511,6 +4535,25 @@ line1 = "覆盖当前许可证密钥后将无法撤销。" line2 = "除非已在其他位置备份,否则您之前的许可证将被永久丢失。" line3 = "重要:请妥善保管许可证密钥,切勿公开分享。" +[admin.settings.premium.inputMethod] +text = "许可证密钥" +file = "证书文件" + +[admin.settings.premium.file] +label = "许可证证书文件" +description = "上传您线下购买的 .lic 或 .cert 许可证文件" +choose = "选择许可证文件" +selected = "已选择:{{filename}}({{size}})" +successMessage = "许可证文件已成功上传并激活。无需重启。" + +[admin.settings.premium.currentLicense] +title = "已激活的许可证" +file = "来源:许可证文件({{path}})" +key = "来源:许可证密钥" +type = "类型:{{type}}" +noInput = "请提供许可证密钥或上传证书文件" +success = "成功" + [admin.settings.premium.enabled] label = "启用高级功能" description = "启用对专业/企业功能的许可证密钥检查" @@ -4622,7 +4665,7 @@ searchFiles = "搜索文件…" recent = "最近" localFiles = "本地文件" googleDrive = "Google 云端硬盘" -googleDriveShort = "Drive" +googleDriveShort = "云端硬盘" myFiles = "我的文件" noRecentFiles = "未找到最近文件" googleDriveNotAvailable = "不可使用 Google 云端硬盘集成" @@ -4644,7 +4687,9 @@ selectedCount = "已选 {{count}}" download = "下载" delete = "删除" unsupported = "不支持" +active = "活跃" addToUpload = "添加至上传" +closeFile = "关闭文件" deleteAll = "删除全部" loadingFiles = "正在加载文件..." noFiles = "没有可用的文件" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "至少需要一个电子邮件地址" submit = "发送邀请" success = "已成功邀请用户" -partialSuccess = "部分邀请失败" +partialFailure = "部分邀请失败" allFailed = "邀请用户失败" error = "发送邀请失败" @@ -5797,6 +5842,13 @@ submit = "登录" signInWith = "使用以下方式登录" oauthPending = "正在打开浏览器进行认证..." orContinueWith = "或使用 Email 继续" +serverRequirement = "注意:服务器必须启用登录功能。" +showInstructions = "如何启用?" +hideInstructions = "隐藏说明" +instructions = "要在您的 Stirling PDF 服务器上启用登录:" +instructionsEnvVar = "设置环境变量:" +instructionsOrYml = "或在 settings.yml 中:" +instructionsRestart = "然后重启服务器以使更改生效。" [setup.login.username] label = "用户名" diff --git a/frontend/public/locales/zh-TW/translation.toml b/frontend/public/locales/zh-TW/translation.toml index 55b4e6b52..8b2f97b5d 100644 --- a/frontend/public/locales/zh-TW/translation.toml +++ b/frontend/public/locales/zh-TW/translation.toml @@ -163,6 +163,11 @@ unfavorite = "從我的最愛移除" fullscreen = "切換至全螢幕模式" sidebar = "切換至側邊欄模式" +[backendStartup] +notFoundTitle = "找不到後端" +retry = "重試" +unreachable = "應用程式目前無法連線至後端。請確認後端狀態與網路連線,然後再試一次。" + [zipWarning] title = "大型 ZIP 檔案" message = "此 ZIP 包含 {{count}} 個檔案。仍要解壓縮嗎?" @@ -912,6 +917,9 @@ desc = "將多個 PDF 動作串接,建立多步驟工作流程。適合重複 desc = "將 PDF 覆蓋在另一個 PDF 上" title = "覆蓋 PDF" +[home.pdfTextEditor] +title = "PDF 文字編輯器" +desc = "編輯 PDF 中既有的文字與圖片" [home.addText] tags = "文字,註解,標籤" @@ -1173,7 +1181,7 @@ selectFilesPlaceholder = "在主視圖選取檔案以開始" settings = "設定" conversionCompleted = "轉換完成" results = "結果" -defaultFilename = "converted_file" +defaultFilename = "已轉換_檔案" conversionResults = "轉換結果" convertFrom = "來源格式" convertTo = "目標格式" @@ -1360,7 +1368,7 @@ title = "新增浮水印" desc = "將文字或影像浮水印加入 PDF 檔案" completed = "已加入浮水印" submit = "新增浮水印" -filenamePrefix = "watermarked" +filenamePrefix = "已加_浮水印" [watermark.error] failed = "為 PDF 新增浮水印時發生錯誤。" @@ -2259,8 +2267,16 @@ defaultCanvasLabel = "手繪簽名" defaultImageLabel = "上傳的簽名" defaultTextLabel = "輸入的簽名" saveButton = "儲存簽名" +savePersonal = "儲存為個人" +saveShared = "儲存為共用" saveUnavailable = "請先建立簽名才能儲存。" noChanges = "目前簽名已儲存。" +tempStorageTitle = "瀏覽器暫存" +tempStorageDescription = "簽名僅儲存在您的瀏覽器中。若清除瀏覽資料或更換瀏覽器,將會遺失。" +personalHeading = "個人簽名" +sharedHeading = "共用簽名" +personalDescription = "只有您能看到這些簽名。" +sharedDescription = "所有使用者都可以查看並使用這些簽名。" [sign.saved.type] canvas = "手繪" @@ -3438,6 +3454,9 @@ signinTitle = "請登入" ssoSignIn = "透過 SSO 單一登入" oAuth2AutoCreateDisabled = "OAuth 2.0 自動建立使用者功能已停用" oAuth2AdminBlockedUser = "目前不允許未註冊的使用者註冊或登入。請聯絡系統管理員。" +oAuth2RequiresLicense = "OAuth/SSO 登入需要付費授權(Server 或 Enterprise)。請聯絡管理員升級您的方案。" +saml2RequiresLicense = "SAML 登入需要付費授權(Server 或 Enterprise)。請聯絡管理員升級您的方案。" +maxUsersReached = "您目前的授權已達使用者上限。請聯絡管理員以升級方案或新增席次。" oauth2RequestNotFound = "找不到驗證請求" oauth2InvalidUserInfoResponse = "使用者資訊回應無效" oauth2invalidRequest = "請求無效" @@ -3533,7 +3552,7 @@ title = "PDF 轉為單一頁面" header = "PDF 轉為單一頁面" submit = "轉換為單一頁面" description = "此工具會將 PDF 的所有頁面合併成一個大型單頁。寬度將與原頁相同,但高度會是所有頁面高度之總和。" -filenamePrefix = "single_page" +filenamePrefix = "單一_頁面" [pdfToSinglePage.files] placeholder = "在主畫面選擇一個 PDF 檔開始使用" @@ -3846,14 +3865,17 @@ fitToWidth = "適合寬度" actualSize = "實際大小" [viewer] +cannotPreviewFile = "無法預覽檔案" +dualPageView = "雙頁檢視" firstPage = "第一頁" lastPage = "最後一頁" -previousPage = "上一頁" nextPage = "下一頁" +onlyPdfSupported = "此檢視器僅支援 PDF 檔案。此檔案似乎是其他格式。" +previousPage = "上一頁" +singlePageView = "單頁檢視" +unknownFile = "未知檔案" zoomIn = "放大" zoomOut = "縮小" -singlePageView = "單頁檢視" -dualPageView = "雙頁檢視" [rightRail] closeSelected = "關閉已選檔案" @@ -3877,6 +3899,7 @@ toggleSidebar = "切換側邊欄" exportSelected = "匯出選取的頁面" toggleAnnotations = "切換註解可見度" annotationMode = "切換註解模式" +print = "列印 PDF" draw = "繪圖" save = "儲存" saveChanges = "儲存變更" @@ -4494,6 +4517,7 @@ description = "Impressum 的 URL 或檔名(某些司法管轄區要求提供 title = "Premium 與 Enterprise" description = "設定您的 Premium 或 Enterprise 授權金鑰。" license = "擴充授權設定" +noInput = "請提供授權金鑰或檔案" [admin.settings.premium.licenseKey] toggle = "有授權金鑰或憑證檔嗎?" @@ -4511,6 +4535,25 @@ line1 = "覆寫目前的授權金鑰後將無法復原。" line2 = "除非你另有備份,否則先前的授權將永久遺失。" line3 = "重要:請妥善保管授權金鑰並保持私密,切勿公開分享。" +[admin.settings.premium.inputMethod] +text = "授權金鑰" +file = "憑證檔案" + +[admin.settings.premium.file] +label = "授權憑證檔案" +description = "上傳您離線購買的 .lic 或 .cert 授權檔案" +choose = "選擇授權檔案" +selected = "已選取:{{filename}}({{size}})" +successMessage = "授權檔案已成功上傳並啟用,無需重新啟動。" + +[admin.settings.premium.currentLicense] +title = "使用中的授權" +file = "來源:授權檔案({{path}})" +key = "來源:授權金鑰" +type = "類型:{{type}}" +noInput = "請提供授權金鑰或上傳憑證檔案" +success = "成功" + [admin.settings.premium.enabled] label = "啟用 Premium 功能" description = "啟用對進階/企業功能的授權金鑰檢查" @@ -4644,7 +4687,9 @@ selectedCount = "{{count}} 個已選" download = "下載" delete = "刪除" unsupported = "不支援" +active = "啟用" addToUpload = "加入上傳" +closeFile = "關閉檔案" deleteAll = "全部刪除" loadingFiles = "正在載入檔案..." noFiles = "沒有可用的檔案" @@ -5245,7 +5290,7 @@ emailsPlaceholder = "user1@example.com, user2@example.com" emailsRequired = "至少需要一個電子郵件地址" submit = "發送邀請" success = "已成功邀請使用者" -partialSuccess = "部分邀請失敗" +partialFailure = "部分邀請失敗" allFailed = "邀請使用者失敗" error = "發送邀請失敗" @@ -5797,13 +5842,20 @@ submit = "登入" signInWith = "以此登入" oauthPending = "正在開啟瀏覽器進行驗證..." orContinueWith = "或改用 Email 繼續" +serverRequirement = "注意:伺服器必須啟用登入功能。" +showInstructions = "如何啟用?" +hideInstructions = "隱藏說明" +instructions = "在您的 Stirling PDF 伺服器上啟用登入功能:" +instructionsEnvVar = "設定環境變數:" +instructionsOrYml = "或在 settings.yml 中:" +instructionsRestart = "然後重新啟動伺服器以套用變更。" [setup.login.username] label = "使用者名稱" placeholder = "輸入你的使用者名稱" [setup.login.email] -label = "Email" +label = "電子郵件" placeholder = "輸入你的 Email" [setup.login.password] diff --git a/scripts/convert_properties_to_json.py b/scripts/convert_properties_to_json.py deleted file mode 100644 index 991550fb6..000000000 --- a/scripts/convert_properties_to_json.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 -""" -Convert Java .properties files to JSON for react-i18next -Preserves hierarchical structure and handles special cases -""" - -import os -import json -import re -from pathlib import Path - -def properties_to_dict(file_path): - """Convert .properties file to nested dictionary""" - result = {} - - with open(file_path, 'r', encoding='utf-8') as f: - for line_num, line in enumerate(f, 1): - line = line.strip() - - # Skip empty lines and comments - if not line or line.startswith('#'): - continue - - # Handle key=value pairs - if '=' in line: - key, value = line.split('=', 1) - key = key.strip() - value = value.strip() - - # Handle multiline values (ending with \) - while value.endswith('\\'): - next_line = next(f, '').strip() - value = value[:-1] + next_line - - # Create nested structure from dot notation - set_nested_value(result, key, value) - - return result - -def set_nested_value(dictionary, key_path, value): - """Set value in nested dictionary using dot notation""" - keys = key_path.split('.') - current = dictionary - - for key in keys[:-1]: - if key not in current: - current[key] = {} - elif not isinstance(current[key], dict): - # Convert existing string value to nested object - old_value = current[key] - current[key] = {"_value": old_value} - current = current[key] - - final_key = keys[-1] - if final_key in current and isinstance(current[final_key], dict): - # If the final key already exists as an object, store the value under "_value" - current[final_key]["_value"] = value - else: - current[final_key] = value - -def convert_all_properties(): - """Convert all messages_*.properties files to JSON""" - - # Get project root - script_dir = Path(__file__).parent - project_root = script_dir.parent - resources_dir = project_root / 'src' / 'main' / 'resources' - output_dir = project_root / 'frontend' / 'public' / 'locales' - - # Create output directory - output_dir.mkdir(parents=True, exist_ok=True) - - # Find all .properties files - properties_files = list(resources_dir.glob('messages*.properties')) - - converted_count = 0 - - for props_file in properties_files: - # Extract locale from filename - filename = props_file.name - if filename == 'messages.properties': - locale = 'en' # Default locale - else: - # Extract locale from messages_en_US.properties format - locale_match = re.match(r'messages_(.+)\.properties', filename) - if locale_match: - locale = locale_match.group(1) - # Convert Java locale format to standard (en_US -> en-US) - locale = locale.replace('_', '-') - else: - continue - - print(f"Converting {filename} -> {locale}.json") - - # Convert to dictionary - data = properties_to_dict(props_file) - - # Create locale directory - locale_dir = output_dir / locale - locale_dir.mkdir(exist_ok=True) - - # Write translation.json (react-i18next default namespace) - output_file = locale_dir / 'translation.json' - with open(output_file, 'w', encoding='utf-8') as f: - json.dump(data, f, indent=2, ensure_ascii=False) - - converted_count += 1 - - print(f"\nConverted {converted_count} language files to {output_dir}") - print("Languages available:", [d.name for d in output_dir.iterdir() if d.is_dir()]) - -if __name__ == '__main__': - convert_all_properties() \ No newline at end of file diff --git a/scripts/counter_translation.py b/scripts/counter_translation.py deleted file mode 100644 index 3d0d8f3b9..000000000 --- a/scripts/counter_translation.py +++ /dev/null @@ -1,219 +0,0 @@ -"""A script to update language progress status in README.md based on -properties file comparison. - -This script compares default properties file with others in a directory to -determine language progress. -It then updates README.md based on provided progress list. - -Author: Ludy87 - -Example: - To use this script, simply run it from command line: - $ python counter_translation.py -""" # noqa: D205 - -import glob -import os -import re - -import tomlkit -import tomlkit.toml_file - - -def convert_to_multiline(data: tomlkit.TOMLDocument) -> tomlkit.TOMLDocument: - """Converts 'ignore' and 'missing' arrays to multiline arrays and sorts the first-level keys of the TOML document. - Enhances readability and consistency in the TOML file by ensuring arrays contain unique and sorted entries. - - Parameters: - data (tomlkit.TOMLDocument): The original TOML document containing the data. - - Returns: - tomlkit.TOMLDocument: A new TOML document with sorted keys and properly formatted arrays. - """ # noqa: D205 - sorted_data = tomlkit.document() - for key in sorted(data.keys()): - value = data[key] - if isinstance(value, dict): - new_table = tomlkit.table() - for subkey in ("ignore", "missing"): - if subkey in value: - # Convert the list to a set to remove duplicates, sort it, and convert to multiline for readability - unique_sorted_array = sorted(set(value[subkey])) - array = tomlkit.array() - array.multiline(True) - for item in unique_sorted_array: - array.append(item) - new_table[subkey] = array - sorted_data[key] = new_table - else: - # Add other types of data unchanged - sorted_data[key] = value - return sorted_data - - -def write_readme(progress_list: list[tuple[str, int]]) -> None: - """Updates the progress status in the README.md file based - on the provided progress list. - - Parameters: - progress_list (list[tuple[str, int]]): A list of tuples containing - language and progress percentage. - - Returns: - None - """ # noqa: D205 - with open("README.md", encoding="utf-8") as file: - content = file.readlines() - - for i, line in enumerate(content[2:], start=2): - for progress in progress_list: - language, value = progress - if language in line: - if match := re.search(r"\!\[(\d+(\.\d+)?)%\]\(.*\)", line): - content[i] = line.replace( - match.group(0), - f"![{value}%](https://geps.dev/progress/{value})", - ) - - with open("README.md", "w", encoding="utf-8", newline="\n") as file: - file.writelines(content) - - -def compare_files( - default_file_path, file_paths, ignore_translation_file -) -> list[tuple[str, int]]: - """Compares the default properties file with other - properties files in the directory. - - Parameters: - default_file_path (str): The path to the default properties file. - files_directory (str): The directory containing other properties files. - - Returns: - list[tuple[str, int]]: A list of tuples containing - language and progress percentage. - """ # noqa: D205 - num_lines = sum( - 1 - for line in open(default_file_path, encoding="utf-8") - if line.strip() and not line.strip().startswith("#") - ) - - result_list = [] - sort_ignore_translation: tomlkit.TOMLDocument - - # read toml - with open(ignore_translation_file, encoding="utf-8") as f: - sort_ignore_translation = tomlkit.parse(f.read()) - - for file_path in file_paths: - language = ( - os.path.basename(file_path) - .split("messages_", 1)[1] - .split(".properties", 1)[0] - ) - - fails = 0 - if "en_GB" in language or "en_US" in language: - result_list.append(("en_GB", 100)) - result_list.append(("en_US", 100)) - continue - - if language not in sort_ignore_translation: - sort_ignore_translation[language] = tomlkit.table() - - if ( - "ignore" not in sort_ignore_translation[language] - or len(sort_ignore_translation[language].get("ignore", [])) < 1 - ): - sort_ignore_translation[language]["ignore"] = tomlkit.array( - ["language.direction"] - ) - - # if "missing" not in sort_ignore_translation[language]: - # sort_ignore_translation[language]["missing"] = tomlkit.array() - # elif "language.direction" in sort_ignore_translation[language]["missing"]: - # sort_ignore_translation[language]["missing"].remove("language.direction") - - with ( - open(default_file_path, encoding="utf-8") as default_file, - open(file_path, encoding="utf-8") as file, - ): - for _ in range(5): - next(default_file) - try: - next(file) - except StopIteration: - fails = num_lines - - for line_num, (line_default, line_file) in enumerate( - zip(default_file, file), start=6 - ): - try: - # Ignoring empty lines and lines start with # - if line_default.strip() == "" or line_default.startswith("#"): - continue - default_key, default_value = line_default.split("=", 1) - file_key, file_value = line_file.split("=", 1) - if ( - default_value.strip() == file_value.strip() - and default_key.strip() - not in sort_ignore_translation[language]["ignore"] - ): - print( - f"{language}: Line {line_num} is missing the translation." - ) - # if default_key.strip() not in sort_ignore_translation[language]["missing"]: - # missing_array = tomlkit.array() - # missing_array.append(default_key.strip()) - # missing_array.multiline(True) - # sort_ignore_translation[language]["missing"].extend(missing_array) - fails += 1 - # elif default_key.strip() in sort_ignore_translation[language]["ignore"]: - # if default_key.strip() in sort_ignore_translation[language]["missing"]: - # sort_ignore_translation[language]["missing"].remove(default_key.strip()) - if default_value.strip() != file_value.strip(): - # if default_key.strip() in sort_ignore_translation[language]["missing"]: - # sort_ignore_translation[language]["missing"].remove(default_key.strip()) - if ( - default_key.strip() - in sort_ignore_translation[language]["ignore"] - ): - sort_ignore_translation[language]["ignore"].remove( - default_key.strip() - ) - except ValueError as e: - print(f"Error processing line {line_num} in {file_path}: {e}") - print(f"{line_default}|{line_file}") - exit(1) - except IndexError: - pass - - print(f"{language}: {fails} out of {num_lines} lines are not translated.") - result_list.append( - ( - language, - int((num_lines - fails) * 100 / num_lines), - ) - ) - ignore_translation = convert_to_multiline(sort_ignore_translation) - with open(ignore_translation_file, "w", encoding="utf-8", newline="\n") as file: - file.write(tomlkit.dumps(ignore_translation)) - - unique_data = list(set(result_list)) - unique_data.sort(key=lambda x: x[1], reverse=True) - - return unique_data - - -if __name__ == "__main__": - directory = os.path.join(os.getcwd(), "app", "core", "src", "main", "resources") - messages_file_paths = glob.glob(os.path.join(directory, "messages_*.properties")) - reference_file = os.path.join(directory, "messages_en_GB.properties") - - scripts_directory = os.path.join(os.getcwd(), "scripts") - translation_state_file = os.path.join(scripts_directory, "ignore_translation.toml") - - write_readme( - compare_files(reference_file, messages_file_paths, translation_state_file) - ) diff --git a/scripts/counter_translation_v2.py b/scripts/counter_translation_v3.py similarity index 91% rename from scripts/counter_translation_v2.py rename to scripts/counter_translation_v3.py index 32b3075ad..d77ec285d 100644 --- a/scripts/counter_translation_v2.py +++ b/scripts/counter_translation_v3.py @@ -1,21 +1,21 @@ """A script to update language progress status in README.md based on -JSON translation file comparison. +TOML translation file comparison. -This script compares the default translation JSON file with others in the locales directory to +This script compares the default translation TOML file with others in the locales directory to determine language progress. It then updates README.md based on provided progress list. Author: Ludy87 +Updated for TOML format Example: To use this script, simply run it from command line: - $ python counter_translation_v2.py + $ python counter_translation_v3.py """ # noqa: D205 import glob import os import re -import json import tomlkit import tomlkit.toml_file @@ -80,14 +80,14 @@ def write_readme(progress_list: list[tuple[str, int]]) -> None: file.writelines(content) -def parse_json_file(file_path): +def parse_toml_file(file_path): """ - Parses a JSON translation file and returns a flat dictionary of all keys. - :param file_path: Path to the JSON file. + Parses a TOML translation file and returns a flat dictionary of all keys. + :param file_path: Path to the TOML file. :return: Dictionary with flattened keys and values. """ with open(file_path, "r", encoding="utf-8") as file: - data = json.load(file) + data = tomlkit.parse(file.read()) def flatten_dict(d, parent_key="", sep="."): items = {} @@ -105,19 +105,19 @@ def parse_json_file(file_path): def compare_files( default_file_path, file_paths, ignore_translation_file ) -> list[tuple[str, int]]: - """Compares the default JSON translation file with other + """Compares the default TOML translation file with other translation files in the locales directory. Parameters: - default_file_path (str): The path to the default translation JSON file. - file_paths (list): List of paths to translation JSON files. + default_file_path (str): The path to the default translation TOML file. + file_paths (list): List of paths to translation TOML files. ignore_translation_file (str): Path to the TOML file with ignore rules. Returns: list[tuple[str, int]]: A list of tuples containing language and progress percentage. """ # noqa: D205 - default_keys = parse_json_file(default_file_path) + default_keys = parse_toml_file(default_file_path) num_keys = len(default_keys) result_list = [] @@ -152,7 +152,7 @@ def compare_files( ["language.direction"] ) - current_keys = parse_json_file(file_path) + current_keys = parse_toml_file(file_path) # Compare keys for default_key, default_value in default_keys.items(): @@ -193,12 +193,12 @@ def compare_files( if __name__ == "__main__": directory = os.path.join(os.getcwd(), "frontend", "public", "locales") - translation_file_paths = glob.glob(os.path.join(directory, "*", "translation.json")) - reference_file = os.path.join(directory, "en-GB", "translation.json") + translation_file_paths = glob.glob(os.path.join(directory, "*", "translation.toml")) + reference_file = os.path.join(directory, "en-GB", "translation.toml") scripts_directory = os.path.join(os.getcwd(), "scripts") translation_state_file = os.path.join(scripts_directory, "ignore_translation.toml") write_readme( compare_files(reference_file, translation_file_paths, translation_state_file) - ) \ No newline at end of file + ) diff --git a/scripts/translations/README.md b/scripts/translations/README.md index a4f9f53d3..0a228ef4b 100644 --- a/scripts/translations/README.md +++ b/scripts/translations/README.md @@ -2,6 +2,12 @@ This directory contains Python scripts for managing frontend translations in Stirling PDF. These tools help analyze, merge, validate, and manage translations against the en-GB golden truth file. +## Current Format: TOML + +**Stirling PDF uses TOML format for translations** in `frontend/public/locales/{lang}/translation.toml`. + +**All scripts now support TOML format!** + ## Quick Start - Automated Translation (RECOMMENDED) The **fastest and easiest way** to translate a language is using the automated pipeline: @@ -451,18 +457,15 @@ python scripts/translations/translation_merger.py fr-FR apply-translations --tra ## Translation File Structure -Translation files are located in `frontend/public/locales/{language}/translation.json` with nested JSON structure: +Translation files are located in `frontend/public/locales/{language}/translation.toml` with TOML structure: -```json -{ - "addPageNumbers": { - "title": "Add Page Numbers", - "selectText": { - "1": "Select PDF file:", - "2": "Margin Size" - } - } -} +```toml +[addPageNumbers] +title = "Add Page Numbers" + +[addPageNumbers.selectText] +"1" = "Select PDF file:" +"2" = "Margin Size" ``` Keys use dot notation internally (e.g., `addPageNumbers.selectText.1`). @@ -478,7 +481,7 @@ All scripts preserve placeholders like `{n}`, `{total}`, `{filename}` in transla ### Automatic Backups Scripts create timestamped backups before modifying files: ``` -translation.backup.20241201_143022.json +translation.backup.20241201_143022.toml ``` ### Context-Aware Translation diff --git a/scripts/translations/ai_translation_helper.py b/scripts/translations/ai_translation_helper.py index c879c229b..bb6fff5e9 100644 --- a/scripts/translations/ai_translation_helper.py +++ b/scripts/translations/ai_translation_helper.py @@ -3,6 +3,7 @@ AI Translation Helper for Stirling PDF Frontend Provides utilities for AI-assisted translation workflows including batch processing, quality checks, and integration helpers. +TOML format only. """ import json @@ -14,31 +15,33 @@ import argparse import re from datetime import datetime import csv +import tomllib +import tomli_w class AITranslationHelper: def __init__(self, locales_dir: str = "frontend/public/locales"): self.locales_dir = Path(locales_dir) - self.golden_truth_file = self.locales_dir / "en-GB" / "translation.json" + self.golden_truth_file = self.locales_dir / "en-GB" / "translation.toml" - def _load_json(self, file_path: Path) -> Dict: - """Load JSON file with error handling.""" + def _load_translation_file(self, file_path: Path) -> Dict: + """Load TOML translation file.""" try: - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f) - except (FileNotFoundError, json.JSONDecodeError) as e: + with open(file_path, 'rb') as f: + return tomllib.load(f) + except (FileNotFoundError, Exception) as e: print(f"Error loading {file_path}: {e}") return {} - def _save_json(self, data: Dict, file_path: Path) -> None: - """Save JSON file.""" - with open(file_path, 'w', encoding='utf-8') as f: - json.dump(data, f, indent=2, ensure_ascii=False) + def _save_translation_file(self, data: Dict, file_path: Path) -> None: + """Save TOML translation file.""" + with open(file_path, 'wb') as f: + tomli_w.dump(data, f) def create_ai_batch_file(self, languages: List[str], output_file: Path, max_entries_per_language: int = 50) -> None: """Create a batch file for AI translation with multiple languages.""" - golden_truth = self._load_json(self.golden_truth_file) + golden_truth = self._load_translation_file(self.golden_truth_file) batch_data = { 'metadata': { 'created_at': datetime.now().isoformat(), @@ -56,12 +59,14 @@ class AITranslationHelper: } for lang in languages: - lang_file = self.locales_dir / lang / "translation.json" - if not lang_file.exists(): - # Create empty translation structure - lang_data = {} + lang_dir = self.locales_dir / lang + toml_file = lang_dir / "translation.toml" + + if toml_file.exists(): + lang_data = self._load_translation_file(toml_file) else: - lang_data = self._load_json(lang_file) + # No translation file found, create empty structure + lang_data = {} # Find untranslated entries untranslated = self._find_untranslated_entries(golden_truth, lang_data) @@ -79,7 +84,9 @@ class AITranslationHelper: 'context': self._get_key_context(key) } - self._save_json(batch_data, output_file) + # Always save batch files as JSON for compatibility + with open(output_file, 'w', encoding='utf-8') as f: + json.dump(batch_data, f, indent=2, ensure_ascii=False) total_entries = sum(len(lang_data) for lang_data in batch_data['translations'].values()) print(f"Created AI batch file: {output_file}") print(f"Total entries to translate: {total_entries}") @@ -173,7 +180,9 @@ class AITranslationHelper: def validate_ai_translations(self, batch_file: Path) -> Dict[str, List[str]]: """Validate AI translations for common issues.""" - batch_data = self._load_json(batch_file) + # Batch files are always JSON + with open(batch_file, 'r', encoding='utf-8') as f: + batch_data = json.load(f) issues = {'errors': [], 'warnings': []} for lang, translations in batch_data.get('translations', {}).items(): @@ -209,7 +218,9 @@ class AITranslationHelper: def apply_ai_batch_translations(self, batch_file: Path, validate: bool = True) -> Dict[str, Any]: """Apply translations from AI batch file to individual language files.""" - batch_data = self._load_json(batch_file) + # Batch files are always JSON + with open(batch_file, 'r', encoding='utf-8') as f: + batch_data = json.load(f) results = {'applied': {}, 'errors': [], 'warnings': []} if validate: @@ -226,14 +237,15 @@ class AITranslationHelper: print(f" WARNING: {warning}") for lang, translations in batch_data.get('translations', {}).items(): - lang_file = self.locales_dir / lang / "translation.json" + lang_dir = self.locales_dir / lang + toml_file = lang_dir / "translation.toml" - # Load existing data or create new - if lang_file.exists(): - lang_data = self._load_json(lang_file) + if toml_file.exists(): + lang_data = self._load_translation_file(toml_file) else: + # No translation file found, create new TOML file lang_data = {} - lang_file.parent.mkdir(parents=True, exist_ok=True) + lang_dir.mkdir(parents=True, exist_ok=True) applied_count = 0 for key, translation_data in translations.items(): @@ -243,7 +255,7 @@ class AITranslationHelper: applied_count += 1 if applied_count > 0: - self._save_json(lang_data, lang_file) + self._save_translation_file(lang_data, toml_file) results['applied'][lang] = applied_count print(f"Applied {applied_count} translations to {lang}") @@ -265,7 +277,7 @@ class AITranslationHelper: def export_for_external_translation(self, languages: List[str], output_format: str = 'csv') -> None: """Export translations for external translation services.""" - golden_truth = self._load_json(self.golden_truth_file) + golden_truth = self._load_translation_file(self.golden_truth_file) golden_flat = self._flatten_dict(golden_truth) if output_format == 'csv': @@ -287,9 +299,11 @@ class AITranslationHelper: } for lang in languages: - lang_file = self.locales_dir / lang / "translation.json" - if lang_file.exists(): - lang_data = self._load_json(lang_file) + lang_dir = self.locales_dir / lang + toml_file = lang_dir / "translation.toml" + + if toml_file.exists(): + lang_data = self._load_translation_file(toml_file) lang_flat = self._flatten_dict(lang_data) value = lang_flat.get(key, '') if value.startswith('[UNTRANSLATED]'): @@ -316,21 +330,28 @@ class AITranslationHelper: } for lang in languages: - lang_file = self.locales_dir / lang / "translation.json" - if lang_file.exists(): - lang_data = self._load_json(lang_file) + lang_dir = self.locales_dir / lang + toml_file = lang_dir / "translation.toml" + + if toml_file.exists(): + lang_data = self._load_translation_file(toml_file) lang_flat = self._flatten_dict(lang_data) value = lang_flat.get(key, '') if value.startswith('[UNTRANSLATED]'): value = '' export_data['translations'][key][lang] = value - self._save_json(export_data, output_file) + # Export files are always JSON + with open(output_file, 'w', encoding='utf-8') as f: + json.dump(export_data, f, indent=2, ensure_ascii=False) print(f"Exported to {output_file}") def main(): - parser = argparse.ArgumentParser(description='AI Translation Helper') + parser = argparse.ArgumentParser( + description='AI Translation Helper', + epilog='Works with TOML translation files.' + ) parser.add_argument('--locales-dir', default='frontend/public/locales', help='Path to locales directory') diff --git a/scripts/translations/auto_translate.py b/scripts/translations/auto_translate.py index 505823f47..9bfbca112 100644 --- a/scripts/translations/auto_translate.py +++ b/scripts/translations/auto_translate.py @@ -2,6 +2,7 @@ """ Automated Translation Pipeline Extracts, translates, merges, and beautifies translations for a language. +TOML format only. """ import json @@ -12,6 +13,8 @@ import subprocess from pathlib import Path import time +import tomllib + def run_command(cmd, description=""): """Run a shell command and return success status.""" @@ -30,26 +33,34 @@ def run_command(cmd, description=""): return result.returncode == 0 +def find_translation_file(lang_dir): + """Find translation file in language directory.""" + toml_file = lang_dir / "translation.toml" + if toml_file.exists(): + return toml_file + return None + +def load_translation_file(file_path): + """Load TOML translation file.""" + with open(file_path, 'rb') as f: + return tomllib.load(f) + def extract_untranslated(language_code, batch_size=500): """Extract untranslated entries and split into batches.""" print(f"\n🔍 Extracting untranslated entries for {language_code}...") # Load files - golden_path = Path(f'frontend/public/locales/en-GB/translation.json') - lang_path = Path(f'frontend/public/locales/{language_code}/translation.json') + golden_path = find_translation_file(Path('frontend/public/locales/en-GB')) + lang_path = find_translation_file(Path(f'frontend/public/locales/{language_code}')) - if not golden_path.exists(): - print(f"Error: Golden truth file not found: {golden_path}") + if not golden_path: + print(f"Error: Golden truth file not found in frontend/public/locales/en-GB") return None - if not lang_path.exists(): - print(f"Error: Language file not found: {lang_path}") + if not lang_path: + print(f"Error: Language file not found in frontend/public/locales/{language_code}") return None - def load_json(path): - with open(path, 'r', encoding='utf-8') as f: - return json.load(f) - def flatten_dict(d, parent_key='', separator='.'): items = [] for k, v in d.items(): @@ -60,8 +71,12 @@ def extract_untranslated(language_code, batch_size=500): items.append((new_key, str(v))) return dict(items) - golden = load_json(golden_path) - lang_data = load_json(lang_path) + golden = load_translation_file(golden_path) + lang_data = load_translation_file(lang_path) + + if not golden or not lang_data: + print(f"Error: Failed to load translation files") + return None golden_flat = flatten_dict(golden) lang_flat = flatten_dict(lang_data) @@ -186,7 +201,7 @@ def beautify_translations(language_code): """Beautify translation file to match en-GB structure.""" print(f"\n✨ Beautifying {language_code} translation file...") - cmd = f'python3 scripts/translations/json_beautifier.py --language {language_code}' + cmd = f'python3 scripts/translations/toml_beautifier.py --language {language_code}' if not run_command(cmd): print(f"✗ Failed to beautify translations") @@ -229,6 +244,8 @@ def main(): description='Automated translation pipeline for Stirling PDF', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" +Note: This script works with TOML translation files. + Examples: # Translate Spanish with API key in environment export OPENAI_API_KEY=your_key_here diff --git a/scripts/translations/batch_translator.py b/scripts/translations/batch_translator.py index aeb99a074..0085a51de 100644 --- a/scripts/translations/batch_translator.py +++ b/scripts/translations/batch_translator.py @@ -5,6 +5,8 @@ Automatically translates JSON batch files to target language while preserving: - Placeholders: {n}, {total}, {filename}, {{variable}} - HTML tags: , , etc. - Technical terms: PDF, API, OAuth2, SAML2, JWT, etc. + +Note: Works with JSON batch files. Translation files can be TOML or JSON format. """ import json @@ -206,9 +208,11 @@ def get_language_info(language_code: str) -> tuple: def main(): parser = argparse.ArgumentParser( - description='Translate JSON batch files using OpenAI API', + description='Translate JSON batch files using OpenAI API (output supports TOML and JSON)', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" +Note: This script works with JSON batch files. The translation files it updates can be TOML or JSON. + Examples: # Translate single batch file python batch_translator.py zh_CN_batch_1_of_4.json --api-key YOUR_KEY --language zh-CN diff --git a/scripts/translations/bulk_auto_translate.py b/scripts/translations/bulk_auto_translate.py new file mode 100644 index 000000000..9dfaa92f4 --- /dev/null +++ b/scripts/translations/bulk_auto_translate.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python3 +""" +Bulk Auto-Translate All Languages +Automatically translates all languages in parallel using OpenAI API. +Supports concurrent translation with configurable thread pool. +""" + +import argparse +import os +import sys +import time +from pathlib import Path +from concurrent.futures import ThreadPoolExecutor, as_completed +import subprocess +from typing import List, Tuple, Optional +import threading + +import tomllib + + +# Thread-safe print lock +print_lock = threading.Lock() + + +def safe_print(*args, **kwargs): + """Thread-safe print function.""" + with print_lock: + print(*args, **kwargs) + + +def get_all_languages(locales_dir: Path) -> List[str]: + """Get all language codes from locales directory.""" + languages = [] + + if not locales_dir.exists(): + print(f"Error: Locales directory not found: {locales_dir}") + return [] + + for lang_dir in sorted(locales_dir.iterdir()): + if lang_dir.is_dir() and lang_dir.name != "en-GB": + toml_file = lang_dir / "translation.toml" + if toml_file.exists(): + languages.append(lang_dir.name) + + return languages + + +def get_language_completion(locales_dir: Path, language: str) -> Optional[float]: + """Get completion percentage for a language.""" + lang_dir = locales_dir / language + toml_file = lang_dir / "translation.toml" + + if not toml_file.exists(): + return None + + try: + with open(toml_file, 'rb') as f: + target_data = tomllib.load(f) + + # Load en-GB reference + en_gb_file = locales_dir / 'en-GB' / 'translation.toml' + with open(en_gb_file, 'rb') as f: + en_gb_data = tomllib.load(f) + + # Flatten and count + def flatten(d, parent=''): + items = {} + for k, v in d.items(): + key = f"{parent}.{k}" if parent else k + if isinstance(v, dict): + items.update(flatten(v, key)) + else: + items[key] = v + return items + + en_gb_flat = flatten(en_gb_data) + target_flat = flatten(target_data) + + # Count translated (not equal to en-GB) + translated = sum(1 for k in en_gb_flat if k in target_flat and target_flat[k] != en_gb_flat[k]) + total = len(en_gb_flat) + + return (translated / total * 100) if total > 0 else 0.0 + + except Exception as e: + print(f"Warning: Could not calculate completion for {language}: {e}") + return None + + +def translate_language(language: str, api_key: str, batch_size: int, timeout: int, skip_verification: bool) -> Tuple[str, bool, str]: + """ + Translate a single language. + Returns: (language_code, success, message) + """ + safe_print(f"[{language}] Starting translation...") + + cmd = [ + 'python3', 'scripts/translations/auto_translate.py', + language, + '--api-key', api_key, + '--batch-size', str(batch_size), + '--timeout', str(timeout) + ] + + if skip_verification: + cmd.append('--skip-verification') + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=timeout * 5 # Overall timeout = 5x per-batch timeout + ) + + if result.returncode == 0: + # Check if nothing to translate + if "Nothing to translate!" in result.stdout: + safe_print(f"[{language}] ✓ Already complete") + return (language, True, "Already complete") + safe_print(f"[{language}] ✓ Success") + return (language, True, "Success") + else: + error_msg = result.stderr.strip() or result.stdout.strip() or "Unknown error" + safe_print(f"[{language}] ✗ Failed: {error_msg[:100]}") + return (language, False, error_msg[:200]) # Truncate long errors + + except subprocess.TimeoutExpired: + safe_print(f"[{language}] ✗ Timeout exceeded") + return (language, False, "Timeout exceeded") + except Exception as e: + safe_print(f"[{language}] ✗ Error: {str(e)}") + return (language, False, str(e)) + + +def main(): + parser = argparse.ArgumentParser( + description='Bulk auto-translate all languages using OpenAI API', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Translate all languages with 10 parallel threads + python3 bulk_auto_translate.py --parallel 10 + + # Translate only incomplete languages (< 95%) + python3 bulk_auto_translate.py --parallel 5 --threshold 95 + + # Translate specific languages only + python3 bulk_auto_translate.py --languages de-DE fr-FR es-ES --parallel 3 + + # Dry run to see what would be translated + python3 bulk_auto_translate.py --dry-run + +Note: Requires OPENAI_API_KEY environment variable or --api-key argument. +""" + ) + + parser.add_argument('--api-key', help='OpenAI API key (or set OPENAI_API_KEY env var)') + parser.add_argument('--parallel', type=int, default=1, + help='Number of parallel translation threads (default: 1)') + parser.add_argument('--batch-size', type=int, default=500, + help='Entries per batch for translation (default: 500)') + parser.add_argument('--timeout', type=int, default=600, + help='Timeout per batch in seconds (default: 600)') + parser.add_argument('--threshold', type=float, default=0.0, + help='Only translate languages below this completion %% (default: 0 = all)') + parser.add_argument('--languages', nargs='+', + help='Translate only specific languages (e.g., de-DE fr-FR)') + parser.add_argument('--locales-dir', default='frontend/public/locales', + help='Path to locales directory') + parser.add_argument('--skip-verification', action='store_true', + help='Skip final completion verification for each language') + parser.add_argument('--dry-run', action='store_true', + help='Show what would be translated without actually translating') + + args = parser.parse_args() + + # Verify API key (unless dry run) + api_key = args.api_key or os.environ.get('OPENAI_API_KEY') + if not args.dry_run and not api_key: + print("Error: OpenAI API key required. Provide via --api-key or OPENAI_API_KEY environment variable") + sys.exit(1) + + locales_dir = Path(args.locales_dir) + + # Get languages to translate + if args.languages: + languages = args.languages + print(f"Translating specified languages: {', '.join(languages)}") + else: + languages = get_all_languages(locales_dir) + print(f"Found {len(languages)} languages (excluding en-GB)") + + if not languages: + print("No languages to translate!") + sys.exit(0) + + # Filter by completion threshold + if args.threshold > 0: + print(f"\nFiltering languages below {args.threshold}% completion...") + filtered = [] + for lang in languages: + completion = get_language_completion(locales_dir, lang) + if completion is None: + filtered.append(lang) # Include if can't determine + print(f" {lang}: Unknown completion - will translate") + elif completion < args.threshold: + filtered.append(lang) + print(f" {lang}: {completion:.1f}% - will translate") + else: + print(f" {lang}: {completion:.1f}% - skipping (above threshold)") + + languages = filtered + + if not languages: + print("\nNo languages below threshold!") + sys.exit(0) + + print(f"\n{'='*60}") + print(f"Bulk Translation Configuration") + print(f"{'='*60}") + print(f"Languages to translate: {len(languages)}") + print(f"Parallel threads: {args.parallel}") + print(f"Batch size: {args.batch_size}") + print(f"Timeout per batch: {args.timeout}s") + if args.threshold > 0: + print(f"Completion threshold: {args.threshold}%") + print(f"{'='*60}\n") + + if args.dry_run: + print("DRY RUN - Languages that would be translated:") + for lang in languages: + completion = get_language_completion(locales_dir, lang) + comp_str = f"{completion:.1f}%" if completion is not None else "Unknown" + print(f" - {lang} ({comp_str})") + print(f"\nTotal: {len(languages)} languages") + sys.exit(0) + + start_time = time.time() + + # Translate in parallel + results = { + 'success': [], + 'failed': [], + 'already_complete': [] + } + + with ThreadPoolExecutor(max_workers=args.parallel) as executor: + futures = { + executor.submit( + translate_language, + lang, + api_key, + args.batch_size, + args.timeout, + args.skip_verification + ): lang + for lang in languages + } + + for future in as_completed(futures): + language, success, message = future.result() + + if success: + if message == "Already complete": + results['already_complete'].append(language) + else: + results['success'].append(language) + else: + results['failed'].append((language, message)) + + elapsed = time.time() - start_time + + # Print summary + print("\n" + "="*60) + print("Bulk Translation Summary") + print("="*60) + print(f"Total languages: {len(languages)}") + print(f"Successful: {len(results['success'])}") + print(f"Already complete: {len(results['already_complete'])}") + print(f"Failed: {len(results['failed'])}") + print(f"Time elapsed: {elapsed:.1f} seconds ({elapsed/60:.1f} minutes)") + print("="*60) + + if results['success']: + print(f"\n✅ Successfully translated ({len(results['success'])}):") + for lang in sorted(results['success']): + print(f" - {lang}") + + if results['already_complete']: + print(f"\n✓ Already complete ({len(results['already_complete'])}):") + for lang in sorted(results['already_complete']): + print(f" - {lang}") + + if results['failed']: + print(f"\n❌ Failed ({len(results['failed'])}):") + for lang, msg in sorted(results['failed']): + print(f" - {lang}: {msg}") + sys.exit(1) + + print("\n✅ Bulk translation completed successfully!") + + +if __name__ == '__main__': + main() diff --git a/scripts/translations/compact_translator.py b/scripts/translations/compact_translator.py index 59efcbe9c..efe22f9f8 100644 --- a/scripts/translations/compact_translator.py +++ b/scripts/translations/compact_translator.py @@ -2,41 +2,37 @@ """ Compact Translation Extractor for Character-Limited AI Translation Outputs untranslated entries in minimal JSON format with whitespace stripped. +TOML format only. """ import json import sys from pathlib import Path import argparse -try: - import tomllib # Python 3.11+ -except ImportError: - try: - import toml as tomllib_fallback - tomllib = None - except ImportError: - tomllib = None - tomllib_fallback = None +import tomllib # Python 3.11+ (stdlib) class CompactTranslationExtractor: def __init__(self, locales_dir: str = "frontend/public/locales", ignore_file: str = "scripts/ignore_translation.toml"): self.locales_dir = Path(locales_dir) - self.golden_truth_file = self.locales_dir / "en-GB" / "translation.json" - self.golden_truth = self._load_json(self.golden_truth_file) + self.golden_truth_file = self.locales_dir / "en-GB" / "translation.toml" + if not self.golden_truth_file.exists(): + print(f"Error: en-GB translation file not found at {self.golden_truth_file}", file=sys.stderr) + sys.exit(1) + self.golden_truth = self._load_translation_file(self.golden_truth_file) self.ignore_file = Path(ignore_file) self.ignore_patterns = self._load_ignore_patterns() - def _load_json(self, file_path: Path) -> dict: - """Load JSON file with error handling.""" + def _load_translation_file(self, file_path: Path) -> dict: + """Load TOML translation file.""" try: - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f) + with open(file_path, 'rb') as f: + return tomllib.load(f) except FileNotFoundError: print(f"Error: File not found: {file_path}", file=sys.stderr) sys.exit(1) - except json.JSONDecodeError as e: - print(f"Error: Invalid JSON in {file_path}: {e}", file=sys.stderr) + except Exception as e: + print(f"Error: Invalid TOML file {file_path}: {e}", file=sys.stderr) sys.exit(1) def _load_ignore_patterns(self) -> dict: @@ -45,40 +41,13 @@ class CompactTranslationExtractor: return {} try: - if tomllib: - with open(self.ignore_file, 'rb') as f: - ignore_data = tomllib.load(f) - elif tomllib_fallback: - ignore_data = tomllib_fallback.load(self.ignore_file) - else: - ignore_data = self._parse_simple_toml() - + with open(self.ignore_file, 'rb') as f: + ignore_data = tomllib.load(f) return {lang: set(data.get('ignore', [])) for lang, data in ignore_data.items()} except Exception as e: print(f"Warning: Could not load ignore file {self.ignore_file}: {e}", file=sys.stderr) return {} - def _parse_simple_toml(self) -> dict: - """Simple TOML parser for ignore patterns (fallback).""" - ignore_data = {} - current_section = None - - with open(self.ignore_file, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if not line or line.startswith('#'): - continue - - if line.startswith('[') and line.endswith(']'): - current_section = line[1:-1] - ignore_data[current_section] = {'ignore': []} - elif line.strip().startswith("'") and current_section: - item = line.strip().strip("',") - if item: - ignore_data[current_section]['ignore'].append(item) - - return ignore_data - def _flatten_dict(self, d: dict, parent_key: str = '', separator: str = '.') -> dict: """Flatten nested dictionary into dot-notation keys.""" items = [] @@ -92,13 +61,14 @@ class CompactTranslationExtractor: def get_untranslated_entries(self, language: str) -> dict: """Get all untranslated entries for a language in compact format.""" - target_file = self.locales_dir / language / "translation.json" + lang_dir = self.locales_dir / language + target_file = lang_dir / "translation.toml" if not target_file.exists(): print(f"Error: Translation file not found for language: {language}", file=sys.stderr) sys.exit(1) - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -145,7 +115,9 @@ class CompactTranslationExtractor: def main(): - parser = argparse.ArgumentParser(description='Extract untranslated entries in compact format for AI translation') + parser = argparse.ArgumentParser( + description='Extract untranslated entries in compact format for AI translation (TOML format only)' + ) parser.add_argument('language', help='Language code (e.g., de-DE, fr-FR)') parser.add_argument('--locales-dir', default='frontend/public/locales', help='Path to locales directory') parser.add_argument('--ignore-file', default='scripts/ignore_translation.toml', help='Path to ignore patterns file') diff --git a/scripts/translations/json_validator.py b/scripts/translations/json_validator.py deleted file mode 100644 index 0ad20fad1..000000000 --- a/scripts/translations/json_validator.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env python3 -""" -JSON Validator for Translation Files - -Validates JSON syntax in translation files and reports detailed error information. -Useful for validating batch translation files before merging. - -Usage: - python3 json_validator.py - python3 json_validator.py ar_AR_batch_*.json - python3 json_validator.py ar_AR_batch_1_of_3.json - python3 json_validator.py --all-batches ar_AR -""" - -import json -import sys -import argparse -import glob -from pathlib import Path - - -def get_line_context(file_path, line_num, context_lines=3): - """Get lines around the error for context""" - try: - with open(file_path, 'r', encoding='utf-8') as f: - lines = f.readlines() - - start = max(0, line_num - context_lines - 1) - end = min(len(lines), line_num + context_lines) - - context = [] - for i in range(start, end): - marker = ">>> " if i == line_num - 1 else " " - context.append(f"{marker}{i+1:4d}: {lines[i].rstrip()}") - - return "\n".join(context) - except Exception as e: - return f"Could not read context: {e}" - - -def get_character_context(file_path, char_pos, context_chars=100): - """Get characters around the error position""" - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - - start = max(0, char_pos - context_chars) - end = min(len(content), char_pos + context_chars) - - before = content[start:char_pos] - error_char = content[char_pos] if char_pos < len(content) else "EOF" - after = content[char_pos+1:end] - - return { - 'before': before, - 'error_char': error_char, - 'after': after, - 'display': f"{before}[{error_char}]{after}" - } - except Exception as e: - return None - - -def validate_json_file(file_path): - """Validate a single JSON file and return detailed error info""" - result = { - 'file': str(file_path), - 'valid': False, - 'error': None, - 'line': None, - 'column': None, - 'position': None, - 'context': None, - 'char_context': None, - 'entry_count': 0 - } - - try: - with open(file_path, 'r', encoding='utf-8') as f: - data = json.load(f) - - result['valid'] = True - result['entry_count'] = len(data) if isinstance(data, dict) else 0 - - except json.JSONDecodeError as e: - result['error'] = e.msg - result['line'] = e.lineno - result['column'] = e.colno - result['position'] = e.pos - result['context'] = get_line_context(file_path, e.lineno) - result['char_context'] = get_character_context(file_path, e.pos) - - except FileNotFoundError: - result['error'] = "File not found" - - except Exception as e: - result['error'] = str(e) - - return result - - -def print_validation_result(result, verbose=True): - """Print validation result in a formatted way""" - file_name = Path(result['file']).name - - if result['valid']: - print(f"✓ {file_name}: Valid JSON ({result['entry_count']} entries)") - else: - print(f"✗ {file_name}: Invalid JSON") - print(f" Error: {result['error']}") - - if result['line']: - print(f" Location: Line {result['line']}, Column {result['column']} (character {result['position']})") - - if verbose and result['context']: - print(f"\n Context:") - for line in result['context'].split('\n'): - print(f" {line}") - - if verbose and result['char_context']: - print(f"\n Character context:") - print(f" ...{result['char_context']['display'][-150:]}...") - print(f" Error character: {repr(result['char_context']['error_char'])}") - - print() - - -def get_common_fixes(error_msg): - """Suggest common fixes based on error message""" - fixes = [] - - if "Expecting ',' delimiter" in error_msg: - fixes.append("Missing comma between JSON entries") - fixes.append("Check for unescaped quotes inside string values") - - if "Invalid \\escape" in error_msg or "Invalid escape" in error_msg: - fixes.append("Unescaped backslash in string (use \\\\ for literal backslash)") - fixes.append("Common in regex patterns: \\d should be \\\\d") - - if "Expecting property name" in error_msg: - fixes.append("Missing or extra comma") - fixes.append("Trailing comma before closing brace") - - if "Expecting value" in error_msg: - fixes.append("Missing value after colon") - fixes.append("Extra comma") - - return fixes - - -def main(): - parser = argparse.ArgumentParser( - description='Validate JSON syntax in translation files', - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=""" -Examples: - Validate single file: - python3 json_validator.py ar_AR_batch_1_of_3.json - - Validate all batches for a language: - python3 json_validator.py --all-batches ar_AR - - Validate pattern: - python3 json_validator.py "ar_AR_batch_*.json" - - Validate multiple files: - python3 json_validator.py file1.json file2.json file3.json - """ - ) - - parser.add_argument( - 'files', - nargs='*', - help='JSON file(s) to validate (supports wildcards)' - ) - - parser.add_argument( - '--all-batches', - metavar='LANGUAGE', - help='Validate all batch files for a language (e.g., ar_AR)' - ) - - parser.add_argument( - '--quiet', - action='store_true', - help='Only show files with errors' - ) - - parser.add_argument( - '--brief', - action='store_true', - help='Brief output without context' - ) - - args = parser.parse_args() - - # Determine which files to validate - files_to_validate = [] - - if args.all_batches: - pattern = f"{args.all_batches}_batch_*.json" - files_to_validate = glob.glob(pattern) - if not files_to_validate: - print(f"No batch files found matching: {pattern}") - return 1 - elif args.files: - for file_pattern in args.files: - if '*' in file_pattern or '?' in file_pattern: - files_to_validate.extend(glob.glob(file_pattern)) - else: - files_to_validate.append(file_pattern) - else: - parser.print_help() - return 1 - - if not files_to_validate: - print("No files to validate") - return 1 - - # Sort files for consistent output - files_to_validate.sort() - - print(f"Validating {len(files_to_validate)} file(s)...\n") - - # Validate each file - results = [] - for file_path in files_to_validate: - result = validate_json_file(file_path) - results.append(result) - - if not args.quiet or not result['valid']: - print_validation_result(result, verbose=not args.brief) - - # Summary - valid_count = sum(1 for r in results if r['valid']) - invalid_count = len(results) - valid_count - - print("=" * 60) - print(f"Summary: {valid_count} valid, {invalid_count} invalid") - - # Show common fixes for errors - if invalid_count > 0: - all_errors = [r['error'] for r in results if r['error']] - unique_error_types = set(all_errors) - - print("\nCommon fixes:") - fixes_shown = set() - for error in unique_error_types: - fixes = get_common_fixes(error) - for fix in fixes: - if fix not in fixes_shown: - print(f" • {fix}") - fixes_shown.add(fix) - - return 0 if invalid_count == 0 else 1 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/scripts/translations/json_beautifier.py b/scripts/translations/toml_beautifier.py similarity index 86% rename from scripts/translations/json_beautifier.py rename to scripts/translations/toml_beautifier.py index 41c65afda..a0e1f95cb 100644 --- a/scripts/translations/json_beautifier.py +++ b/scripts/translations/toml_beautifier.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 """ -JSON Beautifier and Structure Fixer for Stirling PDF Frontend -Restructures translation JSON files to match en-GB structure and key order exactly. +TOML Beautifier and Structure Fixer for Stirling PDF Frontend +Restructures translation TOML files to match en-GB structure and key order exactly. """ -import json import os import sys from pathlib import Path @@ -12,34 +11,38 @@ from typing import Dict, Any, List import argparse from collections import OrderedDict +import tomllib +import tomli_w -class JSONBeautifier: + +class TOMLBeautifier: def __init__(self, locales_dir: str = "frontend/public/locales"): self.locales_dir = Path(locales_dir) - self.golden_truth_file = self.locales_dir / "en-GB" / "translation.json" - self.golden_structure = self._load_json(self.golden_truth_file) + self.golden_truth_file = self.locales_dir / "en-GB" / "translation.toml" + self.golden_structure = self._load_toml(self.golden_truth_file) - def _load_json(self, file_path: Path) -> Dict: - """Load JSON file with error handling.""" + def _load_toml(self, file_path: Path) -> Dict: + """Load TOML file with error handling.""" try: - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f, object_pairs_hook=OrderedDict) + with open(file_path, 'rb') as f: + return tomllib.load(f) except FileNotFoundError: print(f"Error: File not found: {file_path}") sys.exit(1) - except json.JSONDecodeError as e: - print(f"Error: Invalid JSON in {file_path}: {e}") + except Exception as e: + print(f"Error: Invalid TOML in {file_path}: {e}") sys.exit(1) - def _save_json(self, data: Dict, file_path: Path, backup: bool = True) -> None: - """Save JSON file with proper formatting.""" + def _save_toml(self, data: Dict, file_path: Path, backup: bool = False) -> None: + """Save TOML file with proper formatting.""" if backup and file_path.exists(): - backup_path = file_path.with_suffix(f'.backup.restructured.json') - file_path.rename(backup_path) + backup_path = file_path.with_suffix(f'.backup.restructured.toml') + import shutil + shutil.copy2(file_path, backup_path) print(f"Backup created: {backup_path}") - with open(file_path, 'w', encoding='utf-8') as f: - json.dump(data, f, indent=2, ensure_ascii=False, separators=(',', ': ')) + with open(file_path, 'wb') as f: + tomli_w.dump(data, f) def _flatten_dict(self, d: Dict, parent_key: str = '', separator: str = '.') -> Dict[str, Any]: """Flatten nested dictionary into dot-notation keys.""" @@ -93,7 +96,7 @@ class JSONBeautifier: return {} # Load the target file - target_data = self._load_json(target_file) + target_data = self._load_toml(target_file) # Flatten the target translations flat_target = self._flatten_dict(target_data) @@ -103,7 +106,7 @@ class JSONBeautifier: return restructured - def beautify_and_restructure(self, target_file: Path, backup: bool = True) -> Dict[str, Any]: + def beautify_and_restructure(self, target_file: Path, backup: bool = False) -> Dict[str, Any]: """Main function to beautify and restructure a translation file.""" lang_code = target_file.parent.name print(f"Restructuring {lang_code} translation file...") @@ -112,7 +115,7 @@ class JSONBeautifier: restructured_data = self.restructure_translation_file(target_file) # Save the restructured file - self._save_json(restructured_data, target_file, backup) + self._save_toml(restructured_data, target_file, backup) # Analyze the results flat_golden = self._flatten_dict(self.golden_structure) @@ -163,7 +166,7 @@ class JSONBeautifier: def validate_key_order(self, target_file: Path) -> Dict[str, Any]: """Validate that keys appear in the same order as en-GB.""" - target_data = self._load_json(target_file) + target_data = self._load_toml(target_file) def get_key_order(obj: Dict, path: str = '') -> List[str]: keys = [] @@ -198,23 +201,26 @@ class JSONBeautifier: def main(): - parser = argparse.ArgumentParser(description='Beautify and restructure translation JSON files') + parser = argparse.ArgumentParser( + description='Beautify and restructure translation TOML files', + epilog='Works with TOML format translation files.' + ) parser.add_argument('--locales-dir', default='frontend/public/locales', help='Path to locales directory') parser.add_argument('--language', help='Restructure specific language only') parser.add_argument('--all-languages', action='store_true', help='Restructure all language files') - parser.add_argument('--no-backup', action='store_true', - help='Skip backup creation') + parser.add_argument('--backup', action='store_true', + help='Create backup files before modifying') parser.add_argument('--validate-only', action='store_true', help='Only validate structure, do not modify files') args = parser.parse_args() - beautifier = JSONBeautifier(args.locales_dir) + beautifier = TOMLBeautifier(args.locales_dir) if args.language: - target_file = Path(args.locales_dir) / args.language / "translation.json" + target_file = Path(args.locales_dir) / args.language / "translation.toml" if not target_file.exists(): print(f"Error: Translation file not found for language: {args.language}") sys.exit(1) @@ -225,7 +231,7 @@ def main(): print(f" Order preserved: {order_result['order_preserved']}") print(f" Common keys: {order_result['common_keys_count']}/{order_result['golden_keys_count']}") else: - result = beautifier.beautify_and_restructure(target_file, backup=not args.no_backup) + result = beautifier.beautify_and_restructure(target_file, backup=args.backup) print(f"\nResults for {result['language']}:") print(f" Keys preserved: {result['preserved_keys']}/{result['total_reference_keys']}") if result['structure_match']['total_issues'] > 0: @@ -237,13 +243,13 @@ def main(): results = [] for lang_dir in Path(args.locales_dir).iterdir(): if lang_dir.is_dir() and lang_dir.name != "en-GB": - translation_file = lang_dir / "translation.json" + translation_file = lang_dir / "translation.toml" if translation_file.exists(): if args.validate_only: order_result = beautifier.validate_key_order(translation_file) print(f"{lang_dir.name}: Order preserved = {order_result['order_preserved']}") else: - result = beautifier.beautify_and_restructure(translation_file, backup=not args.no_backup) + result = beautifier.beautify_and_restructure(translation_file, backup=args.backup) results.append(result) if not args.validate_only and results: @@ -259,4 +265,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/scripts/translations/toml_validator.py b/scripts/translations/toml_validator.py new file mode 100644 index 000000000..e7018050e --- /dev/null +++ b/scripts/translations/toml_validator.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +""" +TOML Validator for Translation Files + +Validates TOML syntax in translation files and reports detailed error information. +Useful for validating translation files before merging. + +Usage: + python3 toml_validator.py + python3 toml_validator.py ar_AR_batch_*.toml + python3 toml_validator.py ar_AR_batch_1_of_3.toml + python3 toml_validator.py --all-batches ar_AR +""" + +import sys +import argparse +import glob +from pathlib import Path + +import tomllib + + +def get_line_context(file_path, line_num, context_lines=3): + """Get lines around the error for context""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + lines = f.readlines() + + start = max(0, line_num - context_lines - 1) + end = min(len(lines), line_num + context_lines) + + context = [] + for i in range(start, end): + marker = ">>> " if i == line_num - 1 else " " + context.append(f"{marker}{i+1:4d}: {lines[i].rstrip()}") + + return "\n".join(context) + except Exception as e: + return f"Could not read context: {e}" + + +def get_character_context(file_path, char_pos, context_chars=100): + """Get characters around the error position""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + start = max(0, char_pos - context_chars) + end = min(len(content), char_pos + context_chars) + + before = content[start:char_pos] + error_char = content[char_pos] if char_pos < len(content) else "EOF" + after = content[char_pos+1:end] + + return { + 'before': before, + 'error_char': error_char, + 'after': after, + 'display': f"{before}[{error_char}]{after}" + } + except Exception as e: + return None + + +def count_keys(data, prefix=''): + """Recursively count all keys in nested TOML structure""" + count = 0 + if isinstance(data, dict): + for key, value in data.items(): + if isinstance(value, dict): + count += count_keys(value, f"{prefix}.{key}" if prefix else key) + else: + count += 1 + return count + + +def validate_toml_file(file_path): + """Validate a single TOML file and return detailed error info""" + result = { + 'file': str(file_path), + 'valid': False, + 'error': None, + 'line': None, + 'context': None, + 'entry_count': 0 + } + + try: + with open(file_path, 'rb') as f: + data = tomllib.load(f) + + result['valid'] = True + result['entry_count'] = count_keys(data) + + except Exception as e: + error_msg = str(e) + result['error'] = error_msg + + # Try to extract line number from error message + import re + line_match = re.search(r'line (\d+)', error_msg, re.IGNORECASE) + if line_match: + line_num = int(line_match.group(1)) + result['line'] = line_num + result['context'] = get_line_context(file_path, line_num) + + except FileNotFoundError: + result['error'] = "File not found" + + return result + + +def print_validation_result(result, brief=False, quiet=False): + """Print validation result in human-readable format""" + if result['valid']: + if not quiet: + print(f"✓ {result['file']}") + if not brief: + print(f" Valid TOML with {result['entry_count']} entries") + else: + print(f"✗ {result['file']}") + print(f" Error: {result['error']}") + + if result['line']: + print(f" Line: {result['line']}") + + if result['context'] and not brief: + print(f"\n Context:") + print(f" {result['context'].replace(chr(10), chr(10) + ' ')}") + + if not brief: + print(f"\n Common fixes:") + print(f" - Check for missing quotes around keys or values") + print(f" - Ensure proper escaping of special characters") + print(f" - Verify table header syntax: [section.subsection]") + print(f" - Check for duplicate keys in the same table") + + +def main(): + parser = argparse.ArgumentParser(description='Validate TOML translation files') + parser.add_argument('files', nargs='*', help='TOML file(s) or pattern to validate') + parser.add_argument('--all-batches', metavar='LANG', + help='Validate all batch files for a language (e.g., ar_AR)') + parser.add_argument('--brief', action='store_true', + help='Show brief output without context') + parser.add_argument('--quiet', action='store_true', + help='Only show files with errors') + + args = parser.parse_args() + + # Collect files to validate + files_to_validate = [] + + if args.all_batches: + # Find all batch files for the specified language + pattern = f"{args.all_batches}_batch_*.toml" + files_to_validate = glob.glob(pattern) + if not files_to_validate: + print(f"No batch files found matching pattern: {pattern}") + sys.exit(1) + elif args.files: + for file_pattern in args.files: + matched_files = glob.glob(file_pattern) + if matched_files: + files_to_validate.extend(matched_files) + else: + # Try as literal filename + files_to_validate.append(file_pattern) + else: + parser.print_help() + sys.exit(1) + + # Validate all files + results = [] + for file_path in files_to_validate: + result = validate_toml_file(file_path) + results.append(result) + print_validation_result(result, brief=args.brief, quiet=args.quiet) + if not args.brief and not args.quiet: + print() # Empty line between files + + # Summary + total = len(results) + valid = sum(1 for r in results if r['valid']) + invalid = total - valid + + if not args.quiet: + print(f"\n{'='*60}") + print(f"Summary: {valid}/{total} files valid") + if invalid > 0: + print(f" {invalid} file(s) with errors") + + # Exit with error code if any files invalid + sys.exit(0 if invalid == 0 else 1) + + +if __name__ == '__main__': + main() diff --git a/scripts/translations/translation_analyzer.py b/scripts/translations/translation_analyzer.py index 9c8315b53..35b2b3555 100644 --- a/scripts/translations/translation_analyzer.py +++ b/scripts/translations/translation_analyzer.py @@ -10,35 +10,27 @@ import sys from pathlib import Path from typing import Dict, List, Set, Tuple import argparse -try: - import tomllib # Python 3.11+ -except ImportError: - try: - import toml as tomllib_fallback - tomllib = None - except ImportError: - tomllib = None - tomllib_fallback = None +import tomllib class TranslationAnalyzer: def __init__(self, locales_dir: str = "frontend/public/locales", ignore_file: str = "scripts/ignore_translation.toml"): self.locales_dir = Path(locales_dir) - self.golden_truth_file = self.locales_dir / "en-GB" / "translation.json" - self.golden_truth = self._load_json(self.golden_truth_file) + self.golden_truth_file = self.locales_dir / "en-GB" / "translation.toml" + self.golden_truth = self._load_translation_file(self.golden_truth_file) self.ignore_file = Path(ignore_file) self.ignore_patterns = self._load_ignore_patterns() - def _load_json(self, file_path: Path) -> Dict: - """Load JSON file with error handling.""" + def _load_translation_file(self, file_path: Path) -> Dict: + """Load TOML translation file with error handling.""" try: - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f) + with open(file_path, 'rb') as f: + return tomllib.load(f) except FileNotFoundError: print(f"Error: File not found: {file_path}") sys.exit(1) - except json.JSONDecodeError as e: - print(f"Error: Invalid JSON in {file_path}: {e}") + except Exception as e: + print(f"Error: Invalid file {file_path}: {e}") sys.exit(1) def _load_ignore_patterns(self) -> Dict[str, Set[str]]: @@ -47,16 +39,8 @@ class TranslationAnalyzer: return {} try: - if tomllib: - # Use Python 3.11+ built-in - with open(self.ignore_file, 'rb') as f: - ignore_data = tomllib.load(f) - elif tomllib_fallback: - # Use toml library fallback - ignore_data = tomllib_fallback.load(self.ignore_file) - else: - # Simple parser as fallback - ignore_data = self._parse_simple_toml() + with open(self.ignore_file, 'rb') as f: + ignore_data = tomllib.load(f) # Convert lists to sets for faster lookup return {lang: set(patterns) for lang, data in ignore_data.items() @@ -65,31 +49,6 @@ class TranslationAnalyzer: print(f"Warning: Could not load ignore file {self.ignore_file}: {e}") return {} - def _parse_simple_toml(self) -> Dict: - """Simple TOML parser for ignore patterns (fallback).""" - ignore_data = {} - current_section = None - - with open(self.ignore_file, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if not line or line.startswith('#'): - continue - - if line.startswith('[') and line.endswith(']'): - current_section = line[1:-1] - ignore_data[current_section] = {'ignore': []} - elif line.startswith('ignore = [') and current_section: - # Handle ignore array - continue - elif line.strip().startswith("'") and current_section: - # Extract quoted items - item = line.strip().strip("',") - if item: - ignore_data[current_section]['ignore'].append(item) - - return ignore_data - def _flatten_dict(self, d: Dict, parent_key: str = '', separator: str = '.') -> Dict[str, str]: """Flatten nested dictionary into dot-notation keys.""" items = [] @@ -102,18 +61,18 @@ class TranslationAnalyzer: return dict(items) def get_all_language_files(self) -> List[Path]: - """Get all translation.json files except en-GB.""" + """Get all translation files except en-GB.""" files = [] for lang_dir in self.locales_dir.iterdir(): if lang_dir.is_dir() and lang_dir.name != "en-GB": - translation_file = lang_dir / "translation.json" - if translation_file.exists(): - files.append(translation_file) + toml_file = lang_dir / "translation.toml" + if toml_file.exists(): + files.append(toml_file) return sorted(files) def find_missing_translations(self, target_file: Path) -> Set[str]: """Find keys that exist in en-GB but missing in target file.""" - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -127,7 +86,7 @@ class TranslationAnalyzer: def find_untranslated_entries(self, target_file: Path) -> Set[str]: """Find entries that appear to be untranslated (identical to en-GB).""" - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -170,7 +129,7 @@ class TranslationAnalyzer: def find_extra_translations(self, target_file: Path) -> Set[str]: """Find keys that exist in target file but not in en-GB.""" - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -185,7 +144,7 @@ class TranslationAnalyzer: untranslated = self.find_untranslated_entries(target_file) extra = self.find_extra_translations(target_file) - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -249,8 +208,12 @@ def main(): analyzer = TranslationAnalyzer(args.locales_dir, args.ignore_file) if args.language: - target_file = Path(args.locales_dir) / args.language / "translation.json" - if not target_file.exists(): + lang_dir = Path(args.locales_dir) / args.language + toml_file = lang_dir / "translation.toml" + + if toml_file.exists(): + target_file = toml_file + else: print(f"Error: Translation file not found for language: {args.language}") sys.exit(1) results = [analyzer.analyze_file(target_file)] diff --git a/scripts/translations/translation_merger.py b/scripts/translations/translation_merger.py index 84884d946..4f2d8361a 100644 --- a/scripts/translations/translation_merger.py +++ b/scripts/translations/translation_merger.py @@ -3,6 +3,7 @@ Translation Merger for Stirling PDF Frontend Merges missing translations from en-GB into target language files. Useful for AI-assisted translation workflows. +TOML format only. """ import json @@ -14,46 +15,39 @@ import argparse import shutil from datetime import datetime -try: - import tomllib # Python 3.11+ -except ImportError: - try: - import toml as tomllib_fallback - tomllib = None - except ImportError: - tomllib = None - tomllib_fallback = None +import tomllib +import tomli_w class TranslationMerger: def __init__(self, locales_dir: str = "frontend/public/locales", ignore_file: str = "scripts/ignore_translation.toml"): self.locales_dir = Path(locales_dir) - self.golden_truth_file = self.locales_dir / "en-GB" / "translation.json" - self.golden_truth = self._load_json(self.golden_truth_file) + self.golden_truth_file = self.locales_dir / "en-GB" / "translation.toml" + self.golden_truth = self._load_translation_file(self.golden_truth_file) self.ignore_file = Path(ignore_file) self.ignore_patterns = self._load_ignore_patterns() - def _load_json(self, file_path: Path) -> Dict: - """Load JSON file with error handling.""" + def _load_translation_file(self, file_path: Path) -> Dict: + """Load TOML translation file.""" try: - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f) + with open(file_path, 'rb') as f: + return tomllib.load(f) except FileNotFoundError: print(f"Error: File not found: {file_path}") sys.exit(1) - except json.JSONDecodeError as e: - print(f"Error: Invalid JSON in {file_path}: {e}") + except Exception as e: + print(f"Error: Invalid file {file_path}: {e}") sys.exit(1) - def _save_json(self, data: Dict, file_path: Path, backup: bool = True) -> None: - """Save JSON file with backup option.""" + def _save_translation_file(self, data: Dict, file_path: Path, backup: bool = False) -> None: + """Save TOML translation file with backup option.""" if backup and file_path.exists(): - backup_path = file_path.with_suffix(f'.backup.{datetime.now().strftime("%Y%m%d_%H%M%S")}.json') + backup_path = file_path.with_suffix(f'.backup.{datetime.now().strftime("%Y%m%d_%H%M%S")}.toml') shutil.copy2(file_path, backup_path) print(f"Backup created: {backup_path}") - with open(file_path, 'w', encoding='utf-8') as f: - json.dump(data, f, indent=2, ensure_ascii=False) + with open(file_path, 'wb') as f: + tomli_w.dump(data, f) def _load_ignore_patterns(self) -> Dict[str, Set[str]]: """Load ignore patterns from TOML file.""" @@ -61,26 +55,11 @@ class TranslationMerger: return {} try: - # Simple parser for ignore patterns - ignore_data = {} - current_section = None + with open(self.ignore_file, 'rb') as f: + ignore_data = tomllib.load(f) - with open(self.ignore_file, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if not line or line.startswith('#'): - continue - - if line.startswith('[') and line.endswith(']'): - current_section = line[1:-1] - ignore_data[current_section] = set() - elif line.strip().startswith("'") and current_section: - # Extract quoted items - item = line.strip().strip("',") - if item: - ignore_data[current_section].add(item) - - return ignore_data + # Convert to sets for faster lookup + return {lang: set(data.get('ignore', [])) for lang, data in ignore_data.items()} except Exception as e: print(f"Warning: Could not load ignore file {self.ignore_file}: {e}") return {} @@ -131,7 +110,7 @@ class TranslationMerger: golden_keys = set(self._flatten_dict(self.golden_truth).keys()) return sorted(golden_keys - ignore_set) - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -144,7 +123,7 @@ class TranslationMerger: if not target_file.exists(): target_data = {} else: - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) missing_keys = keys_to_add or self.get_missing_keys(target_file) @@ -172,7 +151,7 @@ class TranslationMerger: print(f"Error: Target file does not exist: {target_file}") return {} - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) golden_flat = self._flatten_dict(self.golden_truth) target_flat = self._flatten_dict(target_data) @@ -219,13 +198,13 @@ class TranslationMerger: return False def apply_translations(self, target_file: Path, translations: Dict[str, str], - backup: bool = True) -> Dict: + backup: bool = False) -> Dict: """Apply provided translations to target file.""" if not target_file.exists(): print(f"Error: Target file does not exist: {target_file}") return {'success': False, 'error': 'File not found'} - target_data = self._load_json(target_file) + target_data = self._load_translation_file(target_file) applied_count = 0 errors = [] @@ -241,7 +220,7 @@ class TranslationMerger: errors.append(f"Error setting {key}: {e}") if applied_count > 0: - self._save_json(target_data, target_file, backup) + self._save_translation_file(target_data, target_file, backup) return { 'success': True, @@ -288,7 +267,10 @@ class TranslationMerger: def main(): - parser = argparse.ArgumentParser(description='Merge and manage translation files') + parser = argparse.ArgumentParser( + description='Merge and manage translation files', + epilog='Works with TOML translation files.' + ) parser.add_argument('--locales-dir', default='frontend/public/locales', help='Path to locales directory') parser.add_argument('--ignore-file', default='scripts/ignore_translation.toml', @@ -299,7 +281,7 @@ def main(): # Add missing command add_parser = subparsers.add_parser('add-missing', help='Add missing translations from en-GB') - add_parser.add_argument('--no-backup', action='store_true', help='Skip backup creation') + add_parser.add_argument('--backup', action='store_true', help='Create backup before modifying files') add_parser.add_argument('--mark-untranslated', action='store_true', default=True, help='Mark added translations as [UNTRANSLATED]') @@ -314,7 +296,7 @@ def main(): # Apply translations command apply_parser = subparsers.add_parser('apply-translations', help='Apply translations from JSON file') apply_parser.add_argument('--translations-file', required=True, help='JSON file with translations') - apply_parser.add_argument('--no-backup', action='store_true', help='Skip backup creation') + apply_parser.add_argument('--backup', action='store_true', help='Create backup before modifying files') args = parser.parse_args() @@ -323,7 +305,10 @@ def main(): return merger = TranslationMerger(args.locales_dir, args.ignore_file) - target_file = Path(args.locales_dir) / args.language / "translation.json" + + # Find translation file + lang_dir = Path(args.locales_dir) / args.language + target_file = lang_dir / "translation.toml" if args.command == 'add-missing': print(f"Adding missing translations to {args.language}...") @@ -332,7 +317,7 @@ def main(): mark_untranslated=args.mark_untranslated ) - merger._save_json(result['data'], target_file, backup=not args.no_backup) + merger._save_translation_file(result['data'], target_file, backup=args.backup) print(f"Added {result['added_count']} missing translations") elif args.command == 'extract-untranslated': @@ -355,7 +340,7 @@ def main(): else: translations = translations_data - result = merger.apply_translations(target_file, translations, backup=not args.no_backup) + result = merger.apply_translations(target_file, translations, backup=args.backup) if result['success']: print(f"Applied {result['applied_count']} translations") diff --git a/scripts/translations/validate_json_structure.py b/scripts/translations/validate_json_structure.py index 3f071c5be..102bc154c 100644 --- a/scripts/translations/validate_json_structure.py +++ b/scripts/translations/validate_json_structure.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 """ -Validate JSON structure and formatting of translation files. +Validate TOML structure and formatting of translation files. Checks for: -- Valid JSON syntax +- Valid TOML syntax - Consistent key structure with en-GB - Missing keys - Extra keys not in en-GB @@ -18,6 +18,7 @@ import sys from pathlib import Path from typing import Dict, List, Set import argparse +import tomllib # Python 3.11+ (stdlib) def get_all_keys(d: dict, parent_key: str = '', sep: str = '.') -> Set[str]: @@ -31,14 +32,12 @@ def get_all_keys(d: dict, parent_key: str = '', sep: str = '.') -> Set[str]: return keys -def validate_json_file(file_path: Path) -> tuple[bool, str]: - """Validate that a file contains valid JSON.""" +def validate_translation_file(file_path: Path) -> tuple[bool, str]: + """Validate that a file contains valid TOML.""" try: - with open(file_path, 'r', encoding='utf-8') as f: - json.load(f) - return True, "Valid JSON" - except json.JSONDecodeError as e: - return False, f"Invalid JSON at line {e.lineno}, column {e.colno}: {e.msg}" + with open(file_path, 'rb') as f: + tomllib.load(f) + return True, "Valid TOML" except Exception as e: return False, f"Error reading file: {str(e)}" @@ -101,9 +100,15 @@ def print_validation_result(result: Dict, verbose: bool = False): print("-" * 100) +def load_translation_file(file_path: Path) -> dict: + """Load TOML translation file.""" + with open(file_path, 'rb') as f: + return tomllib.load(f) + + def main(): parser = argparse.ArgumentParser( - description='Validate translation JSON structure' + description='Validate translation TOML structure' ) parser.add_argument( '--language', @@ -125,21 +130,21 @@ def main(): # Define paths locales_dir = Path('frontend/public/locales') - en_gb_path = locales_dir / 'en-GB' / 'translation.json' + en_gb_path = locales_dir / 'en-GB' / 'translation.toml' + file_ext = '.toml' if not en_gb_path.exists(): print(f"❌ Error: en-GB translation file not found at {en_gb_path}") sys.exit(1) # Validate en-GB itself - is_valid, message = validate_json_file(en_gb_path) + is_valid, message = validate_translation_file(en_gb_path) if not is_valid: print(f"❌ Error in en-GB file: {message}") sys.exit(1) # Load en-GB structure - with open(en_gb_path, 'r', encoding='utf-8') as f: - en_gb = json.load(f) + en_gb = load_translation_file(en_gb_path) en_gb_keys = get_all_keys(en_gb) @@ -147,24 +152,26 @@ def main(): if args.language: languages = [args.language] else: - languages = [ - d.name for d in locales_dir.iterdir() - if d.is_dir() and d.name != 'en-GB' and (d / 'translation.json').exists() - ] + # Validate all languages except en-GB + languages = [] + for d in locales_dir.iterdir(): + if d.is_dir() and d.name != 'en-GB': + if (d / 'translation.toml').exists(): + languages.append(d.name) results = [] json_errors = [] # Validate each language for lang_code in sorted(languages): - lang_path = locales_dir / lang_code / 'translation.json' + lang_path = locales_dir / lang_code / 'translation.toml' if not lang_path.exists(): - print(f"⚠️ Warning: {lang_code}/translation.json not found, skipping") + print(f"⚠️ Warning: {lang_code}/translation.toml not found, skipping") continue - # First check if JSON is valid - is_valid, message = validate_json_file(lang_path) + # First check if file is valid + is_valid, message = validate_translation_file(lang_path) if not is_valid: json_errors.append({ 'language': lang_code, @@ -174,8 +181,7 @@ def main(): continue # Load and compare structure - with open(lang_path, 'r', encoding='utf-8') as f: - lang_data = json.load(f) + lang_data = load_translation_file(lang_path) lang_keys = get_all_keys(lang_data) result = validate_structure(en_gb_keys, lang_keys, lang_code) @@ -189,9 +195,9 @@ def main(): } print(json.dumps(output, indent=2, ensure_ascii=False)) else: - # Print JSON errors first + # Print syntax errors first if json_errors: - print("\n❌ JSON Syntax Errors:") + print("\n❌ Syntax Errors:") print("=" * 100) for error in json_errors: print(f"\nLanguage: {error['language']}") diff --git a/scripts/translations/validate_placeholders.py b/scripts/translations/validate_placeholders.py index ff73755ce..5ce18d288 100644 --- a/scripts/translations/validate_placeholders.py +++ b/scripts/translations/validate_placeholders.py @@ -15,6 +15,7 @@ import sys from pathlib import Path from typing import Dict, List, Set, Tuple import argparse +import tomllib # Python 3.11+ (stdlib) def find_placeholders(text: str) -> Set[str]: @@ -117,15 +118,16 @@ def main(): # Define paths locales_dir = Path('frontend/public/locales') - en_gb_path = locales_dir / 'en-GB' / 'translation.json' + en_gb_path = locales_dir / 'en-GB' / 'translation.toml' + file_ext = '.toml' if not en_gb_path.exists(): print(f"❌ Error: en-GB translation file not found at {en_gb_path}") sys.exit(1) # Load en-GB (source of truth) - with open(en_gb_path, 'r', encoding='utf-8') as f: - en_gb = json.load(f) + with open(en_gb_path, 'rb') as f: + en_gb = tomllib.load(f) en_gb_flat = flatten_dict(en_gb) @@ -134,23 +136,25 @@ def main(): languages = [args.language] else: # Validate all languages except en-GB - languages = [ - d.name for d in locales_dir.iterdir() - if d.is_dir() and d.name != 'en-GB' and (d / 'translation.json').exists() - ] + languages = [] + for d in locales_dir.iterdir(): + if d.is_dir() and d.name != 'en-GB': + if (d / 'translation.toml').exists(): + languages.append(d.name) all_issues = [] # Validate each language for lang_code in sorted(languages): - lang_path = locales_dir / lang_code / 'translation.json' + lang_path = locales_dir / lang_code / 'translation.toml' if not lang_path.exists(): - print(f"⚠️ Warning: {lang_code}/translation.json not found, skipping") + print(f"⚠️ Warning: {lang_code}/translation.toml not found, skipping") continue - with open(lang_path, 'r', encoding='utf-8') as f: - lang_data = json.load(f) + # Load language file + with open(lang_path, 'rb') as f: + lang_data = tomllib.load(f) lang_flat = flatten_dict(lang_data) issues = validate_language(en_gb_flat, lang_flat, lang_code) From f902e8aca9ed19160f411cfcce552eb8a4c70b25 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 3 Dec 2025 10:54:53 +0000 Subject: [PATCH 06/56] OAuth Provider Buttons (#5103) PR to allow other OAuth providers to be displayed on the login screen. Will show a generic icon when the provider is not in the known set of providers. 47ab288dadbc889fd84cc83c9ded0829 --------- Signed-off-by: dependabot[bot] Signed-off-by: stirlingbot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ludy Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com> Co-authored-by: Ethan Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com> --- frontend/public/Login/authentik.svg | 5 +++ frontend/public/Login/cloudron.svg | 5 +++ frontend/public/Login/keycloak.svg | 1 + frontend/public/Login/oidc.svg | 6 +++ frontend/src/core/setupTests.ts | 34 +++++++++++++++ frontend/src/proprietary/routes/Login.tsx | 16 +++++-- .../proprietary/routes/login/OAuthButtons.tsx | 43 ++++++++++++------- 7 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 frontend/public/Login/authentik.svg create mode 100644 frontend/public/Login/cloudron.svg create mode 100644 frontend/public/Login/keycloak.svg create mode 100644 frontend/public/Login/oidc.svg diff --git a/frontend/public/Login/authentik.svg b/frontend/public/Login/authentik.svg new file mode 100644 index 000000000..26dc0189e --- /dev/null +++ b/frontend/public/Login/authentik.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/public/Login/cloudron.svg b/frontend/public/Login/cloudron.svg new file mode 100644 index 000000000..a4b50c421 --- /dev/null +++ b/frontend/public/Login/cloudron.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/public/Login/keycloak.svg b/frontend/public/Login/keycloak.svg new file mode 100644 index 000000000..30628c7b2 --- /dev/null +++ b/frontend/public/Login/keycloak.svg @@ -0,0 +1 @@ + diff --git a/frontend/public/Login/oidc.svg b/frontend/public/Login/oidc.svg new file mode 100644 index 000000000..440b54487 --- /dev/null +++ b/frontend/public/Login/oidc.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/src/core/setupTests.ts b/frontend/src/core/setupTests.ts index 3ebb22fda..0e5e9737a 100644 --- a/frontend/src/core/setupTests.ts +++ b/frontend/src/core/setupTests.ts @@ -1,6 +1,40 @@ import '@testing-library/jest-dom'; import { vi } from 'vitest'; +// Mock localStorage for tests +class LocalStorageMock implements Storage { + private store: Record = {}; + + get length(): number { + return Object.keys(this.store).length; + } + + clear(): void { + this.store = {}; + } + + getItem(key: string): string | null { + return this.store[key] ?? null; + } + + key(index: number): string | null { + return Object.keys(this.store)[index] ?? null; + } + + removeItem(key: string): void { + delete this.store[key]; + } + + setItem(key: string, value: string): void { + this.store[key] = value; + } +} + +Object.defineProperty(window, 'localStorage', { + value: new LocalStorageMock(), + writable: true, +}); + // Mock i18next for tests vi.mock('react-i18next', () => ({ useTranslation: () => ({ diff --git a/frontend/src/proprietary/routes/Login.tsx b/frontend/src/proprietary/routes/Login.tsx index 4390131ca..80a12e1d0 100644 --- a/frontend/src/proprietary/routes/Login.tsx +++ b/frontend/src/proprietary/routes/Login.tsx @@ -107,6 +107,7 @@ export default function Login() { const providerIds = Object.keys(data.providerList || {}) .map(key => key.split('/').pop()) .filter((id): id is string => id !== undefined); + setEnabledProviders(providerIds); } catch (err) { console.error('[Login] Failed to fetch enabled providers:', err); @@ -225,16 +226,25 @@ export default function Login() { ); } - const signInWithProvider = async (provider: 'github' | 'google' | 'apple' | 'azure' | 'keycloak' | 'oidc') => { + // Known OAuth providers that have dedicated backend support + const KNOWN_OAUTH_PROVIDERS = ['github', 'google', 'apple', 'azure', 'keycloak', 'oidc'] as const; + type KnownOAuthProvider = typeof KNOWN_OAUTH_PROVIDERS[number]; + + const signInWithProvider = async (provider: string) => { try { setIsSigningIn(true); setError(null); - console.log(`[Login] Signing in with ${provider}`); + // Map unknown providers to 'oidc' for the backend redirect + const backendProvider: KnownOAuthProvider = KNOWN_OAUTH_PROVIDERS.includes(provider as KnownOAuthProvider) + ? (provider as KnownOAuthProvider) + : 'oidc'; + + console.log(`[Login] Signing in with ${provider} (backend: ${backendProvider})`); // Redirect to Spring OAuth2 endpoint const { error } = await springAuth.signInWithOAuth({ - provider, + provider: backendProvider, options: { redirectTo: `${BASE_PATH}/auth/callback` } }); diff --git a/frontend/src/proprietary/routes/login/OAuthButtons.tsx b/frontend/src/proprietary/routes/login/OAuthButtons.tsx index b0cd4a89e..aaa280519 100644 --- a/frontend/src/proprietary/routes/login/OAuthButtons.tsx +++ b/frontend/src/proprietary/routes/login/OAuthButtons.tsx @@ -6,19 +6,23 @@ import { BASE_PATH } from '@app/constants/app'; export const DEBUG_SHOW_ALL_PROVIDERS = false; // OAuth provider configuration - maps provider ID to display info -export const oauthProviderConfig = { +// Known providers get custom icons; unknown providers use generic SSO icon +export const oauthProviderConfig: Record = { google: { label: 'Google', file: 'google.svg' }, github: { label: 'GitHub', file: 'github.svg' }, apple: { label: 'Apple', file: 'apple.svg' }, azure: { label: 'Microsoft', file: 'microsoft.svg' }, - // microsoft and azure are the same, keycloak and oidc need their own icons - // These are commented out from debug view since they need proper icons or backend doesn't use them - // keycloak: { label: 'Keycloak', file: 'keycloak.svg' }, - // oidc: { label: 'OIDC', file: 'oidc.svg' } + keycloak: { label: 'Keycloak', file: 'keycloak.svg' }, + cloudron: { label: 'Cloudron', file: 'cloudron.svg' }, + authentik: { label: 'Authentik', file: 'authentik.svg' }, + oidc: { label: 'OIDC', file: 'oidc.svg' } }; +// Generic fallback for unknown providers +const GENERIC_PROVIDER_ICON = 'oidc.svg'; + interface OAuthButtonsProps { - onProviderClick: (provider: 'github' | 'google' | 'apple' | 'azure' | 'keycloak' | 'oidc') => void + onProviderClick: (provider: string) => void isSubmitting: boolean layout?: 'vertical' | 'grid' | 'icons' enabledProviders?: string[] // List of enabled provider IDs from backend @@ -32,13 +36,22 @@ export default function OAuthButtons({ onProviderClick, isSubmitting, layout = ' ? Object.keys(oauthProviderConfig) : enabledProviders; - // Filter to only show enabled providers from backend - const providers = providersToShow - .filter(id => id in oauthProviderConfig) - .map(id => ({ + // Build provider list - use provider ID to determine icon and label + const providers = providersToShow.map(id => { + if (id in oauthProviderConfig) { + // Known provider - use predefined icon and label + return { + id, + ...oauthProviderConfig[id] + }; + } + // Unknown provider - use generic icon and capitalize ID for label + return { id, - ...oauthProviderConfig[id as keyof typeof oauthProviderConfig] - })); + label: id.charAt(0).toUpperCase() + id.slice(1), + file: GENERIC_PROVIDER_ICON + }; + }); // If no providers are enabled, don't render anything if (providers.length === 0) { @@ -51,7 +64,7 @@ export default function OAuthButtons({ onProviderClick, isSubmitting, layout = ' {providers.map((p) => (
+ + + ); +}; + +export default GetPdfInfoResults; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/KeyValueSection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/KeyValueSection.tsx new file mode 100644 index 000000000..a98a47568 --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/sections/KeyValueSection.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; +import KeyValueList from '@app/components/tools/getPdfInfo/shared/KeyValueList'; + +interface KeyValueSectionProps { + title: string; + anchorId: string; + obj?: Record | null; + emptyLabel?: string; +} + +const KeyValueSection: React.FC = ({ title, anchorId, obj, emptyLabel }) => { + return ( + + + + ); +}; + +export default KeyValueSection; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx new file mode 100644 index 000000000..e7eb8d8b3 --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { Accordion, Stack, Text } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import type { PdfOtherInfo } from '@app/types/getPdfInfo'; +import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; +import ScrollableCodeBlock from '@app/components/tools/getPdfInfo/shared/ScrollableCodeBlock'; +import { pdfInfoAccordionStyles } from '@app/components/tools/getPdfInfo/shared/accordionStyles'; + +interface OtherSectionProps { + anchorId: string; + other?: PdfOtherInfo | null; +} + +const renderList = (arr: unknown[] | undefined, emptyText: string) => { + if (!arr || arr.length === 0) return {emptyText}; + return ( + + {arr.map((item, idx) => ( + + {typeof item === 'string' ? item : JSON.stringify(item)} + + ))} + + ); +}; + +const OtherSection: React.FC = ({ anchorId, other }) => { + const { t } = useTranslation(); + const noneDetected = t('getPdfInfo.noneDetected', 'None detected'); + + const structureTreeContent = Array.isArray(other?.StructureTree) && other.StructureTree.length > 0 + ? JSON.stringify(other.StructureTree, null, 2) + : null; + + return ( + + + + {t('getPdfInfo.other.attachments', 'Attachments')} + {renderList(other?.Attachments, noneDetected)} + + + {t('getPdfInfo.other.embeddedFiles', 'Embedded Files')} + {renderList(other?.EmbeddedFiles, noneDetected)} + + + {t('getPdfInfo.other.javaScript', 'JavaScript')} + {renderList(other?.JavaScript, noneDetected)} + + + {t('getPdfInfo.other.layers', 'Layers')} + {renderList(other?.Layers, noneDetected)} + + + + + {t('getPdfInfo.other.structureTree', 'StructureTree')} + + + + + + + + {t('getPdfInfo.other.xmp', 'XMPMetadata')} + + + + + + + + + ); +}; + +export default OtherSection; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx new file mode 100644 index 000000000..4fd257cce --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import { Accordion, Stack, Text } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import type { PdfPerPageInfo, PdfPageInfo, PdfFontInfo } from '@app/types/getPdfInfo'; +import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; +import KeyValueList from '@app/components/tools/getPdfInfo/shared/KeyValueList'; +import { pdfInfoAccordionStyles } from '@app/components/tools/getPdfInfo/shared/accordionStyles'; + +interface PerPageSectionProps { + anchorId: string; + perPage?: PdfPerPageInfo | null; +} + +const renderList = (arr: unknown[] | undefined, emptyText: string) => { + if (!arr || arr.length === 0) return {emptyText}; + return ( + + {arr.map((item, idx) => ( + + {typeof item === 'string' ? item : JSON.stringify(item)} + + ))} + + ); +}; + +const renderFontsList = (fonts: PdfFontInfo[] | undefined, emptyText: string) => { + if (!fonts || fonts.length === 0) return {emptyText}; + return ( + + {fonts.map((font, idx) => ( + + {`${font.Name ?? 'Unknown'}${font.IsEmbedded ? ' (embedded)' : ''}`} + + ))} + + ); +}; + +const PerPageSection: React.FC = ({ anchorId, perPage }) => { + const { t } = useTranslation(); + const noneDetected = t('getPdfInfo.noneDetected', 'None detected'); + + const hasPages = perPage && Object.keys(perPage).length > 0; + + return ( + + {hasPages ? ( + + {Object.entries(perPage).map(([pageLabel, pageInfo]: [string, PdfPageInfo]) => ( + + + {pageLabel} + + +
+ + {pageInfo?.Size && ( + + {t('getPdfInfo.perPage.size', 'Size')} + + + )} + + {pageInfo?.Annotations && ( + + {t('getPdfInfo.perPage.annotations', 'Annotations')} + + + )} + + {t('getPdfInfo.perPage.images', 'Images')} + {renderList(pageInfo?.Images, noneDetected)} + + + {t('getPdfInfo.perPage.links', 'Links')} + {renderList(pageInfo?.Links, noneDetected)} + + + {t('getPdfInfo.perPage.fonts', 'Fonts')} + {renderFontsList(pageInfo?.Fonts, noneDetected)} + + {pageInfo?.XObjectCounts && ( + + {t('getPdfInfo.perPage.xobjects', 'XObject Counts')} + + + )} + + {t('getPdfInfo.perPage.multimedia', 'Multimedia')} + {renderList(pageInfo?.Multimedia, noneDetected)} + + +
+
+
+ ))} +
+ ) : ( + {noneDetected} + )} +
+ ); +}; + +export default PerPageSection; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/SummarySection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/SummarySection.tsx new file mode 100644 index 000000000..680f4b64d --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/sections/SummarySection.tsx @@ -0,0 +1,148 @@ +import React, { useMemo } from 'react'; +import { Stack, Text } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import type { ParsedPdfSections, PdfFontInfo } from '@app/types/getPdfInfo'; +import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; +import KeyValueList from '@app/components/tools/getPdfInfo/shared/KeyValueList'; + +interface SummarySectionProps { + sections: ParsedPdfSections; + hideSectionTitle?: boolean; +} + +const SummarySection: React.FC = ({ sections, hideSectionTitle = false }) => { + const { t } = useTranslation(); + + const summaryBlocks = useMemo(() => { + const basic = sections.basicInfo ?? {}; + const docInfo = sections.documentInfo ?? {}; + const metadata = sections.metadata ?? {}; + const encryption = sections.encryption ?? {}; + const permissions = sections.permissions ?? {}; + const summary = sections.summaryData ?? {}; + const other = sections.other ?? {}; + const perPage = sections.perPage ?? {}; + + const pages = basic['Number of pages']; + const fileSizeBytes = basic.FileSizeInBytes; + const pdfVersion = docInfo['PDF version']; + const language = basic.Language; + + const basicInformation: Record = { + [t('getPdfInfo.summary.pages', 'Pages')]: pages, + [t('getPdfInfo.summary.fileSize', 'File Size')]: typeof fileSizeBytes === 'number' ? `${(fileSizeBytes / 1024).toFixed(2)} KB` : fileSizeBytes, + [t('getPdfInfo.summary.pdfVersion', 'PDF Version')]: pdfVersion, + [t('getPdfInfo.summary.language', 'Language')]: language, + }; + + const documentInformation: Record = { + [t('getPdfInfo.summary.title', 'Title')]: metadata.Title, + [t('getPdfInfo.summary.author', 'Author')]: metadata.Author, + [t('getPdfInfo.summary.created', 'Created')]: metadata.CreationDate, + [t('getPdfInfo.summary.modified', 'Modified')]: metadata.ModificationDate, + }; + + const securityStatusText = encryption.IsEncrypted + ? t('getPdfInfo.summary.security.encrypted', 'Encrypted PDF - Password protection present') + : t('getPdfInfo.summary.security.unencrypted', 'Unencrypted PDF - No password protection'); + + const restrictedCount = summary.restrictedPermissionsCount ?? 0; + const permissionsAllAllowed = Object.values(permissions).every((v) => v === 'Allowed'); + const permSummary = permissionsAllAllowed + ? t('getPdfInfo.summary.permsAll', 'All Permissions Allowed') + : restrictedCount > 0 + ? t('getPdfInfo.summary.permsRestricted', '{{count}} restrictions', { count: restrictedCount }) + : t('getPdfInfo.summary.permsMixed', 'Some permissions restricted'); + + const complianceText = sections.compliance && Object.values(sections.compliance).some(Boolean) + ? t('getPdfInfo.summary.hasCompliance', 'Has compliance standards') + : t('getPdfInfo.summary.noCompliance', 'No Compliance Standards'); + + // Helper to get first page data + const firstPage = perPage['Page 1']; + const firstPageFonts: PdfFontInfo[] = firstPage?.Fonts ?? []; + + const technical: Record = { + [t('getPdfInfo.summary.tech.images', 'Images')]: (() => { + const total = basic.TotalImages; + if (typeof total === 'number') return total === 0 ? 'None' : `${total}`; + return 'None'; + })(), + [t('getPdfInfo.summary.tech.fonts', 'Fonts')]: (() => { + if (firstPageFonts.length === 0) return 'None'; + const embedded = firstPageFonts.filter((f) => f.IsEmbedded).length; + return `${firstPageFonts.length} (${embedded} embedded)`; + })(), + [t('getPdfInfo.summary.tech.formFields', 'Form Fields')]: sections.formFields && Object.keys(sections.formFields).length > 0 ? Object.keys(sections.formFields).length : 'None', + [t('getPdfInfo.summary.tech.embeddedFiles', 'Embedded Files')]: other.EmbeddedFiles?.length ?? 'None', + [t('getPdfInfo.summary.tech.javaScript', 'JavaScript')]: other.JavaScript?.length ?? 'None', + [t('getPdfInfo.summary.tech.layers', 'Layers')]: other.Layers?.length ?? 'None', + [t('getPdfInfo.summary.tech.bookmarks', 'Bookmarks')]: sections.toc?.length ?? 'None', + [t('getPdfInfo.summary.tech.multimedia', 'Multimedia')]: firstPage?.Multimedia?.length ?? 'None', + }; + + const overview = (() => { + const tTitle = metadata.Title ? `"${metadata.Title}"` : t('getPdfInfo.summary.overview.untitled', 'an untitled document'); + const author = metadata.Author || t('getPdfInfo.summary.overview.unknown', 'Unknown Author'); + const pagesCount = typeof pages === 'number' ? pages : '?'; + const version = pdfVersion ?? '?'; + return t('getPdfInfo.summary.overview.text', 'This is a {{pages}}-page PDF titled {{title}} created by {{author}} (PDF version {{version}}).', { + pages: pagesCount, + title: tTitle, + author, + version, + }); + })(); + + return { + basicInformation, + documentInformation, + securityStatusText, + permSummary, + complianceText, + technical, + overview, + }; + }, [sections, t]); + + const content = ( + + + {t('getPdfInfo.summary.basic', 'Basic Information')} + + + + {t('getPdfInfo.summary.documentInfo', 'Document Information')} + + + + {t('getPdfInfo.summary.securityTitle', 'Security Status')} + {summaryBlocks.securityStatusText} + {summaryBlocks.permSummary} + {summaryBlocks.complianceText} + + + {t('getPdfInfo.summary.technical', 'Technical')} + + + + {t('getPdfInfo.summary.overviewTitle', 'PDF Overview')} + {summaryBlocks.overview} + + + ); + + if (hideSectionTitle) { + return
{content}
; + } + + return ( + + {content} + + ); +}; + +export default SummarySection; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/TableOfContentsSection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/TableOfContentsSection.tsx new file mode 100644 index 000000000..57e4ac2fe --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/sections/TableOfContentsSection.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Stack, Text } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import type { PdfTocEntry } from '@app/types/getPdfInfo'; +import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; + +interface TableOfContentsSectionProps { + anchorId: string; + tocArray: PdfTocEntry[]; +} + +const TableOfContentsSection: React.FC = ({ anchorId, tocArray }) => { + const { t } = useTranslation(); + const noneDetected = t('getPdfInfo.noneDetected', 'None detected'); + + return ( + + {!tocArray || tocArray.length === 0 ? ( + {noneDetected} + ) : ( + + {tocArray.map((item, idx) => ( + + {typeof item === 'string' ? item : JSON.stringify(item)} + + ))} + + )} + + ); +}; + +export default TableOfContentsSection; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/shared/KeyValueList.tsx b/frontend/src/core/components/tools/getPdfInfo/shared/KeyValueList.tsx new file mode 100644 index 000000000..e0cd809cc --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/shared/KeyValueList.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Group, Stack, Text } from '@mantine/core'; + +interface KeyValueListProps { + obj?: Record | null; + emptyLabel?: string; +} + +const KeyValueList: React.FC = ({ obj, emptyLabel }) => { + if (!obj || Object.keys(obj).length === 0) { + return {emptyLabel ?? 'None detected'}; + } + return ( + + {Object.entries(obj).map(([k, v]) => ( + + {k} + + {v == null ? '' : String(v)} + + + ))} + + ); +}; + +export default KeyValueList; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/shared/ScrollableCodeBlock.tsx b/frontend/src/core/components/tools/getPdfInfo/shared/ScrollableCodeBlock.tsx new file mode 100644 index 000000000..bf0426426 --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/shared/ScrollableCodeBlock.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Code, Text } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; + +interface ScrollableCodeBlockProps { + content: string | null | undefined; + maxHeight?: string; + emptyMessage?: string; +} + +/** + * A reusable scrollable code block component with consistent styling. + * Used for displaying large text content like XMP metadata or structure trees. + */ +const ScrollableCodeBlock: React.FC = ({ + content, + maxHeight = '400px', + emptyMessage, +}) => { + const { t } = useTranslation(); + + if (!content) { + return ( + + {emptyMessage ?? t('getPdfInfo.noneDetected', 'None detected')} + + ); + } + + return ( + + {content} + + ); +}; + +export default ScrollableCodeBlock; + diff --git a/frontend/src/core/components/tools/getPdfInfo/shared/SectionBlock.tsx b/frontend/src/core/components/tools/getPdfInfo/shared/SectionBlock.tsx new file mode 100644 index 000000000..0faa993f6 --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/shared/SectionBlock.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { Stack, Text, Divider } from '@mantine/core'; + +interface SectionBlockProps { + title: string; + anchorId: string; + children: React.ReactNode; +} + +const SectionBlock: React.FC = ({ title, anchorId, children }) => { + return ( + + {title} + + {children} + + ); +}; + +export default SectionBlock; + + diff --git a/frontend/src/core/components/tools/getPdfInfo/shared/accordionStyles.ts b/frontend/src/core/components/tools/getPdfInfo/shared/accordionStyles.ts new file mode 100644 index 000000000..e974c9845 --- /dev/null +++ b/frontend/src/core/components/tools/getPdfInfo/shared/accordionStyles.ts @@ -0,0 +1,14 @@ +import type { AccordionStylesNames } from '@mantine/core'; +import type { CSSProperties } from 'react'; + +type AccordionStyles = Partial>; + +export const pdfInfoAccordionStyles: AccordionStyles = { + item: { + backgroundColor: 'var(--accordion-item-bg)', + }, + control: { + backgroundColor: 'transparent', + }, +}; + diff --git a/frontend/src/core/components/tools/validateSignature/reportView/styles.css b/frontend/src/core/components/tools/validateSignature/reportView/styles.css index b2d01f224..27b1081d4 100644 --- a/frontend/src/core/components/tools/validateSignature/reportView/styles.css +++ b/frontend/src/core/components/tools/validateSignature/reportView/styles.css @@ -44,15 +44,15 @@ .simulated-page { width: min(820px, 100%); min-height: 1040px; - background-color: rgb(var(--pdf-light-simulated-page-bg)) !important; - box-shadow: 0 12px 32px rgba(var(--pdf-light-simulated-page-text), 0.12) !important; + background-color: var(--bg-raised) !important; + box-shadow: 0 12px 32px var(--shadow-color) !important; border-radius: 12px !important; padding: 48px 56px !important; position: relative; overflow: hidden; display: flex; flex-direction: column; - color: rgb(var(--pdf-light-simulated-page-text)) !important; + color: var(--text-primary) !important; } /* Container for the interactive report view */ @@ -67,12 +67,12 @@ /* Keep field blocks stable colors across themes */ .field-value { - border: 1px solid rgb(var(--pdf-light-box-border)) !important; - background-color: rgb(var(--pdf-light-box-bg)) !important; + border: 1px solid var(--border-default) !important; + background-color: var(--bg-raised) !important; } .field-container { - color: rgb(var(--pdf-light-simulated-page-text)) !important; + color: var(--text-primary) !important; } /* Thumbnail preview styles */ @@ -103,3 +103,28 @@ color: rgb(var(--pdf-light-text-muted)); background: linear-gradient(145deg, var(--mantine-color-gray-1) 0%, var(--mantine-color-gray-0) 100%); } + +/* Flash highlight animation for section navigation */ +@keyframes section-flash { + 0% { + background-color: rgba(255, 235, 59, 0); + box-shadow: none; + } + 20% { + background-color: rgba(255, 235, 59, 0.35); + box-shadow: 0 0 20px rgba(255, 235, 59, 0.5); + } + 50% { + background-color: rgba(255, 235, 59, 0.25); + box-shadow: 0 0 15px rgba(255, 235, 59, 0.4); + } + 100% { + background-color: rgba(255, 235, 59, 0); + box-shadow: none; + } +} + +.section-flash-highlight { + animation: section-flash 1.5s ease-out; + border-radius: 8px; +} diff --git a/frontend/src/core/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx index 5d0bcd622..bc514d879 100644 --- a/frontend/src/core/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -27,6 +27,7 @@ import AdjustContrastSingleStepSettings from "@app/components/tools/adjustContra import { adjustContrastOperationConfig } from "@app/hooks/tools/adjustContrast/useAdjustContrastOperation"; import { getSynonyms } from "@app/utils/toolSynonyms"; import { useProprietaryToolRegistry } from "@app/data/useProprietaryToolRegistry"; +import GetPdfInfo from "@app/tools/GetPdfInfo"; import AddWatermark from "@app/tools/AddWatermark"; import AddStamp from "@app/tools/AddStamp"; import AddAttachments from "@app/tools/AddAttachments"; @@ -324,14 +325,15 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { getPdfInfo: { icon: , name: t("home.getPdfInfo.title", "Get ALL Info on PDF"), - component: null, + component: GetPdfInfo, description: t("home.getPdfInfo.desc", "Grabs any and all information possible on PDFs"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.VERIFICATION, endpoints: ["get-info-on-pdf"], synonyms: getSynonyms(t, "getPdfInfo"), supportsAutomate: false, - automationSettings: null + automationSettings: null, + maxFiles: 1, }, validateSignature: { icon: , diff --git a/frontend/src/core/hooks/tools/getPdfInfo/useGetPdfInfoOperation.ts b/frontend/src/core/hooks/tools/getPdfInfo/useGetPdfInfoOperation.ts new file mode 100644 index 000000000..019968bca --- /dev/null +++ b/frontend/src/core/hooks/tools/getPdfInfo/useGetPdfInfoOperation.ts @@ -0,0 +1,194 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import apiClient from '@app/services/apiClient'; +import { useFileContext } from '@app/contexts/file/fileHooks'; +import { ToolOperationHook } from '@app/hooks/tools/shared/useToolOperation'; +import type { StirlingFile } from '@app/types/fileContext'; +import { extractErrorMessage } from '@app/utils/toolErrorHandler'; +import { + PdfInfoReportEntry, + INFO_JSON_FILENAME, +} from '@app/types/getPdfInfo'; +import type { GetPdfInfoParameters } from '@app/hooks/tools/getPdfInfo/useGetPdfInfoParameters'; + +export interface GetPdfInfoOperationHook extends ToolOperationHook { + results: PdfInfoReportEntry[]; +} + +export const useGetPdfInfoOperation = (): GetPdfInfoOperationHook => { + const { t } = useTranslation(); + const { selectors } = useFileContext(); + const [isLoading, setIsLoading] = useState(false); + const [status, setStatus] = useState(''); + const [errorMessage, setErrorMessage] = useState(null); + const [files, setFiles] = useState([]); + const [downloadUrl, setDownloadUrl] = useState(null); + const [downloadFilename, setDownloadFilename] = useState(''); + const [results, setResults] = useState([]); + + const cancelRequested = useRef(false); + const previousUrl = useRef(null); + + const cleanupDownloadUrl = useCallback(() => { + if (previousUrl.current) { + URL.revokeObjectURL(previousUrl.current); + previousUrl.current = null; + } + }, []); + + const resetResults = useCallback(() => { + cancelRequested.current = false; + setResults([]); + setFiles([]); + cleanupDownloadUrl(); + setDownloadUrl(null); + setDownloadFilename(''); + setStatus(''); + setErrorMessage(null); + }, [cleanupDownloadUrl]); + + const clearError = useCallback(() => { + setErrorMessage(null); + }, []); + + const executeOperation = useCallback( + async (_params: GetPdfInfoParameters, selectedFiles: StirlingFile[]) => { + if (selectedFiles.length === 0) { + setErrorMessage(t('noFileSelected', 'No files selected')); + return; + } + + cancelRequested.current = false; + setIsLoading(true); + setStatus(t('getPdfInfo.processing', 'Extracting information...')); + setErrorMessage(null); + setResults([]); + setFiles([]); + cleanupDownloadUrl(); + setDownloadUrl(null); + setDownloadFilename(''); + + try { + const aggregated: PdfInfoReportEntry[] = []; + const generatedAt = Date.now(); + + for (const file of selectedFiles) { + if (cancelRequested.current) break; + + const formData = new FormData(); + formData.append('fileInput', file); + + try { + const response = await apiClient.post('/api/v1/security/get-info-on-pdf', formData, { + headers: { 'Content-Type': 'multipart/form-data' }, + }); + + const stub = selectors.getStirlingFileStub(file.fileId); + const entry: PdfInfoReportEntry = { + fileId: file.fileId, + fileName: file.name, + fileSize: file.size ?? null, + lastModified: file.lastModified ?? null, + thumbnailUrl: stub?.thumbnailUrl ?? null, + data: response.data ?? {}, + error: null, + summaryGeneratedAt: generatedAt, + }; + aggregated.push(entry); + } catch (error) { + const stub = selectors.getStirlingFileStub(file.fileId); + aggregated.push({ + fileId: file.fileId, + fileName: file.name, + fileSize: file.size ?? null, + lastModified: file.lastModified ?? null, + thumbnailUrl: stub?.thumbnailUrl ?? null, + data: {}, + error: extractErrorMessage(error), + summaryGeneratedAt: generatedAt, + }); + } + } + + if (!cancelRequested.current) { + setResults(aggregated); + if (aggregated.length > 0) { + // Build V1-compatible JSON: use backend payloads directly. + const payloads = aggregated + .filter((e) => !e.error) + .map((e) => e.data); + const content = payloads.length === 1 ? payloads[0] : payloads; + const json = JSON.stringify(content, null, 2); + const resultFile = new File([json], INFO_JSON_FILENAME, { type: 'application/json' }); + setFiles([resultFile]); + } + + const anyError = aggregated.some((item) => item.error); + if (anyError) { + setErrorMessage(t('getPdfInfo.error.partial', 'Some files could not be processed.')); + } + setStatus(t('getPdfInfo.status.complete', 'Extraction complete')); + } + } catch (e) { + console.error('[getPdfInfo] unexpected failure', e); + setErrorMessage(t('getPdfInfo.error.unexpected', 'Unexpected error during extraction.')); + } finally { + setIsLoading(false); + } + }, + [cleanupDownloadUrl, selectors, t] + ); + + const cancelOperation = useCallback(() => { + if (isLoading) { + cancelRequested.current = true; + setIsLoading(false); + setStatus(t('operationCancelled', 'Operation cancelled')); + } + }, [isLoading, t]); + + const undoOperation = useCallback(async () => { + resetResults(); + }, [resetResults]); + + useEffect(() => { + return () => { + cleanupDownloadUrl(); + }; + }, [cleanupDownloadUrl]); + + return useMemo( + () => ({ + files, + thumbnails: [], + isGeneratingThumbnails: false, + downloadUrl, + downloadFilename, + isLoading, + status, + errorMessage, + progress: null, + executeOperation, + resetResults, + clearError, + cancelOperation, + undoOperation, + results, + }), + [ + cancelOperation, + clearError, + downloadFilename, + downloadUrl, + errorMessage, + executeOperation, + files, + isLoading, + resetResults, + results, + status, + ] + ); +}; + + diff --git a/frontend/src/core/hooks/tools/getPdfInfo/useGetPdfInfoParameters.ts b/frontend/src/core/hooks/tools/getPdfInfo/useGetPdfInfoParameters.ts new file mode 100644 index 000000000..488484809 --- /dev/null +++ b/frontend/src/core/hooks/tools/getPdfInfo/useGetPdfInfoParameters.ts @@ -0,0 +1,19 @@ +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; + +export interface GetPdfInfoParameters extends BaseParameters { + // No parameters needed +} + +export const defaultParameters: GetPdfInfoParameters = {}; + +export type GetPdfInfoParametersHook = BaseParametersHook; + +export const useGetPdfInfoParameters = (): GetPdfInfoParametersHook => { + return useBaseParameters({ + defaultParameters, + endpointName: 'get-info-on-pdf', + }); +}; + + diff --git a/frontend/src/core/styles/theme.css b/frontend/src/core/styles/theme.css index 30991cf30..8551735ed 100644 --- a/frontend/src/core/styles/theme.css +++ b/frontend/src/core/styles/theme.css @@ -256,6 +256,7 @@ --header-selected-bg: #1E88E5; /* light mode selected header matches dark */ --header-selected-fg: #FFFFFF; --file-card-bg: #FFFFFF; /* file card background (light/dark paired) */ + --accordion-item-bg: #E8EAED; /* accordion item background - more distinguishable */ /* shadows */ --drop-shadow-color: rgba(0, 0, 0, 0.08); @@ -519,6 +520,7 @@ --header-selected-fg: #FFFFFF; /* file card background (dark) */ --file-card-bg: #1F2329; + --accordion-item-bg: #373D45; /* accordion item background - more distinguishable */ /* shadows */ --drop-shadow-color: rgba(255, 255, 255, 0.08); diff --git a/frontend/src/core/tools/GetPdfInfo.tsx b/frontend/src/core/tools/GetPdfInfo.tsx new file mode 100644 index 000000000..aa35fe16b --- /dev/null +++ b/frontend/src/core/tools/GetPdfInfo.tsx @@ -0,0 +1,188 @@ +import { useEffect, useMemo, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; +import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; +import LinkIcon from '@mui/icons-material/Link'; +import { Stack, Group, Divider, Text, UnstyledButton } from '@mantine/core'; +import { createToolFlow } from '@app/components/tools/shared/createToolFlow'; +import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool'; +import { BaseToolProps, ToolComponent } from '@app/types/tool'; +import { useGetPdfInfoParameters, defaultParameters } from '@app/hooks/tools/getPdfInfo/useGetPdfInfoParameters'; +import GetPdfInfoResults from '@app/components/tools/getPdfInfo/GetPdfInfoResults'; +import { useGetPdfInfoOperation, GetPdfInfoOperationHook } from '@app/hooks/tools/getPdfInfo/useGetPdfInfoOperation'; +import GetPdfInfoReportView from '@app/components/tools/getPdfInfo/GetPdfInfoReportView'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext'; +import type { PdfInfoReportData } from '@app/types/getPdfInfo'; + +const CHAPTERS = [ + { id: 'summary', labelKey: 'getPdfInfo.summary.title', fallback: 'PDF Summary' }, + { id: 'metadata', labelKey: 'getPdfInfo.sections.metadata', fallback: 'Metadata' }, + { id: 'formFields', labelKey: 'getPdfInfo.sections.formFields', fallback: 'Form Fields' }, + { id: 'basicInfo', labelKey: 'getPdfInfo.sections.basicInfo', fallback: 'Basic Info' }, + { id: 'documentInfo', labelKey: 'getPdfInfo.sections.documentInfo', fallback: 'Document Info' }, + { id: 'compliance', labelKey: 'getPdfInfo.sections.compliance', fallback: 'Compliance' }, + { id: 'encryption', labelKey: 'getPdfInfo.sections.encryption', fallback: 'Encryption' }, + { id: 'permissions', labelKey: 'getPdfInfo.sections.permissions', fallback: 'Permissions' }, + { id: 'toc', labelKey: 'getPdfInfo.sections.tableOfContents', fallback: 'Table of Contents' }, + { id: 'other', labelKey: 'getPdfInfo.sections.other', fallback: 'Other' }, + { id: 'perPage', labelKey: 'getPdfInfo.sections.perPageInfo', fallback: 'Per Page Info' }, +]; + +const GetPdfInfo = (props: BaseToolProps) => { + const { t } = useTranslation(); + const { actions: navigationActions } = useNavigationActions(); + const navigationState = useNavigationState(); + const { + registerCustomWorkbenchView, + unregisterCustomWorkbenchView, + setCustomWorkbenchViewData, + clearCustomWorkbenchViewData, + } = useToolWorkflow(); + + const REPORT_VIEW_ID = 'getPdfInfoReport'; + const REPORT_WORKBENCH_ID = 'custom:getPdfInfoReport' as const; + const reportIcon = useMemo(() => , []); + + const base = useBaseTool( + 'getPdfInfo', + useGetPdfInfoParameters, + useGetPdfInfoOperation, + props + ); + + const operation = base.operation as GetPdfInfoOperationHook; + const hasResults = operation.results.length > 0; + const showResultsStep = hasResults || base.operation.isLoading || !!base.operation.errorMessage; + + useEffect(() => { + registerCustomWorkbenchView({ + id: REPORT_VIEW_ID, + workbenchId: REPORT_WORKBENCH_ID, + label: t('getPdfInfo.report.shortTitle', 'PDF Information'), + icon: reportIcon, + component: GetPdfInfoReportView, + }); + + return () => { + clearCustomWorkbenchViewData(REPORT_VIEW_ID); + unregisterCustomWorkbenchView(REPORT_VIEW_ID); + }; + }, [ + clearCustomWorkbenchViewData, + registerCustomWorkbenchView, + reportIcon, + t, + unregisterCustomWorkbenchView, + ]); + + const reportData = useMemo(() => { + if (operation.results.length === 0) return null; + const generatedAt = operation.results[0].summaryGeneratedAt ?? Date.now(); + return { + generatedAt, + entries: operation.results, + }; + }, [operation.results]); + + const lastReportGeneratedAtRef = useRef(null); + useEffect(() => { + if (reportData) { + setCustomWorkbenchViewData(REPORT_VIEW_ID, reportData); + const generatedAt = reportData.generatedAt ?? null; + const isNewReport = generatedAt && generatedAt !== lastReportGeneratedAtRef.current; + if (isNewReport) { + lastReportGeneratedAtRef.current = generatedAt; + if (navigationState.selectedTool === 'getPdfInfo' && navigationState.workbench !== REPORT_WORKBENCH_ID) { + navigationActions.setWorkbench(REPORT_WORKBENCH_ID); + } + } + } else { + clearCustomWorkbenchViewData(REPORT_VIEW_ID); + lastReportGeneratedAtRef.current = null; + } + }, [ + clearCustomWorkbenchViewData, + navigationActions, + navigationState.selectedTool, + navigationState.workbench, + reportData, + setCustomWorkbenchViewData, + ]); + + return createToolFlow({ + files: { + selectedFiles: base.selectedFiles, + isCollapsed: hasResults, + }, + steps: [ + { + title: t('getPdfInfo.indexTitle', 'Index'), + isVisible: Boolean(reportData), + isCollapsed: false, + content: ( + + {CHAPTERS.map((c, idx) => ( + + { + if (!reportData) return; + setCustomWorkbenchViewData(REPORT_VIEW_ID, { ...reportData, scrollTo: c.id }); + if (navigationState.workbench !== REPORT_WORKBENCH_ID) { + navigationActions.setWorkbench(REPORT_WORKBENCH_ID); + } + }} + style={{ width: '100%', textAlign: 'left', padding: '8px 4px' }} + > + + + + {t(c.labelKey, c.fallback)} + + + + {idx < CHAPTERS.length - 1 && } + + ))} + + ), + }, + { + title: t('getPdfInfo.results', 'Results'), + isVisible: showResultsStep, + isCollapsed: false, + content: ( + + ), + }, + ], + executeButton: { + text: t('getPdfInfo.submit', 'Generate'), + loadingText: t('loading', 'Loading...'), + onClick: base.handleExecute, + disabled: + !base.params.validateParameters() || + !base.hasFiles || + base.operation.isLoading || + !base.endpointEnabled, + isVisible: true, + }, + review: { + isVisible: false, + operation: base.operation, + title: t('getPdfInfo.results', 'Results'), + onUndo: base.handleUndo, + }, + }); +}; + +const GetPdfInfoTool = GetPdfInfo as ToolComponent; +GetPdfInfoTool.tool = () => useGetPdfInfoOperation; +GetPdfInfoTool.getDefaultParameters = () => ({ ...defaultParameters }); + +export default GetPdfInfoTool; + + diff --git a/frontend/src/core/types/getPdfInfo.ts b/frontend/src/core/types/getPdfInfo.ts new file mode 100644 index 000000000..f489cd99a --- /dev/null +++ b/frontend/src/core/types/getPdfInfo.ts @@ -0,0 +1,273 @@ +/** Metadata section from PDF */ +export interface PdfMetadata { + Title?: string | null; + Author?: string | null; + Subject?: string | null; + Keywords?: string | null; + Creator?: string | null; + Producer?: string | null; + CreationDate?: string | null; + ModificationDate?: string | null; + [key: string]: unknown; +} + +/** Basic info section */ +export interface PdfBasicInfo { + FileSizeInBytes?: number; + WordCount?: number; + ParagraphCount?: number; + CharacterCount?: number; + Compression?: boolean; + CompressionType?: string; + Language?: string | null; + 'Number of pages'?: number; + TotalImages?: number; + [key: string]: unknown; +} + +/** Document info section */ +export interface PdfDocumentInfo { + 'PDF version'?: string; + Trapped?: string | null; + 'Page Mode'?: string; + [key: string]: unknown; +} + +/** Encryption section */ +export interface PdfEncryption { + IsEncrypted?: boolean; + EncryptionAlgorithm?: string; + KeyLength?: number; + [key: string]: unknown; +} + +/** Permissions section - values are "Allowed" or "Not Allowed" */ +export interface PdfPermissions { + 'Document Assembly'?: 'Allowed' | 'Not Allowed'; + 'Extracting Content'?: 'Allowed' | 'Not Allowed'; + 'Extracting for accessibility'?: 'Allowed' | 'Not Allowed'; + 'Form Filling'?: 'Allowed' | 'Not Allowed'; + 'Modifying'?: 'Allowed' | 'Not Allowed'; + 'Modifying annotations'?: 'Allowed' | 'Not Allowed'; + 'Printing'?: 'Allowed' | 'Not Allowed'; + [key: string]: 'Allowed' | 'Not Allowed' | undefined; +} + +/** Compliance section */ +export interface PdfCompliance { + 'IsPDF/ACompliant'?: boolean; + 'PDF/AConformanceLevel'?: string; + 'IsPDF/AValidated'?: boolean; + 'IsPDF/XCompliant'?: boolean; + 'IsPDF/ECompliant'?: boolean; + 'IsPDF/VTCompliant'?: boolean; + 'IsPDF/UACompliant'?: boolean; + 'IsPDF/BCompliant'?: boolean; + 'IsPDF/SECCompliant'?: boolean; + [key: string]: unknown; +} + +/** Font info within a page */ +export interface PdfFontInfo { + Name?: string; + IsEmbedded?: boolean; + Subtype?: string; + ItalicAngle?: number; + IsItalic?: boolean; + IsBold?: boolean; + IsFixedPitch?: boolean; + IsSerif?: boolean; + IsSymbolic?: boolean; + IsScript?: boolean; + IsNonsymbolic?: boolean; + FontFamily?: string; + FontWeight?: number; + Count?: number; +} + +/** Image info within a page */ +export interface PdfImageInfo { + Width?: number; + Height?: number; + Name?: string; + ColorSpace?: string; +} + +/** Link info within a page */ +export interface PdfLinkInfo { + URI?: string; +} + +/** Annotations info within a page */ +export interface PdfAnnotationsInfo { + AnnotationsCount?: number; + SubtypeCount?: number; + ContentsCount?: number; + [key: string]: unknown; +} + +/** Size/dimensions info within a page */ +export interface PdfSizeInfo { + 'Width (px)'?: string; + 'Height (px)'?: string; + 'Width (in)'?: string; + 'Height (in)'?: string; + 'Width (cm)'?: string; + 'Height (cm)'?: string; + 'Standard Page'?: string; + [key: string]: unknown; +} + +/** XObject counts within a page */ +export interface PdfXObjectCounts { + Image?: number; + Form?: number; + Other?: number; + [key: string]: unknown; +} + +/** ICC Profile info */ +export interface PdfICCProfile { + 'ICC Profile Length'?: number; +} + +/** Page-level information */ +export interface PdfPageInfo { + Size?: PdfSizeInfo; + Rotation?: number; + 'Page Orientation'?: string; + MediaBox?: string; + CropBox?: string; + BleedBox?: string; + TrimBox?: string; + ArtBox?: string; + 'Text Characters Count'?: number; + Annotations?: PdfAnnotationsInfo; + Images?: PdfImageInfo[]; + Links?: PdfLinkInfo[]; + Fonts?: PdfFontInfo[]; + 'Color Spaces & ICC Profiles'?: PdfICCProfile[]; + XObjectCounts?: PdfXObjectCounts; + Multimedia?: Record[]; +} + +/** Per-page info section (keyed by "Page 1", "Page 2", etc.) */ +export interface PdfPerPageInfo { + [pageLabel: string]: PdfPageInfo; +} + +/** Embedded file info */ +export interface PdfEmbeddedFileInfo { + Name?: string; + FileSize?: number; +} + +/** Attachment info */ +export interface PdfAttachmentInfo { + Name?: string; + Description?: string; +} + +/** JavaScript info */ +export interface PdfJavaScriptInfo { + 'JS Name'?: string; + 'JS Script Length'?: number; +} + +/** Layer info */ +export interface PdfLayerInfo { + Name?: string; +} + +/** Structure tree element */ +export interface PdfStructureTreeElement { + Type?: string; + Content?: string; + Children?: PdfStructureTreeElement[]; +} + +/** Other section with miscellaneous data */ +export interface PdfOtherInfo { + Attachments?: PdfAttachmentInfo[]; + EmbeddedFiles?: PdfEmbeddedFileInfo[]; + JavaScript?: PdfJavaScriptInfo[]; + Layers?: PdfLayerInfo[]; + StructureTree?: PdfStructureTreeElement[]; + 'Bookmarks/Outline/TOC'?: PdfTocEntry[]; + XMPMetadata?: string | null; +} + +/** Table of contents bookmark entry */ +export interface PdfTocEntry { + Title?: string; + [key: string]: unknown; +} + +/** Summary data section */ +export interface PdfSummaryData { + encrypted?: boolean; + restrictedPermissions?: string[]; + restrictedPermissionsCount?: number; + standardCompliance?: string; + standardPurpose?: string; + standardValidationPassed?: boolean; +} + +/** Form fields section */ +export type PdfFormFields = Record; + +/** Parsed sections with normalized keys for frontend use */ +export interface ParsedPdfSections { + metadata?: PdfMetadata | null; + formFields?: PdfFormFields | null; + basicInfo?: PdfBasicInfo | null; + documentInfo?: PdfDocumentInfo | null; + compliance?: PdfCompliance | null; + encryption?: PdfEncryption | null; + permissions?: PdfPermissions | null; + toc?: PdfTocEntry[] | null; + other?: PdfOtherInfo | null; + perPage?: PdfPerPageInfo | null; + summaryData?: PdfSummaryData | null; +} + +/** Raw backend response structure */ +export interface PdfInfoBackendData { + Metadata?: PdfMetadata; + FormFields?: PdfFormFields; + BasicInfo?: PdfBasicInfo; + DocumentInfo?: PdfDocumentInfo; + Compliancy?: PdfCompliance; + Encryption?: PdfEncryption; + Permissions?: PdfPermissions; + Other?: PdfOtherInfo; + PerPageInfo?: PdfPerPageInfo; + SummaryData?: PdfSummaryData; + // Legacy/alternative keys for backwards compatibility + 'Form Fields'?: PdfFormFields; + 'Basic Info'?: PdfBasicInfo; + 'Document Info'?: PdfDocumentInfo; + Compliance?: PdfCompliance; + 'Bookmarks/Outline/TOC'?: PdfTocEntry[]; + 'Table of Contents'?: PdfTocEntry[]; + 'Per Page Info'?: PdfPerPageInfo; +} + +export interface PdfInfoReportEntry { + fileId: string; + fileName: string; + fileSize: number | null; + lastModified: number | null; + thumbnailUrl?: string | null; + data: PdfInfoBackendData; + error: string | null; + summaryGeneratedAt?: number; +} + +export interface PdfInfoReportData { + generatedAt: number; + entries: PdfInfoReportEntry[]; +} + +export const INFO_JSON_FILENAME = 'response.json'; +export const INFO_PDF_FILENAME = 'pdf-information-report.pdf'; From c9bf436895ac9444268d5b7163f09db546b5457d Mon Sep 17 00:00:00 2001 From: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com> Date: Wed, 3 Dec 2025 20:37:23 +0000 Subject: [PATCH 12/56] couple of small fixes for text editor (#5155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description of Changes - Workbench.tsx: Allow PDF text editor to handle it's own custom state (this is a bit of a hotfix, we're going to handle the PDF text editors file upload flow better in a future PR). - PdfTextEditorView.tsx: Added a dropzone and some helper text to upload the first file. - PdfTextEditorView.tsx: Hide document view when isConverting is true. Prevents showing stale content from previous file during conversion. - useTranslatedToolRegistry.tsx: Moved PDF Text Editor to top of Recommended tools list. Increased visibility of the new feature. - PdfTextEditor.tsx: Removed auto-navigation to PDF Editor workbench on file selection. Stops the "jumpy" behavior when selecting files. - HomePage.tsx: Check specifically for pdfTextEditor tool instead of any custom workbench. Prevents auto-switch to viewer when uploading files while in PDF Text Editor. Screenshot 2025-12-03 at 6 01
14 PM --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --------- Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> --- build.gradle | 2 +- .../public/locales/en-GB/translation.toml | 3 + .../src/core/components/layout/Workbench.tsx | 23 +- .../components/shared/AllToolsNavButton.tsx | 18 +- .../shared/NavigationWarningModal.tsx | 6 +- .../core/components/shared/QuickAccessBar.tsx | 17 +- .../quickAccessBar/ActiveToolButton.tsx | 13 +- .../tools/pdfTextEditor/PdfTextEditorView.tsx | 77 ++++- .../src/core/contexts/NavigationContext.tsx | 94 ++++-- .../src/core/contexts/ToolWorkflowContext.tsx | 6 +- .../core/data/useTranslatedToolRegistry.tsx | 34 +- frontend/src/core/pages/HomePage.tsx | 10 +- .../tools/pdfTextEditor/PdfTextEditor.tsx | 295 ++++++++++++++++-- .../tools/pdfTextEditor/pdfTextEditorTypes.ts | 3 + 14 files changed, 492 insertions(+), 109 deletions(-) diff --git a/build.gradle b/build.gradle index 1738c1ef7..2ae135594 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ repositories { allprojects { group = 'stirling.software' - version = '2.0.3' + version = '2.1.0' configurations.configureEach { exclude group: 'commons-logging', module: 'commons-logging' diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index dd30ca449..2d2fa19c6 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -5991,6 +5991,7 @@ earlyAccess = "Early Access" reset = "Reset Changes" downloadJson = "Download JSON" generatePdf = "Generate PDF" +saveChanges = "Save Changes" [pdfTextEditor.options.autoScaleText] title = "Auto-scale text to fit boxes" @@ -6028,6 +6029,8 @@ alpha = "This alpha viewer is still evolving—certain fonts, colours, transpare [pdfTextEditor.empty] title = "No document loaded" subtitle = "Load a PDF or JSON file to begin editing text content." +dropzone = "Drag and drop a PDF or JSON file here, or click to browse" +dropzoneWithFiles = "Select a file from the Files tab, or drag and drop a PDF or JSON file here, or click to browse" [pdfTextEditor.welcomeBanner] title = "Welcome to PDF Text Editor (Early Access)" diff --git a/frontend/src/core/components/layout/Workbench.tsx b/frontend/src/core/components/layout/Workbench.tsx index f6477c67a..0fa31dd24 100644 --- a/frontend/src/core/components/layout/Workbench.tsx +++ b/frontend/src/core/components/layout/Workbench.tsx @@ -71,6 +71,20 @@ export default function Workbench() { }; const renderMainContent = () => { + // Check for custom workbench views first + if (!isBaseWorkbench(currentView)) { + const customView = customWorkbenchViews.find((view) => view.workbenchId === currentView && view.data != null); + if (customView) { + // PDF text editor handles its own empty state (shows dropzone when no document) + const handlesOwnEmptyState = currentView === 'custom:pdfTextEditor'; + if (handlesOwnEmptyState || activeFiles.length > 0) { + const CustomComponent = customView.component; + return ; + } + } + } + + // For base workbenches (or custom views that don't handle empty state), show landing page when no files if (activeFiles.length === 0) { return ( view.workbenchId === currentView && view.data != null); - - - if (customView) { - const CustomComponent = customView.component; - return ; - } - } return ; } }; diff --git a/frontend/src/core/components/shared/AllToolsNavButton.tsx b/frontend/src/core/components/shared/AllToolsNavButton.tsx index cc7a8777c..efa9a2a5d 100644 --- a/frontend/src/core/components/shared/AllToolsNavButton.tsx +++ b/frontend/src/core/components/shared/AllToolsNavButton.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import { Tooltip } from '@app/components/shared/Tooltip'; import AppsIcon from '@mui/icons-material/AppsRounded'; import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useNavigationState, useNavigationActions } from '@app/contexts/NavigationContext'; import { useSidebarNavigation } from '@app/hooks/useSidebarNavigation'; import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; @@ -20,21 +21,36 @@ const AllToolsNavButton: React.FC = ({ }) => { const { t } = useTranslation(); const { handleReaderToggle, handleBackToTools, selectedToolKey, leftPanelView } = useToolWorkflow(); + const { hasUnsavedChanges } = useNavigationState(); + const { actions: navigationActions } = useNavigationActions(); const { getHomeNavigation } = useSidebarNavigation(); - const handleClick = () => { + const performNavigation = () => { setActiveButton('tools'); // Preserve existing behavior used in QuickAccessBar header handleReaderToggle(); handleBackToTools(); }; + const handleClick = () => { + if (hasUnsavedChanges) { + navigationActions.requestNavigation(performNavigation); + return; + } + performNavigation(); + }; + // Do not highlight All Tools when a specific tool is open (indicator is shown) const isActive = activeButton === 'tools' && !selectedToolKey && leftPanelView === 'toolPicker'; const navProps = getHomeNavigation(); const handleNavClick = (e: React.MouseEvent) => { + if (hasUnsavedChanges) { + e.preventDefault(); + navigationActions.requestNavigation(performNavigation); + return; + } handleUnlessSpecialClick(e, handleClick); }; diff --git a/frontend/src/core/components/shared/NavigationWarningModal.tsx b/frontend/src/core/components/shared/NavigationWarningModal.tsx index faff07427..b8803f176 100644 --- a/frontend/src/core/components/shared/NavigationWarningModal.tsx +++ b/frontend/src/core/components/shared/NavigationWarningModal.tsx @@ -12,7 +12,7 @@ interface NavigationWarningModalProps { const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: NavigationWarningModalProps) => { const { t } = useTranslation(); - const { showNavigationWarning, hasUnsavedChanges, cancelNavigation, confirmNavigation, setHasUnsavedChanges } = + const { showNavigationWarning, hasUnsavedChanges, pendingNavigation, cancelNavigation, confirmNavigation, setHasUnsavedChanges } = useNavigationGuard(); const handleKeepWorking = () => { @@ -41,7 +41,9 @@ const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: Nav }; const BUTTON_WIDTH = "10rem"; - if (!hasUnsavedChanges) { + // Only show modal if there are unsaved changes AND there's an actual pending navigation + // This prevents the modal from showing due to spurious state updates + if (!hasUnsavedChanges || !pendingNavigation) { return null; } diff --git a/frontend/src/core/components/shared/QuickAccessBar.tsx b/frontend/src/core/components/shared/QuickAccessBar.tsx index 029a6d567..28efd60cb 100644 --- a/frontend/src/core/components/shared/QuickAccessBar.tsx +++ b/frontend/src/core/components/shared/QuickAccessBar.tsx @@ -7,6 +7,7 @@ import { useRainbowThemeContext } from "@app/components/shared/RainbowThemeProvi import { useIsOverflowing } from '@app/hooks/useIsOverflowing'; import { useFilesModalContext } from '@app/contexts/FilesModalContext'; import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useNavigationState, useNavigationActions } from '@app/contexts/NavigationContext'; import { useSidebarNavigation } from '@app/hooks/useSidebarNavigation'; import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; import { ButtonConfig } from '@app/types/sidebar'; @@ -32,6 +33,8 @@ const QuickAccessBar = forwardRef((_, ref) => { const { isRainbowMode } = useRainbowThemeContext(); const { openFilesModal, isFilesModalOpen } = useFilesModalContext(); const { handleReaderToggle, handleToolSelect, selectedToolKey, leftPanelView, toolRegistry, readerMode, resetTool } = useToolWorkflow(); + const { hasUnsavedChanges } = useNavigationState(); + const { actions: navigationActions } = useNavigationActions(); const { getToolNavigation } = useSidebarNavigation(); const { config } = useAppConfig(); const licenseAlert = useLicenseAlert(); @@ -58,7 +61,7 @@ const QuickAccessBar = forwardRef((_, ref) => { }; // Helper function to render navigation buttons with URL support - const renderNavButton = (config: ButtonConfig, index: number) => { + const renderNavButton = (config: ButtonConfig, index: number, shouldGuardNavigation = false) => { const isActive = isNavButtonActive(config, activeButton, isFilesModalOpen, configModalOpen, selectedToolKey, leftPanelView); // Check if this button has URL navigation support @@ -67,6 +70,14 @@ const QuickAccessBar = forwardRef((_, ref) => { : null; const handleClick = (e?: React.MouseEvent) => { + // If there are unsaved changes and this button should guard navigation, show warning modal + if (shouldGuardNavigation && hasUnsavedChanges) { + e?.preventDefault(); + navigationActions.requestNavigation(() => { + config.onClick(); + }); + return; + } if (navProps && e) { handleUnlessSpecialClick(e, config.onClick); } else { @@ -89,7 +100,7 @@ const QuickAccessBar = forwardRef((_, ref) => { onClick: (e: React.MouseEvent) => handleClick(e), 'aria-label': config.name } : { - onClick: () => handleClick(), + onClick: (e: React.MouseEvent) => handleClick(e), 'aria-label': config.name })} size={isActive ? 'lg' : 'md'} @@ -222,7 +233,7 @@ const QuickAccessBar = forwardRef((_, ref) => { {mainButtons.map((config, index) => ( - {renderNavButton(config, index)} + {renderNavButton(config, index, config.id === 'read' || config.id === 'automate')} ))} diff --git a/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx b/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx index 273c09d0e..55b79b26c 100644 --- a/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx +++ b/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx @@ -16,6 +16,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { ActionIcon } from '@mantine/core'; import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded'; import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useNavigationState, useNavigationActions } from '@app/contexts/NavigationContext'; import { useSidebarNavigation } from '@app/hooks/useSidebarNavigation'; import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; import FitText from '@app/components/shared/FitText'; @@ -31,6 +32,8 @@ const NAV_IDS = ['read', 'sign', 'automate']; const ActiveToolButton: React.FC = ({ setActiveButton, tooltipPosition = 'right' }) => { const { selectedTool, selectedToolKey, leftPanelView, handleBackToTools } = useToolWorkflow(); + const { hasUnsavedChanges } = useNavigationState(); + const { actions: navigationActions } = useNavigationActions(); const { getHomeNavigation } = useSidebarNavigation(); // Determine if the indicator should be visible (do not require selectedTool to be resolved yet) @@ -150,10 +153,16 @@ const ActiveToolButton: React.FC = ({ setActiveButton, to component="a" href={getHomeNavigation().href} onClick={(e: React.MouseEvent) => { - handleUnlessSpecialClick(e, () => { + const performNavigation = () => { setActiveButton('tools'); handleBackToTools(); - }); + }; + if (hasUnsavedChanges) { + e.preventDefault(); + navigationActions.requestNavigation(performNavigation); + return; + } + handleUnlessSpecialClick(e, performNavigation); }} size={'lg'} variant="subtle" diff --git a/frontend/src/core/components/tools/pdfTextEditor/PdfTextEditorView.tsx b/frontend/src/core/components/tools/pdfTextEditor/PdfTextEditorView.tsx index 0dbe8c50e..4eeff845b 100644 --- a/frontend/src/core/components/tools/pdfTextEditor/PdfTextEditorView.tsx +++ b/frontend/src/core/components/tools/pdfTextEditor/PdfTextEditorView.tsx @@ -21,6 +21,7 @@ import { Title, Tooltip, } from '@mantine/core'; +import { Dropzone } from '@mantine/dropzone'; import { useTranslation } from 'react-i18next'; import DescriptionIcon from '@mui/icons-material/DescriptionOutlined'; import FileDownloadIcon from '@mui/icons-material/FileDownloadOutlined'; @@ -32,9 +33,12 @@ import CloseIcon from '@mui/icons-material/Close'; import MergeTypeIcon from '@mui/icons-material/MergeType'; import CallSplitIcon from '@mui/icons-material/CallSplit'; import MoreVertIcon from '@mui/icons-material/MoreVert'; +import UploadFileIcon from '@mui/icons-material/UploadFileOutlined'; +import SaveIcon from '@mui/icons-material/SaveOutlined'; import { Rnd } from 'react-rnd'; import NavigationWarningModal from '@app/components/shared/NavigationWarningModal'; +import { useFileContext } from '@app/contexts/FileContext'; import { PdfTextEditorViewData, PdfJsonFont, @@ -313,6 +317,7 @@ type GroupingMode = 'auto' | 'paragraph' | 'singleLine'; const PdfTextEditorView = ({ data }: PdfTextEditorViewProps) => { const { t } = useTranslation(); + const { activeFiles } = useFileContext(); const [activeGroupId, setActiveGroupId] = useState(null); const [editingGroupId, setEditingGroupId] = useState(null); const [activeImageId, setActiveImageId] = useState(null); @@ -375,6 +380,7 @@ const PdfTextEditorView = ({ data }: PdfTextEditorViewProps) => { fileName, errorMessage, isGeneratingPdf, + isSavingToWorkbench, isConverting, conversionProgress, hasChanges, @@ -389,11 +395,12 @@ const PdfTextEditorView = ({ data }: PdfTextEditorViewProps) => { onReset, onDownloadJson, onGeneratePdf, - onGeneratePdfForNavigation, + onSaveToWorkbench, onForceSingleTextElementChange, onGroupingModeChange, onMergeGroups, onUngroupGroup, + onLoadFile, } = data; // Define derived variables immediately after props destructuring, before any hooks @@ -1430,7 +1437,8 @@ const selectionToolbarPosition = useMemo(() => { height: '100%', display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) 320px', - alignItems: 'start', + gridTemplateRows: '1fr', + alignItems: hasDocument ? 'start' : 'stretch', gap: '1.5rem', }} > @@ -1486,6 +1494,17 @@ const selectionToolbarPosition = useMemo(() => { > {t('pdfTextEditor.actions.generatePdf', 'Generate PDF')} + {fileName && ( @@ -1639,17 +1658,45 @@ const selectionToolbarPosition = useMemo(() => { )} {!hasDocument && !isConverting && ( - - - - - {t('pdfTextEditor.empty.title', 'No document loaded')} - - - {t('pdfTextEditor.empty.subtitle', 'Load a PDF or JSON file to begin editing text content.')} - - - + + { + if (files.length > 0) { + onLoadFile(files[0]); + } + }} + accept={['application/pdf', 'application/json']} + maxFiles={1} + style={{ + width: '100%', + maxWidth: 480, + minHeight: 200, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + border: '2px dashed var(--mantine-color-gray-4)', + borderRadius: 'var(--mantine-radius-lg)', + cursor: 'pointer', + transition: 'border-color 150ms ease, background-color 150ms ease', + }} + > + + + + {t('pdfTextEditor.empty.title', 'No document loaded')} + + + {activeFiles.length > 0 + ? t('pdfTextEditor.empty.dropzoneWithFiles', 'Select a file from the Files tab, or drag and drop a PDF or JSON file here, or click to browse') + : t('pdfTextEditor.empty.dropzone', 'Drag and drop a PDF or JSON file here, or click to browse')} + + + + )} {isConverting && ( @@ -1683,7 +1730,7 @@ const selectionToolbarPosition = useMemo(() => { )} - {hasDocument && ( + {hasDocument && !isConverting && ( { {/* Navigation Warning Modal */} ); diff --git a/frontend/src/core/contexts/NavigationContext.tsx b/frontend/src/core/contexts/NavigationContext.tsx index 500a6db5e..c11649400 100644 --- a/frontend/src/core/contexts/NavigationContext.tsx +++ b/frontend/src/core/contexts/NavigationContext.tsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useReducer, useCallback } from 'react'; +import React, { createContext, useContext, useReducer, useCallback, useMemo } from 'react'; import { WorkbenchType, getDefaultWorkbench } from '@app/types/workbench'; import { ToolId, isValidToolId } from '@app/types/toolId'; import { useToolRegistry } from '@app/contexts/ToolRegistryContext'; @@ -110,8 +110,8 @@ export const NavigationProvider: React.FC<{ const { allTools: toolRegistry } = useToolRegistry(); const unsavedChangesCheckerRef = React.useRef<(() => boolean) | null>(null); - const actions: NavigationContextActions = { - setWorkbench: useCallback((workbench: WorkbenchType) => { + // Memoize individual callbacks + const setWorkbench = useCallback((workbench: WorkbenchType) => { // Check for unsaved changes using registered checker or state const hasUnsavedChanges = unsavedChangesCheckerRef.current?.() || state.hasUnsavedChanges; console.log('[NavigationContext] setWorkbench:', { @@ -152,13 +152,13 @@ export const NavigationProvider: React.FC<{ } else { dispatch({ type: 'SET_WORKBENCH', payload: { workbench } }); } - }, [state.workbench, state.hasUnsavedChanges]), + }, [state.workbench, state.hasUnsavedChanges]); - setSelectedTool: useCallback((toolId: ToolId | null) => { + const setSelectedTool = useCallback((toolId: ToolId | null) => { dispatch({ type: 'SET_SELECTED_TOOL', payload: { toolId } }); - }, []), + }, []); - setToolAndWorkbench: useCallback((toolId: ToolId | null, workbench: WorkbenchType) => { + const setToolAndWorkbench = useCallback((toolId: ToolId | null, workbench: WorkbenchType) => { // Check for unsaved changes using registered checker or state const hasUnsavedChanges = unsavedChangesCheckerRef.current?.() || state.hasUnsavedChanges; @@ -177,25 +177,25 @@ export const NavigationProvider: React.FC<{ } else { dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId, workbench } }); } - }, [state.workbench, state.hasUnsavedChanges]), + }, [state.workbench, state.hasUnsavedChanges]); - setHasUnsavedChanges: useCallback((hasChanges: boolean) => { + const setHasUnsavedChanges = useCallback((hasChanges: boolean) => { dispatch({ type: 'SET_UNSAVED_CHANGES', payload: { hasChanges } }); - }, []), + }, []); - registerUnsavedChangesChecker: useCallback((checker: () => boolean) => { + const registerUnsavedChangesChecker = useCallback((checker: () => boolean) => { unsavedChangesCheckerRef.current = checker; - }, []), + }, []); - unregisterUnsavedChangesChecker: useCallback(() => { + const unregisterUnsavedChangesChecker = useCallback(() => { unsavedChangesCheckerRef.current = null; - }, []), + }, []); - showNavigationWarning: useCallback((show: boolean) => { + const showNavigationWarning = useCallback((show: boolean) => { dispatch({ type: 'SHOW_NAVIGATION_WARNING', payload: { show } }); - }, []), + }, []); - requestNavigation: useCallback((navigationFn: () => void) => { + const requestNavigation = useCallback((navigationFn: () => void) => { if (!state.hasUnsavedChanges) { navigationFn(); return; @@ -203,9 +203,9 @@ export const NavigationProvider: React.FC<{ dispatch({ type: 'SET_PENDING_NAVIGATION', payload: { navigationFn } }); dispatch({ type: 'SHOW_NAVIGATION_WARNING', payload: { show: true } }); - }, [state.hasUnsavedChanges]), + }, [state.hasUnsavedChanges]); - confirmNavigation: useCallback(() => { + const confirmNavigation = useCallback(() => { console.log('[NavigationContext] confirmNavigation called', { hasPendingNav: !!state.pendingNavigation, currentWorkbench: state.workbench, @@ -218,18 +218,18 @@ export const NavigationProvider: React.FC<{ dispatch({ type: 'SET_PENDING_NAVIGATION', payload: { navigationFn: null } }); dispatch({ type: 'SHOW_NAVIGATION_WARNING', payload: { show: false } }); console.log('[NavigationContext] confirmNavigation completed'); - }, [state.pendingNavigation, state.workbench, state.selectedTool]), + }, [state.pendingNavigation, state.workbench, state.selectedTool]); - cancelNavigation: useCallback(() => { + const cancelNavigation = useCallback(() => { dispatch({ type: 'SET_PENDING_NAVIGATION', payload: { navigationFn: null } }); dispatch({ type: 'SHOW_NAVIGATION_WARNING', payload: { show: false } }); - }, []), + }, []); - clearToolSelection: useCallback(() => { + const clearToolSelection = useCallback(() => { dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId: null, workbench: getDefaultWorkbench() } }); - }, []), + }, []); - handleToolSelect: useCallback((toolId: string) => { + const handleToolSelect = useCallback((toolId: string) => { if (toolId === 'allTools') { dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId: null, workbench: getDefaultWorkbench() } }); return; @@ -245,11 +245,40 @@ export const NavigationProvider: React.FC<{ const tool = isValidToolId(toolId)? toolRegistry[toolId] : null; const workbench = tool ? (tool.workbench || getDefaultWorkbench()) : getDefaultWorkbench(); - // Validate toolId and convert to ToolId type - const validToolId = isValidToolId(toolId) ? toolId : null; - dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId: validToolId, workbench } }); - }, [toolRegistry]) - }; + // Validate toolId and convert to ToolId type + const validToolId = isValidToolId(toolId) ? toolId : null; + dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId: validToolId, workbench } }); + }, [toolRegistry]); + + // Memoize the actions object to prevent unnecessary context updates + // This is critical to avoid infinite loops when effects depend on actions + const actions: NavigationContextActions = useMemo(() => ({ + setWorkbench, + setSelectedTool, + setToolAndWorkbench, + setHasUnsavedChanges, + registerUnsavedChangesChecker, + unregisterUnsavedChangesChecker, + showNavigationWarning, + requestNavigation, + confirmNavigation, + cancelNavigation, + clearToolSelection, + handleToolSelect, + }), [ + setWorkbench, + setSelectedTool, + setToolAndWorkbench, + setHasUnsavedChanges, + registerUnsavedChangesChecker, + unregisterUnsavedChangesChecker, + showNavigationWarning, + requestNavigation, + confirmNavigation, + cancelNavigation, + clearToolSelection, + handleToolSelect, + ]); const stateValue: NavigationContextStateValue = { workbench: state.workbench, @@ -259,9 +288,10 @@ export const NavigationProvider: React.FC<{ showNavigationWarning: state.showNavigationWarning }; - const actionsValue: NavigationContextActionsValue = { + // Also memoize the context value to prevent unnecessary re-renders + const actionsValue: NavigationContextActionsValue = useMemo(() => ({ actions - }; + }), [actions]); return ( diff --git a/frontend/src/core/contexts/ToolWorkflowContext.tsx b/frontend/src/core/contexts/ToolWorkflowContext.tsx index 9717b7f68..b2c695801 100644 --- a/frontend/src/core/contexts/ToolWorkflowContext.tsx +++ b/frontend/src/core/contexts/ToolWorkflowContext.tsx @@ -224,11 +224,15 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) { return; } + if (navigationState.pendingNavigation || navigationState.showNavigationWarning) { + return; + } + const currentCustomView = customWorkbenchViews.find(view => view.workbenchId === navigationState.workbench); if (!currentCustomView || currentCustomView.data == null) { actions.setWorkbench(getDefaultWorkbench()); } - }, [actions, customWorkbenchViews, navigationState.workbench]); + }, [actions, customWorkbenchViews, navigationState.workbench, navigationState.pendingNavigation, navigationState.showNavigationWarning]); // Persisted via PreferencesContext; no direct localStorage writes needed here diff --git a/frontend/src/core/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx index bc514d879..0844b94d1 100644 --- a/frontend/src/core/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -152,6 +152,23 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { // Proprietary tools (if any) ...proprietaryTools, // Recommended Tools in order + pdfTextEditor: { + icon: , + name: t("home.pdfTextEditor.title", "PDF Text Editor"), + component: PdfTextEditor, + description: t( + "home.pdfTextEditor.desc", + "Review and edit text and images in PDFs with grouped text editing and PDF regeneration" + ), + categoryId: ToolCategoryId.RECOMMENDED_TOOLS, + subcategoryId: SubcategoryId.GENERAL, + maxFiles: 1, + endpoints: ["text-editor-pdf"], + synonyms: getSynonyms(t, "pdfTextEditor"), + supportsAutomate: false, + automationSettings: null, + versionStatus: "alpha", + }, multiTool: { icon: , name: t("home.multiTool.title", "Multi-Tool"), @@ -893,23 +910,6 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { automationSettings: RedactSingleStepSettings, synonyms: getSynonyms(t, "redact") }, - pdfTextEditor: { - icon: , - name: t("home.pdfTextEditor.title", "PDF Text Editor"), - component: PdfTextEditor, - description: t( - "home.pdfTextEditor.desc", - "Review and edit text and images in PDFs with grouped text editing and PDF regeneration" - ), - categoryId: ToolCategoryId.RECOMMENDED_TOOLS, - subcategoryId: SubcategoryId.GENERAL, - maxFiles: 1, - endpoints: ["text-editor-pdf"], - synonyms: getSynonyms(t, "pdfTextEditor"), - supportsAutomate: false, - automationSettings: null, - versionStatus: "alpha", - }, }; const regularTools = {} as RegularToolRegistry; diff --git a/frontend/src/core/pages/HomePage.tsx b/frontend/src/core/pages/HomePage.tsx index b629e86a5..c22a9624d 100644 --- a/frontend/src/core/pages/HomePage.tsx +++ b/frontend/src/core/pages/HomePage.tsx @@ -59,17 +59,21 @@ export default function HomePage() { const prevFileCountRef = useRef(activeFiles.length); // Auto-switch to viewer when going from 0 to 1 file + // Skip this if PDF Text Editor is active - it handles its own empty state useEffect(() => { const prevCount = prevFileCountRef.current; const currentCount = activeFiles.length; if (prevCount === 0 && currentCount === 1) { - actions.setWorkbench('viewer'); - setActiveFileIndex(0); + // PDF Text Editor handles its own empty state with a dropzone + if (selectedToolKey !== 'pdfTextEditor') { + actions.setWorkbench('viewer'); + setActiveFileIndex(0); + } } prevFileCountRef.current = currentCount; - }, [activeFiles.length, actions, setActiveFileIndex]); + }, [activeFiles.length, actions, setActiveFileIndex, selectedToolKey]); const brandAltText = t("home.mobile.brandAlt", "Stirling PDF logo"); const brandIconSrc = useLogoPath(); diff --git a/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx b/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx index 571f3be09..533dc644b 100644 --- a/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx +++ b/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx @@ -3,9 +3,11 @@ import { useTranslation } from 'react-i18next'; import DescriptionIcon from '@mui/icons-material/DescriptionOutlined'; import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; -import { useFileSelection } from '@app/contexts/FileContext'; +import { useFileSelection, useFileManagement, useFileContext } from '@app/contexts/FileContext'; import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext'; +import { createStirlingFilesAndStubs } from '@app/services/fileStubHelpers'; import { BaseToolProps, ToolComponent } from '@app/types/tool'; +import { getDefaultWorkbench } from '@app/types/workbench'; import { CONVERSION_ENDPOINTS } from '@app/constants/convertConstants'; import apiClient from '@app/services/apiClient'; import { downloadBlob, downloadTextAsFile } from '@app/utils/downloadUtils'; @@ -208,7 +210,8 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { } = useToolWorkflow(); const { actions: navigationActions } = useNavigationActions(); const navigationState = useNavigationState(); - const { registerUnsavedChangesChecker, unregisterUnsavedChangesChecker } = navigationActions; + const { addFiles } = useFileManagement(); + const { consumeFiles, selectors } = useFileContext(); const [loadedDocument, setLoadedDocument] = useState(null); const [groupsByPage, setGroupsByPage] = useState([]); @@ -217,6 +220,8 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { const [fileName, setFileName] = useState(''); const [errorMessage, setErrorMessage] = useState(null); const [isGeneratingPdf, setIsGeneratingPdf] = useState(false); + const [isSavingToWorkbench, setIsSavingToWorkbench] = useState(false); + const [shouldNavigateAfterSave, setShouldNavigateAfterSave] = useState(false); const [isConverting, setIsConverting] = useState(false); const [conversionProgress, setConversionProgress] = useState(null); const [forceSingleTextElement, setForceSingleTextElement] = useState(true); @@ -234,6 +239,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { const originalGroupsRef = useRef([]); const imagesByPageRef = useRef([]); const autoLoadKeyRef = useRef(null); + const sourceFileIdRef = useRef(null); const loadRequestIdRef = useRef(0); const latestPdfRequestIdRef = useRef(null); const loadedDocumentRef = useRef(null); @@ -279,6 +285,23 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { ); const hasChanges = useMemo(() => dirtyPages.some(Boolean), [dirtyPages]); const hasDocument = loadedDocument !== null; + + // Sync hasChanges to navigation context so navigation guards can block + useEffect(() => { + navigationActions.setHasUnsavedChanges(hasChanges); + return () => { + navigationActions.setHasUnsavedChanges(false); + }; + }, [hasChanges, navigationActions]); + + // Navigate to files view AFTER the unsaved changes state is properly cleared + useEffect(() => { + if (shouldNavigateAfterSave && !navigationState.hasUnsavedChanges) { + setShouldNavigateAfterSave(false); + navigationActions.setToolAndWorkbench(null, getDefaultWorkbench()); + } + }, [shouldNavigateAfterSave, navigationState.hasUnsavedChanges, navigationActions]); + const viewLabel = useMemo(() => t('pdfTextEditor.viewLabel', 'PDF Editor'), [t]); const { selectedFiles } = useFileSelection(); @@ -720,6 +743,21 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { [groupingMode, resetToDocument, t], ); + // Wrapper for loading files from the dropzone - adds to workbench first + const handleLoadFileFromDropzone = useCallback( + async (file: File) => { + // Add the file to the workbench so it appears in the file list + const addedFiles = await addFiles([file]); + // Capture the file ID for save-to-workbench functionality + if (addedFiles.length > 0 && addedFiles[0].fileId) { + sourceFileIdRef.current = addedFiles[0].fileId; + } + // Then load it into the editor + void handleLoadFile(file); + }, + [addFiles, handleLoadFile], + ); + const handleSelectPage = useCallback((pageIndex: number) => { setSelectedPage(pageIndex); // Trigger lazy loading for images on the selected page @@ -1122,6 +1160,229 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { t, ]); + // Save changes to workbench (replaces the original file with edited version) + const handleSaveToWorkbench = useCallback(async () => { + setIsSavingToWorkbench(true); + + try { + if (!sourceFileIdRef.current) { + console.warn('[PdfTextEditor] No source file ID available for save to workbench'); + // Fall back to generating PDF download if no source file + await handleGeneratePdf(true); + return; + } + + const parentStub = selectors.getStirlingFileStub(sourceFileIdRef.current as any); + if (!parentStub) { + console.warn('[PdfTextEditor] Could not find parent stub for save to workbench'); + await handleGeneratePdf(true); + return; + } + + const ensureImagesForPages = async (pageIndices: number[]) => { + const uniqueIndices = Array.from(new Set(pageIndices)).filter((index) => index >= 0); + if (uniqueIndices.length === 0) { + return; + } + + for (const index of uniqueIndices) { + if (!loadedImagePagesRef.current.has(index)) { + await loadImagesForPage(index); + } + } + + const maxWaitTime = 15000; + const pollInterval = 150; + const startWait = Date.now(); + while (Date.now() - startWait < maxWaitTime) { + const allLoaded = uniqueIndices.every( + (index) => + loadedImagePagesRef.current.has(index) && + imagesByPageRef.current[index] !== undefined, + ); + const anyLoading = uniqueIndices.some((index) => + loadingImagePagesRef.current.has(index), + ); + if (allLoaded && !anyLoading) { + return; + } + await new Promise((resolve) => setTimeout(resolve, pollInterval)); + } + + const missing = uniqueIndices.filter( + (index) => !loadedImagePagesRef.current.has(index), + ); + if (missing.length > 0) { + throw new Error( + `Failed to load images for pages ${missing.map((i) => i + 1).join(', ')}`, + ); + } + }; + + const currentDoc = loadedDocumentRef.current; + const totalPages = currentDoc?.pages?.length ?? 0; + const currentDirtyPages = getDirtyPages(groupsByPage, imagesByPage, originalGroupsRef.current, originalImagesRef.current); + const dirtyPageIndices = currentDirtyPages + .map((isDirty, index) => (isDirty ? index : -1)) + .filter((index) => index >= 0); + + let pdfBlob: Blob; + let downloadName: string; + + const canUseIncremental = + isLazyMode && + cachedJobId && + dirtyPageIndices.length > 0 && + dirtyPageIndices.length < totalPages; + + if (canUseIncremental) { + await ensureImagesForPages(dirtyPageIndices); + + try { + const payload = buildPayload(); + if (!payload) { + throw new Error('Failed to build payload'); + } + + const { document, filename } = payload; + const dirtyPageSet = new Set(dirtyPageIndices); + const partialPages = + document.pages?.filter((_, index) => dirtyPageSet.has(index)) ?? []; + + const partialDocument: PdfJsonDocument = { + metadata: document.metadata, + xmpMetadata: document.xmpMetadata, + fonts: document.fonts, + lazyImages: true, + pages: partialPages, + }; + + const baseName = sanitizeBaseName(filename).replace(/-edited$/u, ''); + const expectedName = `${baseName || 'document'}.pdf`; + const response = await apiClient.post( + `/api/v1/convert/pdf/text-editor/partial/${cachedJobId}?filename=${encodeURIComponent(expectedName)}`, + partialDocument, + { + responseType: 'blob', + }, + ); + + const contentDisposition = response.headers?.['content-disposition'] ?? ''; + const detectedName = getFilenameFromHeaders(contentDisposition); + downloadName = detectedName || expectedName; + pdfBlob = response.data; + } catch (incrementalError) { + console.warn( + '[handleSaveToWorkbench] Incremental export failed, falling back to full export', + incrementalError, + ); + // Fall through to full export + if (isLazyMode && totalPages > 0) { + const allPageIndices = Array.from({ length: totalPages }, (_, index) => index); + await ensureImagesForPages(allPageIndices); + } + + const payload = buildPayload(); + if (!payload) { + throw new Error('Failed to build payload'); + } + + const { document, filename } = payload; + const serialized = JSON.stringify(document); + const jsonFile = new File([serialized], filename, { type: 'application/json' }); + + const formData = new FormData(); + formData.append('fileInput', jsonFile); + const response = await apiClient.post(CONVERSION_ENDPOINTS['text-editor-pdf'], formData, { + responseType: 'blob', + }); + + const contentDisposition = response.headers?.['content-disposition'] ?? ''; + const detectedName = getFilenameFromHeaders(contentDisposition); + const baseName = sanitizeBaseName(filename).replace(/-edited$/u, ''); + downloadName = detectedName || `${baseName || 'document'}.pdf`; + pdfBlob = response.data; + } + } else { + if (isLazyMode && totalPages > 0) { + const allPageIndices = Array.from({ length: totalPages }, (_, index) => index); + await ensureImagesForPages(allPageIndices); + } + + const payload = buildPayload(); + if (!payload) { + throw new Error('Failed to build payload'); + } + + const { document, filename } = payload; + const serialized = JSON.stringify(document); + const jsonFile = new File([serialized], filename, { type: 'application/json' }); + + const formData = new FormData(); + formData.append('fileInput', jsonFile); + const response = await apiClient.post(CONVERSION_ENDPOINTS['text-editor-pdf'], formData, { + responseType: 'blob', + }); + + const contentDisposition = response.headers?.['content-disposition'] ?? ''; + const detectedName = getFilenameFromHeaders(contentDisposition); + const baseName = sanitizeBaseName(filename).replace(/-edited$/u, ''); + downloadName = detectedName || `${baseName || 'document'}.pdf`; + pdfBlob = response.data; + } + + // Create the new PDF file + const pdfFile = new File([pdfBlob], downloadName, { type: 'application/pdf' }); + + // Create StirlingFile and stub for the output + const { stirlingFiles, stubs } = await createStirlingFilesAndStubs( + [pdfFile], + parentStub, + 'pdfTextEditor', + ); + + // Replace the original file with the edited version + await consumeFiles([sourceFileIdRef.current as any], stirlingFiles, stubs); + + // Update the source file ID to point to the new file + sourceFileIdRef.current = stubs[0].id; + + // Clear the unsaved changes flag - this will trigger the useEffect to navigate + // once React has processed the state update + navigationActions.setHasUnsavedChanges(false); + setErrorMessage(null); + + // Set flag to trigger navigation after state update is processed + setShouldNavigateAfterSave(true); + } catch (error: any) { + console.error('Failed to save to workbench', error); + const message = + error?.response?.data || + error?.message || + t('pdfTextEditor.errors.pdfConversion', 'Unable to save changes to workbench.'); + const msgString = typeof message === 'string' ? message : String(message); + setErrorMessage(msgString); + if (onError) { + onError(msgString); + } + } finally { + setIsSavingToWorkbench(false); + } + }, [ + buildPayload, + cachedJobId, + consumeFiles, + groupsByPage, + handleGeneratePdf, + imagesByPage, + isLazyMode, + loadImagesForPage, + navigationActions, + onError, + selectors, + t, + ]); + const requestPagePreview = useCallback( async (pageIndex: number, scale: number) => { if (!hasVectorPreview || !pdfDocumentRef.current) { @@ -1260,6 +1521,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { fileName, errorMessage, isGeneratingPdf, + isSavingToWorkbench, isConverting, conversionProgress, hasChanges, @@ -1278,15 +1540,19 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { // Generate PDF without triggering tool completion await handleGeneratePdf(true); }, + onSaveToWorkbench: handleSaveToWorkbench, onForceSingleTextElementChange: setForceSingleTextElement, onGroupingModeChange: setGroupingMode, onMergeGroups: handleMergeGroups, onUngroupGroup: handleUngroupGroup, + onLoadFile: handleLoadFileFromDropzone, }), [ handleMergeGroups, handleUngroupGroup, handleImageTransform, + handleSaveToWorkbench, imagesByPage, + isSavingToWorkbench, pagePreviews, dirtyPages, errorMessage, @@ -1311,6 +1577,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { groupingMode, requestPagePreview, setForceSingleTextElement, + handleLoadFileFromDropzone, ]); const latestViewDataRef = useRef(viewData); @@ -1326,6 +1593,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { useEffect(() => { if (selectedFiles.length === 0) { autoLoadKeyRef.current = null; + sourceFileIdRef.current = null; return; } @@ -1344,6 +1612,8 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { } autoLoadKeyRef.current = fileKey; + // Capture the source file ID for save-to-workbench functionality + sourceFileIdRef.current = (file as any).fileId ?? null; void handleLoadFile(file); }, [selectedFiles, navigationState.selectedTool, handleLoadFile]); @@ -1398,27 +1668,6 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { // The workbench should be set when the tool is selected via proper channels // (tool registry, tool picker, etc.) - not forced here - // Keep hasChanges in a ref for the checker to access - const hasChangesRef = useRef(hasChanges); - useEffect(() => { - hasChangesRef.current = hasChanges; - console.log('[PdfTextEditor] hasChanges updated to:', hasChanges); - }, [hasChanges]); - - // Register unsaved changes checker for navigation guard - useEffect(() => { - const checker = () => { - console.log('[PdfTextEditor] Checking unsaved changes:', hasChangesRef.current); - return hasChangesRef.current; - }; - registerUnsavedChangesChecker(checker); - console.log('[PdfTextEditor] Registered unsaved changes checker'); - return () => { - console.log('[PdfTextEditor] Unregistered unsaved changes checker'); - unregisterUnsavedChangesChecker(); - }; - }, [registerUnsavedChangesChecker, unregisterUnsavedChangesChecker]); - const lastSentViewDataRef = useRef(null); useEffect(() => { diff --git a/frontend/src/core/tools/pdfTextEditor/pdfTextEditorTypes.ts b/frontend/src/core/tools/pdfTextEditor/pdfTextEditorTypes.ts index 8439bb4c1..3dd45a465 100644 --- a/frontend/src/core/tools/pdfTextEditor/pdfTextEditorTypes.ts +++ b/frontend/src/core/tools/pdfTextEditor/pdfTextEditorTypes.ts @@ -221,8 +221,11 @@ export interface PdfTextEditorViewData { onDownloadJson: () => void; onGeneratePdf: () => void; onGeneratePdfForNavigation: () => Promise; + onSaveToWorkbench: () => Promise; + isSavingToWorkbench: boolean; onForceSingleTextElementChange: (value: boolean) => void; onGroupingModeChange: (value: 'auto' | 'paragraph' | 'singleLine') => void; onMergeGroups: (pageIndex: number, groupIds: string[]) => boolean; onUngroupGroup: (pageIndex: number, groupId: string) => boolean; + onLoadFile: (file: File) => void; } From 7459463a3ccc133368e5d263e5bfe992d7febdf2 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 3 Dec 2025 21:12:29 +0000 Subject: [PATCH 13/56] V2 sso in server plan (#5158) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- ...stomSaml2AuthenticationSuccessHandler.java | 10 ++--- .../service/UserLicenseSettingsService.java | 43 +++++++++++++++---- .../public/locales/en-GB/translation.toml | 4 +- .../configSections/providerDefinitions.ts | 6 ++- .../proprietary/constants/planConstants.ts | 11 +++-- 5 files changed, 53 insertions(+), 21 deletions(-) diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java index 0f350d7b4..b342fdcb4 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java @@ -67,19 +67,19 @@ public class CustomSaml2AuthenticationSuccessHandler boolean userExists = userService.usernameExistsIgnoreCase(username); - // Check if user is eligible for SAML (grandfathered or system has paid license) + // Check if user is eligible for SAML (grandfathered or system has ENTERPRISE license) if (userExists) { stirling.software.proprietary.security.model.User user = userService.findByUsernameIgnoreCase(username).orElse(null); - if (user != null && !licenseSettingsService.isOAuthEligible(user)) { - // User is not grandfathered and no paid license - block SAML login + if (user != null && !licenseSettingsService.isSamlEligible(user)) { + // User is not grandfathered and no ENTERPRISE license - block SAML login response.sendRedirect( request.getContextPath() + "/logout?saml2RequiresLicense=true"); return; } - } else if (!licenseSettingsService.isOAuthEligible(null)) { - // No existing user and no paid license -> block auto creation + } else if (!licenseSettingsService.isSamlEligible(null)) { + // No existing user and no ENTERPRISE license -> block auto creation response.sendRedirect( request.getContextPath() + "/logout?saml2RequiresLicense=true"); return; diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java index 1cddefde3..d3bade89c 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java @@ -331,17 +331,17 @@ public class UserLicenseSettingsService { } /** - * Checks if a user is eligible to use OAuth/SAML authentication. + * Checks if a user is eligible to use OAuth authentication. * *

A user is eligible if: * *

    *
  • They are grandfathered for OAuth (existing user before policy change), OR - *
  • The system has an ENTERPRISE license (SSO is enterprise-only) + *
  • The system has a paid license (SERVER or ENTERPRISE) *
* * @param user The user to check - * @return true if the user can use OAuth/SAML + * @return true if the user can use OAuth */ public boolean isOAuthEligible(stirling.software.proprietary.security.model.User user) { // Grandfathered users always have OAuth access @@ -350,10 +350,36 @@ public class UserLicenseSettingsService { return true; } - // Users can use OAuth/SAML only if system has ENTERPRISE license - boolean hasEnterpriseLicense = hasEnterpriseLicense(); - log.debug("OAuth eligibility check: hasEnterpriseLicense={}", hasEnterpriseLicense); - return hasEnterpriseLicense; + // Users can use OAuth with SERVER or ENTERPRISE license + boolean hasPaid = hasPaidLicense(); + log.debug("OAuth eligibility check: hasPaidLicense={}", hasPaid); + return hasPaid; + } + + /** + * Checks if a user is eligible to use SAML authentication. + * + *

A user is eligible if: + * + *

    + *
  • They are grandfathered for OAuth (existing user before policy change), OR + *
  • The system has an ENTERPRISE license (SAML is enterprise-only) + *
+ * + * @param user The user to check + * @return true if the user can use SAML + */ + public boolean isSamlEligible(stirling.software.proprietary.security.model.User user) { + // Grandfathered users always have SAML access + if (user != null && user.isOauthGrandfathered()) { + log.debug("User {} is grandfathered for SAML", user.getUsername()); + return true; + } + + // Users can use SAML only with ENTERPRISE license + boolean hasEnterprise = hasEnterpriseLicense(); + log.debug("SAML eligibility check: hasEnterpriseLicense={}", hasEnterprise); + return hasEnterprise; } /** @@ -500,8 +526,7 @@ public class UserLicenseSettingsService { } /** - * Checks if the system has an ENTERPRISE license. Used for enterprise-only features like SSO - * (OAuth/SAML). + * Checks if the system has an ENTERPRISE license. Used for enterprise-only features like SAML. * * @return true if ENTERPRISE license is active */ diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index 2d2fa19c6..b68a380d6 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -3539,8 +3539,8 @@ signinTitle = "Please sign in" ssoSignIn = "Login via Single Sign-on" oAuth2AutoCreateDisabled = "OAUTH2 Auto-Create User Disabled" oAuth2AdminBlockedUser = "Registration or logging in of non-registered users is currently blocked. Please contact the administrator." -oAuth2RequiresLicense = "OAuth/SSO login requires a paid license (Server or Enterprise). Please contact the administrator to upgrade your plan." -saml2RequiresLicense = "SAML login requires a paid license (Server or Enterprise). Please contact the administrator to upgrade your plan." +oAuth2RequiresLicense = "OAuth/SSO login requires a Server or Enterprise license. Please contact the administrator to upgrade your plan." +saml2RequiresLicense = "SAML login requires an Enterprise license. Please contact the administrator to upgrade your plan." maxUsersReached = "Maximum number of users reached for your current license. Please contact the administrator to upgrade your plan or add more seats." oauth2RequestNotFound = "Authorization request not found" oauth2InvalidUserInfoResponse = "Invalid User Info Response" diff --git a/frontend/src/core/components/shared/config/configSections/providerDefinitions.ts b/frontend/src/core/components/shared/config/configSections/providerDefinitions.ts index f51f997c7..f9d4af7c4 100644 --- a/frontend/src/core/components/shared/config/configSections/providerDefinitions.ts +++ b/frontend/src/core/components/shared/config/configSections/providerDefinitions.ts @@ -97,6 +97,7 @@ export const OAUTH2_PROVIDERS: Provider[] = [ icon: 'key-rounded', type: 'oauth2', scope: 'SSO', + businessTier: false, // Server tier - OAuth2/OIDC SSO fields: [ { key: 'issuer', @@ -141,6 +142,7 @@ export const GENERIC_OAUTH2_PROVIDER: Provider = { icon: 'link-rounded', type: 'oauth2', scope: 'SSO', + businessTier: false, // Server tier - OAuth2/OIDC SSO fields: [ { key: 'enabled', @@ -262,8 +264,8 @@ export const SAML2_PROVIDER: Provider = { name: 'SAML2', icon: 'verified-user-rounded', type: 'saml2', - scope: 'SSO', - businessTier: true, + scope: 'SSO (SAML)', + businessTier: true, // Enterprise tier - SAML only fields: [ { key: 'enabled', diff --git a/frontend/src/proprietary/constants/planConstants.ts b/frontend/src/proprietary/constants/planConstants.ts index ab14a2c55..f7073d25c 100644 --- a/frontend/src/proprietary/constants/planConstants.ts +++ b/frontend/src/proprietary/constants/planConstants.ts @@ -19,6 +19,7 @@ export const PLAN_FEATURES = { { name: 'Editing text in pdfs', included: false }, { name: 'Users limited to seats', included: false }, { name: 'SSO', included: false }, + { name: 'SAML', included: false }, { name: 'Auditing', included: false }, { name: 'Usage tracking', included: false }, { name: 'Prometheus Support', included: false }, @@ -37,7 +38,8 @@ export const PLAN_FEATURES = { { name: 'External Database', included: true }, { name: 'Editing text in pdfs', included: true }, { name: 'Users limited to seats', included: false }, - { name: 'SSO', included: false }, + { name: 'SSO', included: true }, + { name: 'SAML', included: false }, { name: 'Auditing', included: false }, { name: 'Usage tracking', included: false }, { name: 'Prometheus Support', included: false }, @@ -57,6 +59,7 @@ export const PLAN_FEATURES = { { name: 'Editing text in pdfs', included: true }, { name: 'Users limited to seats', included: true }, { name: 'SSO', included: true }, + { name: 'SAML', included: true }, { name: 'Auditing', included: true }, { name: 'Usage tracking', included: true }, { name: 'Prometheus Support', included: true }, @@ -74,6 +77,7 @@ export const PLAN_HIGHLIGHTS = { 'Self-hosted on your infrastructure', 'Unlimited users', 'Advanced integrations', + 'SSO (OAuth2/OIDC)', 'Editing text in PDFs', 'Cancel anytime' ], @@ -81,17 +85,18 @@ export const PLAN_HIGHLIGHTS = { 'Self-hosted on your infrastructure', 'Unlimited users', 'Advanced integrations', + 'SSO (OAuth2/OIDC)', 'Editing text in PDFs', 'Save with annual billing' ], ENTERPRISE_MONTHLY: [ - 'Enterprise features (SSO, Auditing)', + 'Enterprise features (SAML, Auditing)', 'Usage tracking & Prometheus', 'Custom PDF metadata', 'Per-seat licensing' ], ENTERPRISE_YEARLY: [ - 'Enterprise features (SSO, Auditing)', + 'Enterprise features (SAML, Auditing)', 'Usage tracking & Prometheus', 'Custom PDF metadata', 'Save with annual billing' From c6b4a2b141a399f410cd94c0e590ee25f4389d89 Mon Sep 17 00:00:00 2001 From: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com> Date: Thu, 4 Dec 2025 17:48:19 +0000 Subject: [PATCH 14/56] Desktop to match normal login screens (#5122)1 Also fixed issue with csrf Also fixed issue with rust keychain --------- Co-authored-by: James Brunton --- .../common/model/ApplicationProperties.java | 1 - .../common/service/PostHogService.java | 5 +- .../software/SPDF/config/InitialSetup.java | 16 +- .../controller/api/SettingsController.java | 7 - .../web/ReactRoutingController.java | 10 +- .../src/main/resources/settings.yml.template | 1 - .../configuration/SecurityConfiguration.java | 50 +--- .../public/locales/en-GB/translation.toml | 9 + frontend/src-tauri/Cargo.lock | 19 +- frontend/src-tauri/Cargo.toml | 2 +- frontend/src-tauri/src/commands/auth.rs | 67 ++--- .../SetupWizard/DesktopAuthLayout.tsx | 72 ++++++ .../SetupWizard/DesktopOAuthButtons.tsx | 110 +++++++++ .../components/SetupWizard/LoginForm.tsx | 225 ----------------- .../components/SetupWizard/ModeSelection.tsx | 72 ------ .../SetupWizard/SaaSLoginScreen.tsx | 95 ++++++++ .../components/SetupWizard/SelfHostedLink.tsx | 25 ++ .../SetupWizard/SelfHostedLoginScreen.tsx | 105 ++++++++ .../SetupWizard/ServerSelection.tsx | 91 ++++++- .../SetupWizard/ServerSelectionScreen.tsx | 34 +++ .../components/SetupWizard/SetupWizard.css | 23 -- .../desktop/components/SetupWizard/index.tsx | 230 ++++++++---------- frontend/src/desktop/services/apiClient.ts | 2 +- .../src/desktop/services/apiClientSetup.ts | 14 +- frontend/src/desktop/services/authService.ts | 74 ++++-- .../desktop/services/connectionModeService.ts | 1 + .../src/desktop/services/tauriHttpClient.ts | 7 +- .../configSections/AdminSecuritySection.tsx | 19 -- 28 files changed, 779 insertions(+), 607 deletions(-) create mode 100644 frontend/src/desktop/components/SetupWizard/DesktopAuthLayout.tsx create mode 100644 frontend/src/desktop/components/SetupWizard/DesktopOAuthButtons.tsx delete mode 100644 frontend/src/desktop/components/SetupWizard/LoginForm.tsx delete mode 100644 frontend/src/desktop/components/SetupWizard/ModeSelection.tsx create mode 100644 frontend/src/desktop/components/SetupWizard/SaaSLoginScreen.tsx create mode 100644 frontend/src/desktop/components/SetupWizard/SelfHostedLink.tsx create mode 100644 frontend/src/desktop/components/SetupWizard/SelfHostedLoginScreen.tsx create mode 100644 frontend/src/desktop/components/SetupWizard/ServerSelectionScreen.tsx delete mode 100644 frontend/src/desktop/components/SetupWizard/SetupWizard.css diff --git a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java index 6a6ee8453..f6afa62ea 100644 --- a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java +++ b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java @@ -112,7 +112,6 @@ public class ApplicationProperties { @Data public static class Security { private Boolean enableLogin; - private Boolean csrfDisabled; private InitialLogin initialLogin = new InitialLogin(); private OAUTH2 oauth2 = new OAUTH2(); private SAML2 saml2 = new SAML2(); diff --git a/app/common/src/main/java/stirling/software/common/service/PostHogService.java b/app/common/src/main/java/stirling/software/common/service/PostHogService.java index 310fc43ab..786c04a43 100644 --- a/app/common/src/main/java/stirling/software/common/service/PostHogService.java +++ b/app/common/src/main/java/stirling/software/common/service/PostHogService.java @@ -254,10 +254,7 @@ public class PostHogService { properties, "security_enableLogin", applicationProperties.getSecurity().getEnableLogin()); - addIfNotEmpty( - properties, - "security_csrfDisabled", - applicationProperties.getSecurity().getCsrfDisabled()); + addIfNotEmpty(properties, "security_csrfDisabled", true); addIfNotEmpty( properties, "security_loginAttemptCount", diff --git a/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java b/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java index 0a63a6f48..ef592cb55 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java @@ -34,7 +34,6 @@ public class InitialSetup { public void init() throws IOException { initUUIDKey(); initSecretKey(); - initEnableCSRFSecurity(); initLegalUrls(); initSetAppVersion(); GeneralUtils.extractPipeline(); @@ -59,19 +58,6 @@ public class InitialSetup { applicationProperties.getAutomaticallyGenerated().setKey(secretKey); } } - - public void initEnableCSRFSecurity() throws IOException { - if (GeneralUtils.isVersionHigher( - "0.46.0", applicationProperties.getAutomaticallyGenerated().getAppVersion())) { - Boolean csrf = applicationProperties.getSecurity().getCsrfDisabled(); - if (!csrf) { - GeneralUtils.saveKeyToSettings("security.csrfDisabled", false); - GeneralUtils.saveKeyToSettings("system.enableAnalytics", true); - applicationProperties.getSecurity().setCsrfDisabled(false); - } - } - } - public void initLegalUrls() throws IOException { // Initialize Terms and Conditions String termsUrl = applicationProperties.getLegal().getTermsAndConditions(); @@ -95,7 +81,7 @@ public class InitialSetup { isNewServer = existingVersion == null || existingVersion.isEmpty() - || existingVersion.equals("0.0.0"); + || "0.0.0".equals(existingVersion); String appVersion = "0.0.0"; Resource resource = new ClassPathResource("version.properties"); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java index 9657d8f15..1d9f63818 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java @@ -124,7 +124,6 @@ public class SettingsController { ApplicationProperties.Security security = applicationProperties.getSecurity(); settings.put("enableLogin", security.getEnableLogin()); - settings.put("csrfDisabled", security.getCsrfDisabled()); settings.put("loginMethod", security.getLoginMethod()); settings.put("loginAttemptCount", security.getLoginAttemptCount()); settings.put("loginResetTimeMinutes", security.getLoginResetTimeMinutes()); @@ -159,12 +158,6 @@ public class SettingsController { .getSecurity() .setEnableLogin((Boolean) settings.get("enableLogin")); } - if (settings.containsKey("csrfDisabled")) { - GeneralUtils.saveKeyToSettings("security.csrfDisabled", settings.get("csrfDisabled")); - applicationProperties - .getSecurity() - .setCsrfDisabled((Boolean) settings.get("csrfDisabled")); - } if (settings.containsKey("loginMethod")) { GeneralUtils.saveKeyToSettings("security.loginMethod", settings.get("loginMethod")); applicationProperties diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java index 7741220f2..6373e0752 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java @@ -4,8 +4,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import jakarta.annotation.PostConstruct; - import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.http.MediaType; @@ -13,6 +11,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; @Controller @@ -63,9 +62,10 @@ public class ReactRoutingController { } } - @GetMapping(value = {"/", "/index.html"}, produces = MediaType.TEXT_HTML_VALUE) - public ResponseEntity serveIndexHtml(HttpServletRequest request) - throws IOException { + @GetMapping( + value = {"/", "/index.html"}, + produces = MediaType.TEXT_HTML_VALUE) + public ResponseEntity serveIndexHtml(HttpServletRequest request) throws IOException { if (indexHtmlExists && cachedIndexHtml != null) { return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(cachedIndexHtml); } diff --git a/app/core/src/main/resources/settings.yml.template b/app/core/src/main/resources/settings.yml.template index 5ea28f71e..4c2ec003e 100644 --- a/app/core/src/main/resources/settings.yml.template +++ b/app/core/src/main/resources/settings.yml.template @@ -12,7 +12,6 @@ security: enableLogin: true # set to 'true' to enable login - csrfDisabled: false # set to 'true' to disable CSRF protection (not recommended for production) loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1 loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts loginMethod: all # Accepts values like 'all' and 'normal'(only Login with Username/Password), 'oauth2'(only Login with OAuth2) or 'saml2'(only Login with SAML2) diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java index ab1e4934d..2a0cd5734 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -1,7 +1,6 @@ package stirling.software.proprietary.security.configuration; import java.util.List; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -25,8 +24,6 @@ import org.springframework.security.saml2.provider.service.web.authentication.Op import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; -import org.springframework.security.web.csrf.CookieCsrfTokenRepository; -import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.NullRequestCache; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.web.cors.CorsConfiguration; @@ -47,7 +44,6 @@ import stirling.software.proprietary.security.database.repository.PersistentLogi import stirling.software.proprietary.security.filter.IPRateLimitingFilter; import stirling.software.proprietary.security.filter.JwtAuthenticationFilter; import stirling.software.proprietary.security.filter.UserAuthenticationFilter; -import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationFailureHandler; import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationSuccessHandler; import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationFailureHandler; @@ -198,9 +194,7 @@ public class SecurityConfiguration { http.cors(cors -> cors.disable()); } - if (securityProperties.getCsrfDisabled() || !loginEnabledValue) { - http.csrf(CsrfConfigurer::disable); - } + http.csrf(CsrfConfigurer::disable); if (loginEnabledValue) { boolean v2Enabled = appConfig.v2Enabled(); @@ -210,48 +204,6 @@ public class SecurityConfiguration { .addFilterBefore(rateLimitingFilter, UsernamePasswordAuthenticationFilter.class) .addFilterBefore(jwtAuthenticationFilter, UserAuthenticationFilter.class); - if (!securityProperties.getCsrfDisabled()) { - CookieCsrfTokenRepository cookieRepo = - CookieCsrfTokenRepository.withHttpOnlyFalse(); - CsrfTokenRequestAttributeHandler requestHandler = - new CsrfTokenRequestAttributeHandler(); - requestHandler.setCsrfRequestAttributeName(null); - http.csrf( - csrf -> - csrf.ignoringRequestMatchers( - request -> { - String uri = request.getRequestURI(); - - // Ignore CSRF for auth endpoints - if (uri.startsWith("/api/v1/auth/")) { - return true; - } - - String apiKey = request.getHeader("X-API-KEY"); - // If there's no API key, don't ignore CSRF - // (return false) - if (apiKey == null || apiKey.trim().isEmpty()) { - return false; - } - // Validate API key using existing UserService - try { - Optional user = - userService.getUserByApiKey(apiKey); - // If API key is valid, ignore CSRF (return - // true) - // If API key is invalid, don't ignore CSRF - // (return false) - return user.isPresent(); - } catch (Exception e) { - // If there's any error validating the API - // key, don't ignore CSRF - return false; - } - }) - .csrfTokenRepository(cookieRepo) - .csrfTokenRequestHandler(requestHandler)); - } - http.sessionManagement( sessionManagement -> { if (v2Enabled) { diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index b68a380d6..c60df3a85 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -5901,6 +5901,7 @@ subtitle = "Sign in with your Stirling account" [setup.selfhosted] title = "Sign in to Server" subtitle = "Enter your server credentials" +link = "or connect to a self-hosted account" [setup.server] title = "Connect to Server" @@ -5919,6 +5920,14 @@ description = "Enter the full URL of your self-hosted Stirling PDF server" emptyUrl = "Please enter a server URL" unreachable = "Could not connect to server" testFailed = "Connection test failed" +configFetch = "Failed to fetch server configuration. Please check the URL and try again." + +[setup.server.error.securityDisabled] +title = "Login Not Enabled" +body = "This server does not have login enabled. To connect to this server, you must enable authentication:" +step1 = "Set DOCKER_ENABLE_SECURITY=true in your environment" +step2 = "Or set security.enableLogin=true in settings.yml" +step3 = "Restart the server" [setup.login] title = "Sign In" diff --git a/frontend/src-tauri/Cargo.lock b/frontend/src-tauri/Cargo.lock index 9d2395e2d..9719752dc 100644 --- a/frontend/src-tauri/Cargo.lock +++ b/frontend/src-tauri/Cargo.lock @@ -2152,7 +2152,11 @@ version = "3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" dependencies = [ + "byteorder", "log", + "security-framework 2.11.1", + "security-framework 3.5.1", + "windows-sys 0.60.2", "zeroize", ] @@ -2378,7 +2382,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -3841,6 +3845,19 @@ dependencies = [ "security-framework-sys", ] +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework-sys" version = "2.15.0" diff --git a/frontend/src-tauri/Cargo.toml b/frontend/src-tauri/Cargo.toml index 6884bd178..dc84ad8a2 100644 --- a/frontend/src-tauri/Cargo.toml +++ b/frontend/src-tauri/Cargo.toml @@ -32,7 +32,7 @@ tauri-plugin-http = "2.4.4" tauri-plugin-single-instance = "2.0.1" tauri-plugin-store = "2.1.0" tauri-plugin-opener = "2.0.0" -keyring = "3.6.1" +keyring = { version = "3.6.1", features = ["apple-native", "windows-native"] } tokio = { version = "1.0", features = ["time", "sync"] } reqwest = { version = "0.11", features = ["json"] } tiny_http = "0.12" diff --git a/frontend/src-tauri/src/commands/auth.rs b/frontend/src-tauri/src/commands/auth.rs index 30ec0d6c4..3e75b452e 100644 --- a/frontend/src-tauri/src/commands/auth.rs +++ b/frontend/src-tauri/src/commands/auth.rs @@ -1,4 +1,4 @@ -use keyring::Entry; +use keyring::{Entry}; use serde::{Deserialize, Serialize}; use std::sync::{Arc, Mutex}; use tauri::AppHandle; @@ -21,53 +21,70 @@ pub struct UserInfo { } fn get_keyring_entry() -> Result { - Entry::new(KEYRING_SERVICE, KEYRING_TOKEN_KEY) - .map_err(|e| format!("Failed to access keyring: {}", e)) + log::debug!("Creating keyring entry with service='{}' username='{}'", KEYRING_SERVICE, KEYRING_TOKEN_KEY); + let entry = Entry::new(KEYRING_SERVICE, KEYRING_TOKEN_KEY) + .map_err(|e| { + log::error!("Failed to create keyring entry: {}", e); + format!("Failed to access keyring: {}", e) + })?; + log::debug!("Keyring entry created successfully"); + Ok(entry) } #[tauri::command] pub async fn save_auth_token(_app_handle: AppHandle, token: String) -> Result<(), String> { - log::info!("Saving auth token to keyring"); + if token.is_empty() { + log::warn!("Attempted to save empty auth token"); + return Err("Token cannot be empty".to_string()); + } let entry = get_keyring_entry()?; entry .set_password(&token) - .map_err(|e| format!("Failed to save token to keyring: {}", e))?; + .map_err(|e| { + log::error!("Failed to set password in keyring: {}", e); + format!("Failed to save token to keyring: {}", e) + })?; + + // Verify the save worked + match entry.get_password() { + Ok(retrieved_token) => { + if retrieved_token != token { + log::error!("Token verification failed: Retrieved token doesn't match"); + return Err("Token verification failed after save".to_string()); + } + } + Err(e) => { + log::error!("Token verification failed: {}", e); + return Err(format!("Token verification failed: {}", e)); + } + } - log::info!("Auth token saved successfully"); Ok(()) } #[tauri::command] pub async fn get_auth_token(_app_handle: AppHandle) -> Result, String> { - log::debug!("Retrieving auth token from keyring"); - let entry = get_keyring_entry()?; match entry.get_password() { Ok(token) => Ok(Some(token)), Err(keyring::Error::NoEntry) => Ok(None), - Err(e) => Err(format!("Failed to retrieve token: {}", e)), + Err(e) => { + log::error!("Failed to retrieve token from keyring: {}", e); + Err(format!("Failed to retrieve token: {}", e)) + }, } } #[tauri::command] pub async fn clear_auth_token(_app_handle: AppHandle) -> Result<(), String> { - log::info!("Clearing auth token from keyring"); - let entry = get_keyring_entry()?; // Delete the token - ignore error if it doesn't exist match entry.delete_credential() { - Ok(_) => { - log::info!("Auth token cleared successfully"); - Ok(()) - } - Err(keyring::Error::NoEntry) => { - log::info!("Auth token was already cleared"); - Ok(()) - } + Ok(_) | Err(keyring::Error::NoEntry) => Ok(()), Err(e) => Err(format!("Failed to clear token: {}", e)), } } @@ -78,8 +95,6 @@ pub async fn save_user_info( username: String, email: Option, ) -> Result<(), String> { - log::info!("Saving user info for: {}", username); - let user_info = UserInfo { username, email }; let store = app_handle @@ -96,7 +111,6 @@ pub async fn save_user_info( .save() .map_err(|e| format!("Failed to save store: {}", e))?; - log::info!("User info saved successfully"); Ok(()) } @@ -117,8 +131,6 @@ pub async fn get_user_info(app_handle: AppHandle) -> Result, St #[tauri::command] pub async fn clear_user_info(app_handle: AppHandle) -> Result<(), String> { - log::info!("Clearing user info"); - let store = app_handle .store(STORE_FILE) .map_err(|e| format!("Failed to access store: {}", e))?; @@ -129,7 +141,6 @@ pub async fn clear_user_info(app_handle: AppHandle) -> Result<(), String> { .save() .map_err(|e| format!("Failed to save store: {}", e))?; - log::info!("User info cleared successfully"); Ok(()) } @@ -186,12 +197,8 @@ pub async fn login( supabase_key: String, saas_server_url: String, ) -> Result { - log::info!("Login attempt for user: {} to server: {}", username, server_url); - // Detect if this is Supabase (SaaS) or Spring Boot (self-hosted) - // Compare against the configured SaaS server URL let is_supabase = server_url.trim_end_matches('/') == saas_server_url.trim_end_matches('/'); - log::info!("Authentication type: {}", if is_supabase { "Supabase (SaaS)" } else { "Spring Boot (Self-hosted)" }); // Create HTTP client let client = reqwest::Client::new(); @@ -248,8 +255,6 @@ pub async fn login( .or_else(|| email.clone()) .unwrap_or_else(|| username); - log::info!("Supabase login successful for user: {}", username); - Ok(LoginResponse { token: login_response.access_token, username, diff --git a/frontend/src/desktop/components/SetupWizard/DesktopAuthLayout.tsx b/frontend/src/desktop/components/SetupWizard/DesktopAuthLayout.tsx new file mode 100644 index 000000000..92558857b --- /dev/null +++ b/frontend/src/desktop/components/SetupWizard/DesktopAuthLayout.tsx @@ -0,0 +1,72 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import LoginRightCarousel from '@app/components/shared/LoginRightCarousel'; +import buildLoginSlides from '@app/components/shared/loginSlides'; +import styles from '@app/routes/authShared/AuthLayout.module.css'; +import { useLogoVariant } from '@app/hooks/useLogoVariant'; + +interface DesktopAuthLayoutProps { + children: React.ReactNode; +} + +export const DesktopAuthLayout: React.FC = ({ children }) => { + const { t } = useTranslation(); + const cardRef = useRef(null); + const [hideRightPanel, setHideRightPanel] = useState(false); + const logoVariant = useLogoVariant(); + const imageSlides = useMemo(() => buildLoginSlides(logoVariant, t), [logoVariant, t]); + + // Force light mode on auth pages + useEffect(() => { + const htmlElement = document.documentElement; + const previousColorScheme = htmlElement.getAttribute('data-mantine-color-scheme'); + + // Set light mode + htmlElement.setAttribute('data-mantine-color-scheme', 'light'); + + // Cleanup: restore previous theme when leaving auth pages + return () => { + if (previousColorScheme) { + htmlElement.setAttribute('data-mantine-color-scheme', previousColorScheme); + } + }; + }, []); + + useEffect(() => { + const update = () => { + // Use viewport to avoid hysteresis when the card is already in single-column mode + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + const cardWidthIfTwoCols = Math.min(1180, viewportWidth * 0.96); // matches min(73.75rem, 96vw) + const columnWidth = cardWidthIfTwoCols / 2; + const tooNarrow = columnWidth < 470; + const tooShort = viewportHeight < 740; + setHideRightPanel(tooNarrow || tooShort); + }; + update(); + window.addEventListener('resize', update); + window.addEventListener('orientationchange', update); + return () => { + window.removeEventListener('resize', update); + window.removeEventListener('orientationchange', update); + }; + }, []); + + return ( +
+
+
+
+ {children} +
+
+ {!hideRightPanel && ( + + )} +
+
+ ); +}; diff --git a/frontend/src/desktop/components/SetupWizard/DesktopOAuthButtons.tsx b/frontend/src/desktop/components/SetupWizard/DesktopOAuthButtons.tsx new file mode 100644 index 000000000..49b55a386 --- /dev/null +++ b/frontend/src/desktop/components/SetupWizard/DesktopOAuthButtons.tsx @@ -0,0 +1,110 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { authService, UserInfo } from '@app/services/authService'; +import { buildOAuthCallbackHtml } from '@app/utils/oauthCallbackHtml'; +import { BASE_PATH } from '@app/constants/app'; +import '@app/routes/authShared/auth.css'; + +export type OAuthProvider = 'google' | 'github' | 'keycloak' | 'azure' | 'apple' | 'oidc'; + +interface DesktopOAuthButtonsProps { + onOAuthSuccess: (userInfo: UserInfo) => Promise; + onError: (error: string) => void; + isDisabled: boolean; + serverUrl: string; + providers: OAuthProvider[]; +} + +export const DesktopOAuthButtons: React.FC = ({ + onOAuthSuccess, + onError, + isDisabled, + serverUrl, + providers, +}) => { + const { t } = useTranslation(); + const [oauthLoading, setOauthLoading] = useState(false); + + const handleOAuthLogin = async (provider: OAuthProvider) => { + // Prevent concurrent OAuth attempts + if (oauthLoading || isDisabled) { + return; + } + + try { + setOauthLoading(true); + + // Build callback page HTML with translations and dark mode support + const successHtml = buildOAuthCallbackHtml({ + title: t('oauth.success.title', 'Authentication Successful'), + message: t('oauth.success.message', 'You can close this window and return to Stirling PDF.'), + isError: false, + }); + + const errorHtml = buildOAuthCallbackHtml({ + title: t('oauth.error.title', 'Authentication Failed'), + message: t('oauth.error.message', 'Authentication was not successful. You can close this window and try again.'), + isError: true, + errorPlaceholder: true, // {error} will be replaced by Rust + }); + + const userInfo = await authService.loginWithOAuth(provider, serverUrl, successHtml, errorHtml); + + // Call the onOAuthSuccess callback to complete setup + await onOAuthSuccess(userInfo); + } catch (error) { + console.error('OAuth login failed:', error); + + const errorMessage = error instanceof Error + ? error.message + : t('setup.login.error.oauthFailed', 'OAuth login failed. Please try again.'); + + onError(errorMessage); + setOauthLoading(false); + } + }; + + const providerConfig: Record = { + google: { label: 'Google', file: 'google.svg' }, + github: { label: 'GitHub', file: 'github.svg' }, + keycloak: { label: 'Keycloak', file: 'keycloak.svg' }, + azure: { label: 'Microsoft', file: 'microsoft.svg' }, + apple: { label: 'Apple', file: 'apple.svg' }, + oidc: { label: 'OpenID', file: 'oidc.svg' }, + }; + + if (providers.length === 0) { + return null; + } + + return ( +
+ {providers + .filter((providerId) => providerId in providerConfig) + .map((providerId) => { + const provider = providerConfig[providerId]; + return ( + + ); + })} + {oauthLoading && ( +

+ {t('setup.login.oauthPending', 'Opening browser for authentication...')} +

+ )} +
+ ); +}; diff --git a/frontend/src/desktop/components/SetupWizard/LoginForm.tsx b/frontend/src/desktop/components/SetupWizard/LoginForm.tsx deleted file mode 100644 index 4ad388822..000000000 --- a/frontend/src/desktop/components/SetupWizard/LoginForm.tsx +++ /dev/null @@ -1,225 +0,0 @@ -import React, { useState } from 'react'; -import { Stack, TextInput, PasswordInput, Button, Text, Divider, Group, Collapse, Anchor, Box } from '@mantine/core'; -import { useTranslation } from 'react-i18next'; -import { authService } from '@app/services/authService'; -import { STIRLING_SAAS_URL } from '@app/constants/connection'; -import { buildOAuthCallbackHtml } from '@app/utils/oauthCallbackHtml'; -import { BASE_PATH } from '@app/constants/app'; - -interface LoginFormProps { - serverUrl: string; - isSaaS?: boolean; - onLogin: (username: string, password: string) => Promise; - loading: boolean; -} - -export const LoginForm: React.FC = ({ serverUrl, isSaaS = false, onLogin, loading }) => { - const { t } = useTranslation(); - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [validationError, setValidationError] = useState(null); - const [oauthLoading, setOauthLoading] = useState(false); - const [showInstructions, setShowInstructions] = useState(false); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - - // Validation - if (!username.trim()) { - setValidationError(isSaaS - ? t('setup.login.error.emptyEmail', 'Please enter your email') - : t('setup.login.error.emptyUsername', 'Please enter your username')); - return; - } - - if (!password) { - setValidationError(t('setup.login.error.emptyPassword', 'Please enter your password')); - return; - } - - setValidationError(null); - await onLogin(username.trim(), password); - }; - - const handleOAuthLogin = async (provider: 'google' | 'github') => { - // Prevent concurrent OAuth attempts - if (oauthLoading || loading) { - return; - } - - try { - setOauthLoading(true); - setValidationError(null); - - // For SaaS, use configured SaaS URL; for self-hosted, derive from serverUrl - const authServerUrl = isSaaS - ? STIRLING_SAAS_URL - : serverUrl; // Self-hosted might have its own auth - - // Build callback page HTML with translations and dark mode support - const successHtml = buildOAuthCallbackHtml({ - title: t('oauth.success.title', 'Authentication Successful'), - message: t('oauth.success.message', 'You can close this window and return to Stirling PDF.'), - isError: false, - }); - - const errorHtml = buildOAuthCallbackHtml({ - title: t('oauth.error.title', 'Authentication Failed'), - message: t('oauth.error.message', 'Authentication was not successful. You can close this window and try again.'), - isError: true, - errorPlaceholder: true, // {error} will be replaced by Rust - }); - - const userInfo = await authService.loginWithOAuth(provider, authServerUrl, successHtml, errorHtml); - - // Call the onLogin callback to complete setup (username/password not needed for OAuth) - await onLogin(userInfo.username, ''); - } catch (error) { - console.error('OAuth login failed:', error); - - const errorMessage = error instanceof Error - ? error.message - : t('setup.login.error.oauthFailed', 'OAuth login failed. Please try again.'); - - setValidationError(errorMessage); - setOauthLoading(false); - } - }; - - return ( -
- - - {t('setup.login.connectingTo', 'Connecting to:')} {isSaaS ? 'stirling.com' : serverUrl} - - - {/* Login requirement note for self-hosted servers */} - {!isSaaS && ( - - - {t('setup.login.serverRequirement', 'Note: The server must have login enabled.')}{' '} - setShowInstructions(!showInstructions)} - style={{ cursor: 'pointer' }} - > - {showInstructions - ? t('setup.login.hideInstructions', 'Hide instructions') - : t('setup.login.showInstructions', 'How to enable?')} - - - - - - - {t('setup.login.instructions', 'To enable login on your Stirling PDF server:')} - - - {t('setup.login.instructionsEnvVar', 'Set the environment variable:')} - - - SECURITY_ENABLELOGIN=true - - - {t('setup.login.instructionsOrYml', 'Or in settings.yml:')} - - - security.enableLogin: true - - - {t('setup.login.instructionsRestart', 'Then restart your server for the changes to take effect.')} - - - - - )} - - {/* OAuth Login Buttons - Only show for SaaS */} - {isSaaS && ( - <> - - - - - - - - {oauthLoading && ( - - {t('setup.login.oauthPending', 'Opening browser for authentication...')} - - )} - - - - - )} - - { - setUsername(e.target.value); - setValidationError(null); - }} - disabled={loading} - required - /> - - { - setPassword(e.target.value); - setValidationError(null); - }} - disabled={loading} - required - /> - - {validationError && ( - - {validationError} - - )} - - - -
- ); -}; diff --git a/frontend/src/desktop/components/SetupWizard/ModeSelection.tsx b/frontend/src/desktop/components/SetupWizard/ModeSelection.tsx deleted file mode 100644 index 8242fa5ed..000000000 --- a/frontend/src/desktop/components/SetupWizard/ModeSelection.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import { Stack, Button, Text } from '@mantine/core'; -import { useTranslation } from 'react-i18next'; -import CloudIcon from '@mui/icons-material/Cloud'; -import ComputerIcon from '@mui/icons-material/Computer'; - -interface ModeSelectionProps { - onSelect: (mode: 'saas' | 'selfhosted') => void; - loading: boolean; -} - -export const ModeSelection: React.FC = ({ onSelect, loading }) => { - const { t } = useTranslation(); - - return ( - - - - - - ); -}; diff --git a/frontend/src/desktop/components/SetupWizard/SaaSLoginScreen.tsx b/frontend/src/desktop/components/SetupWizard/SaaSLoginScreen.tsx new file mode 100644 index 000000000..ab82bde1e --- /dev/null +++ b/frontend/src/desktop/components/SetupWizard/SaaSLoginScreen.tsx @@ -0,0 +1,95 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import LoginHeader from '@app/routes/login/LoginHeader'; +import ErrorMessage from '@app/routes/login/ErrorMessage'; +import EmailPasswordForm from '@app/routes/login/EmailPasswordForm'; +import DividerWithText from '@app/components/shared/DividerWithText'; +import { DesktopOAuthButtons } from '@app/components/SetupWizard/DesktopOAuthButtons'; +import { SelfHostedLink } from '@app/components/SetupWizard/SelfHostedLink'; +import { UserInfo } from '@app/services/authService'; +import '@app/routes/authShared/auth.css'; + +interface SaaSLoginScreenProps { + serverUrl: string; + onLogin: (username: string, password: string) => Promise; + onOAuthSuccess: (userInfo: UserInfo) => Promise; + onSelfHostedClick: () => void; + loading: boolean; + error: string | null; +} + +export const SaaSLoginScreen: React.FC = ({ + serverUrl, + onLogin, + onOAuthSuccess, + onSelfHostedClick, + loading, + error, +}) => { + const { t } = useTranslation(); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [validationError, setValidationError] = useState(null); + + const handleEmailPasswordSubmit = async () => { + // Validation + if (!email.trim()) { + setValidationError(t('setup.login.error.emptyEmail', 'Please enter your email')); + return; + } + + if (!password) { + setValidationError(t('setup.login.error.emptyPassword', 'Please enter your password')); + return; + } + + setValidationError(null); + await onLogin(email.trim(), password); + }; + + const handleOAuthError = (errorMessage: string) => { + setValidationError(errorMessage); + }; + + const displayError = error || validationError; + + return ( + <> + + + + + + + + + { + setEmail(value); + setValidationError(null); + }} + setPassword={(value) => { + setPassword(value); + setValidationError(null); + }} + onSubmit={handleEmailPasswordSubmit} + isSubmitting={loading} + submitButtonText={t('setup.login.submit', 'Login')} + /> + + + + ); +}; diff --git a/frontend/src/desktop/components/SetupWizard/SelfHostedLink.tsx b/frontend/src/desktop/components/SetupWizard/SelfHostedLink.tsx new file mode 100644 index 000000000..6a184cc58 --- /dev/null +++ b/frontend/src/desktop/components/SetupWizard/SelfHostedLink.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import '@app/routes/authShared/auth.css'; + +interface SelfHostedLinkProps { + onClick: () => void; + disabled?: boolean; +} + +export const SelfHostedLink: React.FC = ({ onClick, disabled = false }) => { + const { t } = useTranslation(); + + return ( +
+ +
+ ); +}; diff --git a/frontend/src/desktop/components/SetupWizard/SelfHostedLoginScreen.tsx b/frontend/src/desktop/components/SetupWizard/SelfHostedLoginScreen.tsx new file mode 100644 index 000000000..9a68b9156 --- /dev/null +++ b/frontend/src/desktop/components/SetupWizard/SelfHostedLoginScreen.tsx @@ -0,0 +1,105 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Text } from '@mantine/core'; +import LoginHeader from '@app/routes/login/LoginHeader'; +import ErrorMessage from '@app/routes/login/ErrorMessage'; +import EmailPasswordForm from '@app/routes/login/EmailPasswordForm'; +import DividerWithText from '@app/components/shared/DividerWithText'; +import { DesktopOAuthButtons, OAuthProvider } from '@app/components/SetupWizard/DesktopOAuthButtons'; +import { UserInfo } from '@app/services/authService'; +import '@app/routes/authShared/auth.css'; + +interface SelfHostedLoginScreenProps { + serverUrl: string; + enabledOAuthProviders?: string[]; + onLogin: (username: string, password: string) => Promise; + onOAuthSuccess: (userInfo: UserInfo) => Promise; + loading: boolean; + error: string | null; +} + +export const SelfHostedLoginScreen: React.FC = ({ + serverUrl, + enabledOAuthProviders, + onLogin, + onOAuthSuccess, + loading, + error, +}) => { + const { t } = useTranslation(); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [validationError, setValidationError] = useState(null); + + const handleSubmit = async () => { + // Validation + if (!username.trim()) { + setValidationError(t('setup.login.error.emptyUsername', 'Please enter your username')); + return; + } + + if (!password) { + setValidationError(t('setup.login.error.emptyPassword', 'Please enter your password')); + return; + } + + setValidationError(null); + await onLogin(username.trim(), password); + }; + + const handleOAuthError = (errorMessage: string) => { + setValidationError(errorMessage); + }; + + const displayError = error || validationError; + + return ( + <> + + + + + + {t('setup.login.connectingTo', 'Connecting to:')} {serverUrl} + + + {/* Show OAuth buttons if providers are available */} + {enabledOAuthProviders && enabledOAuthProviders.length > 0 && ( + <> + + + + + )} + + { + setUsername(value); + setValidationError(null); + }} + setPassword={(value) => { + setPassword(value); + setValidationError(null); + }} + onSubmit={handleSubmit} + isSubmitting={loading} + submitButtonText={t('setup.login.submit', 'Login')} + /> + + ); +}; diff --git a/frontend/src/desktop/components/SetupWizard/ServerSelection.tsx b/frontend/src/desktop/components/SetupWizard/ServerSelection.tsx index 3ca5ea65b..f8a0d4f9e 100644 --- a/frontend/src/desktop/components/SetupWizard/ServerSelection.tsx +++ b/frontend/src/desktop/components/SetupWizard/ServerSelection.tsx @@ -1,8 +1,9 @@ import React, { useState } from 'react'; -import { Stack, Button, TextInput } from '@mantine/core'; +import { Stack, Button, TextInput, Alert, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import { ServerConfig } from '@app/services/connectionModeService'; import { connectionModeService } from '@app/services/connectionModeService'; +import LocalIcon from '@app/components/shared/LocalIcon'; interface ServerSelectionProps { onSelect: (config: ServerConfig) => void; @@ -14,11 +15,13 @@ export const ServerSelection: React.FC = ({ onSelect, load const [customUrl, setCustomUrl] = useState(''); const [testing, setTesting] = useState(false); const [testError, setTestError] = useState(null); + const [securityDisabled, setSecurityDisabled] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - const url = customUrl.trim(); + // Normalize URL: trim and remove trailing slashes + const url = customUrl.trim().replace(/\/+$/, ''); if (!url) { setTestError(t('setup.server.error.emptyUrl', 'Please enter a server URL')); @@ -28,6 +31,7 @@ export const ServerSelection: React.FC = ({ onSelect, load // Test connection before proceeding setTesting(true); setTestError(null); + setSecurityDisabled(false); try { const isReachable = await connectionModeService.testConnection(url); @@ -38,9 +42,67 @@ export const ServerSelection: React.FC = ({ onSelect, load return; } - // Connection successful + // Fetch OAuth providers and check if login is enabled + let enabledProviders: string[] = []; + try { + const response = await fetch(`${url}/api/v1/proprietary/ui-data/login`); + + // Check if security is disabled (status 403 or error response) + if (!response.ok) { + if (response.status === 403 || response.status === 401) { + setSecurityDisabled(true); + setTesting(false); + return; + } + // Other error statuses - show generic error + setTestError( + t('setup.server.error.configFetch', 'Failed to fetch server configuration (status {{status}})', { + status: response.status + }) + ); + setTesting(false); + return; + } + + const data = await response.json(); + console.log('Login UI data:', data); + + // Check if the response indicates security is disabled + if (data.enableLogin === false || data.securityEnabled === false) { + setSecurityDisabled(true); + setTesting(false); + return; + } + + // Extract provider IDs from authorization URLs + // Example: "/oauth2/authorization/google" → "google" + enabledProviders = Object.keys(data.providerList || {}) + .map(key => key.split('/').pop()) + .filter((id): id is string => id !== undefined); + + console.log('[ServerSelection] Detected OAuth providers:', enabledProviders); + } catch (err) { + console.error('[ServerSelection] Failed to fetch login configuration', err); + + // Check if it's a security disabled error + if (err instanceof Error && (err.message.includes('403') || err.message.includes('401'))) { + setSecurityDisabled(true); + setTesting(false); + return; + } + + // For any other error (network, CORS, invalid JSON, etc.), show error and don't proceed + setTestError( + t('setup.server.error.configFetch', 'Failed to fetch server configuration. Please check the URL and try again.') + ); + setTesting(false); + return; + } + + // Connection successful - pass URL and OAuth providers onSelect({ url, + enabledOAuthProviders: enabledProviders.length > 0 ? enabledProviders : undefined, }); } catch (error) { console.error('Connection test failed:', error); @@ -64,6 +126,7 @@ export const ServerSelection: React.FC = ({ onSelect, load onChange={(e) => { setCustomUrl(e.target.value); setTestError(null); + setSecurityDisabled(false); }} disabled={loading || testing} error={testError} @@ -73,6 +136,28 @@ export const ServerSelection: React.FC = ({ onSelect, load )} /> + {securityDisabled && ( + } + title={t('setup.server.error.securityDisabled.title', 'Login Not Enabled')} + > + + + {t('setup.server.error.securityDisabled.body', 'This server does not have login enabled. To connect to this server, you must enable authentication:')} + + +
    +
  1. {t('setup.server.error.securityDisabled.step1', 'Set DOCKER_ENABLE_SECURITY=true in your environment')}
  2. +
  3. {t('setup.server.error.securityDisabled.step2', 'Or set security.enableLogin=true in settings.yml')}
  4. +
  5. {t('setup.server.error.securityDisabled.step3', 'Restart the server')}
  6. +
+
+
+
+ )} + - )} - - - -
+ {/* Back Button */} + {activeStep > SetupStep.SaaSLogin && !loading && ( +
+ +
+ )} + ); }; diff --git a/frontend/src/desktop/services/apiClient.ts b/frontend/src/desktop/services/apiClient.ts index 8773afc5e..257099c80 100644 --- a/frontend/src/desktop/services/apiClient.ts +++ b/frontend/src/desktop/services/apiClient.ts @@ -14,7 +14,7 @@ import { getApiBaseUrl } from '@app/services/apiClientConfig'; const apiClient = create({ baseURL: getApiBaseUrl(), responseType: 'json', - withCredentials: true, + withCredentials: false, // Desktop doesn't need credentials }); // Setup interceptors (desktop-specific auth and backend ready checks) diff --git a/frontend/src/desktop/services/apiClientSetup.ts b/frontend/src/desktop/services/apiClientSetup.ts index d01c0d997..ee9cbcf55 100644 --- a/frontend/src/desktop/services/apiClientSetup.ts +++ b/frontend/src/desktop/services/apiClientSetup.ts @@ -48,13 +48,21 @@ export function setupApiInterceptors(client: AxiosInstance): void { // Debug logging console.debug(`[apiClientSetup] Request to: ${extendedConfig.url}`); - // Add auth token for remote requests + // Add auth token for remote requests and enable credentials const isRemote = await operationRouter.isSelfHostedMode(); if (isRemote) { + // Self-hosted mode: enable credentials for session management + extendedConfig.withCredentials = true; + const token = await authService.getAuthToken(); if (token) { extendedConfig.headers.Authorization = `Bearer ${token}`; + } else { + console.warn('[apiClientSetup] Self-hosted mode but no auth token available'); } + } else { + // SaaS mode: disable credentials (security disabled on local backend) + extendedConfig.withCredentials = false; } // Backend readiness check (for local backend) @@ -85,7 +93,9 @@ export function setupApiInterceptors(client: AxiosInstance): void { // Response interceptor: Handle auth errors client.interceptors.response.use( - (response) => response, + (response) => { + return response; + }, async (error) => { const originalRequest = error.config as ExtendedRequestConfig; diff --git a/frontend/src/desktop/services/authService.ts b/frontend/src/desktop/services/authService.ts index 76f8aa157..ed8be911f 100644 --- a/frontend/src/desktop/services/authService.ts +++ b/frontend/src/desktop/services/authService.ts @@ -25,6 +25,7 @@ export class AuthService { private static instance: AuthService; private authStatus: AuthStatus = 'unauthenticated'; private userInfo: UserInfo | null = null; + private cachedToken: string | null = null; private authListeners = new Set<(status: AuthStatus, userInfo: UserInfo | null) => void>(); static getInstance(): AuthService { @@ -38,13 +39,32 @@ export class AuthService { * Save token to all storage locations and notify listeners */ private async saveTokenEverywhere(token: string): Promise { - // Save to Tauri store - await invoke('save_auth_token', { token }); - console.log('[Desktop AuthService] Token saved to Tauri store'); + // Validate token before caching + if (!token || token.trim().length === 0) { + console.warn('[Desktop AuthService] Attempted to save invalid/empty token'); + throw new Error('Invalid token'); + } - // Sync to localStorage for web layer - localStorage.setItem('stirling_jwt', token); - console.log('[Desktop AuthService] Token saved to localStorage'); + try { + // Save to Tauri store + await invoke('save_auth_token', { token }); + console.log('[Desktop AuthService] ✅ Token saved to Tauri store'); + } catch (error) { + console.error('[Desktop AuthService] ❌ Failed to save token to Tauri store:', error); + // Don't throw - we can still use localStorage + } + + try { + // Sync to localStorage for web layer + localStorage.setItem('stirling_jwt', token); + console.log('[Desktop AuthService] ✅ Token saved to localStorage'); + } catch (error) { + console.error('[Desktop AuthService] ❌ Failed to save token to localStorage:', error); + } + + // Cache the valid token in memory + this.cachedToken = token; + console.log('[Desktop AuthService] ✅ Token cached in memory'); // Notify other parts of the system window.dispatchEvent(new CustomEvent('jwt-available')); @@ -56,20 +76,25 @@ export class AuthService { */ private async getTokenFromAnySource(): Promise { // Try Tauri store first - console.log('[Desktop AuthService] Retrieving token from Tauri store...'); - const token = await invoke('get_auth_token'); + try { + const token = await invoke('get_auth_token'); - if (token) { - console.log(`[Desktop AuthService] Token found in Tauri store (length: ${token.length})`); - return token; + if (token) { + console.log(`[Desktop AuthService] ✅ Token found in Tauri store (length: ${token.length})`); + return token; + } + + console.log('[Desktop AuthService] ℹ️ No token in Tauri store, checking localStorage...'); + } catch (error) { + console.error('[Desktop AuthService] ❌ Failed to read from Tauri store:', error); } - console.log('[Desktop AuthService] No token in Tauri store'); - // Fallback to localStorage const localStorageToken = localStorage.getItem('stirling_jwt'); if (localStorageToken) { - console.log('[Desktop AuthService] Token found in localStorage (length:', localStorageToken.length, ')'); + console.log(`[Desktop AuthService] ✅ Token found in localStorage (length: ${localStorageToken.length})`); + } else { + console.log('[Desktop AuthService] ❌ No token found in any storage'); } return localStorageToken; @@ -79,6 +104,10 @@ export class AuthService { * Clear token from all storage locations */ private async clearTokenEverywhere(): Promise { + // Invalidate cache + this.cachedToken = null; + console.log('[Desktop AuthService] Cache invalidated'); + await invoke('clear_auth_token'); localStorage.removeItem('stirling_jwt'); } @@ -183,7 +212,22 @@ export class AuthService { async getAuthToken(): Promise { try { - return await this.getTokenFromAnySource(); + // Return cached token if available + if (this.cachedToken) { + console.debug('[Desktop AuthService] ✅ Returning cached token'); + return this.cachedToken; + } + + console.debug('[Desktop AuthService] Cache miss, fetching from storage...'); + const token = await this.getTokenFromAnySource(); + + // Cache the token if valid + if (token && token.trim().length > 0) { + this.cachedToken = token; + console.log('[Desktop AuthService] ✅ Token cached in memory after retrieval'); + } + + return token; } catch (error) { console.error('[Desktop AuthService] Failed to get auth token:', error); return null; diff --git a/frontend/src/desktop/services/connectionModeService.ts b/frontend/src/desktop/services/connectionModeService.ts index f01dbc40a..cf454a50b 100644 --- a/frontend/src/desktop/services/connectionModeService.ts +++ b/frontend/src/desktop/services/connectionModeService.ts @@ -5,6 +5,7 @@ export type ConnectionMode = 'saas' | 'selfhosted'; export interface ServerConfig { url: string; + enabledOAuthProviders?: string[]; } export interface ConnectionConfig { diff --git a/frontend/src/desktop/services/tauriHttpClient.ts b/frontend/src/desktop/services/tauriHttpClient.ts index 89c87bfbb..b5bbceb93 100644 --- a/frontend/src/desktop/services/tauriHttpClient.ts +++ b/frontend/src/desktop/services/tauriHttpClient.ts @@ -61,7 +61,7 @@ class TauriHttpClient { headers: {}, timeout: 120000, responseType: 'json', - withCredentials: true, + withCredentials: false, // Desktop doesn't need credentials (backend has allowCredentials=false) }; public interceptors: Interceptors = { @@ -173,14 +173,15 @@ class TauriHttpClient { } try { - // Debug logging - console.debug(`[tauriHttpClient] Fetch request:`, { url, method }); + // Convert withCredentials to fetch API's credentials option + const credentials: RequestCredentials = finalConfig.withCredentials ? 'include' : 'omit'; // Make the request using Tauri's native HTTP client (standard Fetch API) const response = await fetch(url, { method, headers, body, + credentials, }); // Parse response based on responseType diff --git a/frontend/src/proprietary/components/shared/config/configSections/AdminSecuritySection.tsx b/frontend/src/proprietary/components/shared/config/configSections/AdminSecuritySection.tsx index 8934f4c45..19721b760 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/AdminSecuritySection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/AdminSecuritySection.tsx @@ -13,7 +13,6 @@ import LoginRequiredBanner from '@app/components/shared/config/LoginRequiredBann interface SecuritySettingsData { enableLogin?: boolean; - csrfDisabled?: boolean; loginMethod?: string; loginAttemptCount?: number; loginResetTimeMinutes?: number; @@ -123,7 +122,6 @@ export default function AdminSecuritySection() { const deltaSettings: Record = { // Security settings 'security.enableLogin': securitySettings.enableLogin, - 'security.csrfDisabled': securitySettings.csrfDisabled, 'security.loginMethod': securitySettings.loginMethod, 'security.loginAttemptCount': securitySettings.loginAttemptCount, 'security.loginResetTimeMinutes': securitySettings.loginResetTimeMinutes, @@ -282,23 +280,6 @@ export default function AdminSecuritySection() { disabled={!loginEnabled} /> - -
-
- {t('admin.settings.security.csrfDisabled.label', 'Disable CSRF Protection')} - - {t('admin.settings.security.csrfDisabled.description', 'Disable Cross-Site Request Forgery protection (not recommended)')} - -
- - setSettings({ ...settings, csrfDisabled: e.target.checked })} - disabled={!loginEnabled} - /> - - -
From e7db714091af8ac62bf47e99047bca7b2247994f Mon Sep 17 00:00:00 2001 From: James Brunton Date: Thu, 4 Dec 2025 17:53:08 +0000 Subject: [PATCH 15/56] More fixes for automate (#5168) # Description of Changes Fix file missed in #5127 to use `apiClient` instead of `axios` directly Co-authored-by: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com> --- frontend/src/core/utils/automationFileProcessor.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/core/utils/automationFileProcessor.ts b/frontend/src/core/utils/automationFileProcessor.ts index b07fe961b..311848bfd 100644 --- a/frontend/src/core/utils/automationFileProcessor.ts +++ b/frontend/src/core/utils/automationFileProcessor.ts @@ -2,7 +2,7 @@ * File processing utilities specifically for automation workflows */ -import axios from 'axios'; +import apiClient from '@app/services/apiClient'; import { zipFileService } from '@app/services/zipFileService'; import { ResourceManager } from '@app/utils/resourceManager'; import { AUTOMATION_CONSTANTS } from '@app/constants/automation'; @@ -97,7 +97,7 @@ export class AutomationFileProcessor { options: AutomationProcessingOptions = {} ): Promise { try { - const response = await axios.post(endpoint, formData, { + const response = await apiClient.post(endpoint, formData, { responseType: options.responseType || 'blob', timeout: options.timeout || AUTOMATION_CONSTANTS.OPERATION_TIMEOUT }); @@ -139,7 +139,7 @@ export class AutomationFileProcessor { options: AutomationProcessingOptions = {} ): Promise { try { - const response = await axios.post(endpoint, formData, { + const response = await apiClient.post(endpoint, formData, { responseType: options.responseType || 'blob', timeout: options.timeout || AUTOMATION_CONSTANTS.OPERATION_TIMEOUT }); From 3a2370ea1f2feb9887e17afb2fced4acc198102c Mon Sep 17 00:00:00 2001 From: Keon Chen <66115421+keonchennl@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:35:11 +0100 Subject: [PATCH 16/56] Update OCR setup guide link in LanguagePicker (#5162) # Description of Changes --- ## 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) - [ x] 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 - [x ] 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) - [x ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- frontend/src/core/components/tools/ocr/LanguagePicker.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/core/components/tools/ocr/LanguagePicker.tsx b/frontend/src/core/components/tools/ocr/LanguagePicker.tsx index 784d22da5..7e023e9cc 100644 --- a/frontend/src/core/components/tools/ocr/LanguagePicker.tsx +++ b/frontend/src/core/components/tools/ocr/LanguagePicker.tsx @@ -134,7 +134,7 @@ const LanguagePicker: React.FC = ({ textDecoration: 'underline', textAlign: 'center' }} - onClick={() => window.open('https://docs.stirlingpdf.com/Advanced%20Configuration/OCR', '_blank')} + onClick={() => window.open('https://docs.stirlingpdf.com/Configuration/OCR', '_blank')} > {t('ocr.languagePicker.viewSetupGuide', 'View setup guide →')} @@ -158,4 +158,4 @@ const LanguagePicker: React.FC = ({ ); }; -export default LanguagePicker; \ No newline at end of file +export default LanguagePicker; From 9fd8fd89ed26de1147e4ed21a585390658b0cfe4 Mon Sep 17 00:00:00 2001 From: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:18:23 +0000 Subject: [PATCH 17/56] add enum SERVER to list of valid licenses (#5172) --- frontend/src/core/hooks/useServerExperience.ts | 2 +- frontend/src/proprietary/contexts/ServerExperienceContext.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/core/hooks/useServerExperience.ts b/frontend/src/core/hooks/useServerExperience.ts index 8dd60069a..28f62c1c5 100644 --- a/frontend/src/core/hooks/useServerExperience.ts +++ b/frontend/src/core/hooks/useServerExperience.ts @@ -65,7 +65,7 @@ export function useServerExperience(): ServerExperienceValue { const loginEnabled = config?.enableLogin !== false; const configIsAdmin = Boolean(config?.isAdmin); const effectiveIsAdmin = configIsAdmin || (!loginEnabled && selfReportedAdmin); - const hasPaidLicense = config?.license === 'PRO' || config?.license === 'ENTERPRISE'; + const hasPaidLicense = config?.license === 'SERVER' || config?.license === 'PRO' || config?.license === 'ENTERPRISE'; const setSelfReportedAdmin = useCallback((value: boolean) => { setSelfReportedAdminState(value); diff --git a/frontend/src/proprietary/contexts/ServerExperienceContext.tsx b/frontend/src/proprietary/contexts/ServerExperienceContext.tsx index 17ac572fc..92ce8148a 100644 --- a/frontend/src/proprietary/contexts/ServerExperienceContext.tsx +++ b/frontend/src/proprietary/contexts/ServerExperienceContext.tsx @@ -249,7 +249,7 @@ export function ServerExperienceProvider({ children }: { children: ReactNode }) }, [fetchUserCounts]); const hasPaidLicense = useMemo(() => { - return config?.license === 'PRO' || config?.license === 'ENTERPRISE'; + return config?.license === 'SERVER' || config?.license === 'PRO' || config?.license === 'ENTERPRISE'; }, [config?.license]); const licenseKeyValid = useMemo(() => { From 82dbcfbb9b78a01dee5a2754391a5444172b8875 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Fri, 5 Dec 2025 23:19:41 +0000 Subject: [PATCH 18/56] SSO login fix (#5167) Fixes bug where SSO login with custom providers caused an `InvalidClientRegistrationIdException: Invalid Client Registration with Id: oidc` errors. Root Cause: - Backend: Redirect URI was hardcoded to `/login/oauth2/code/oidc` regardless of provider registration ID - Frontend: Unknown providers were mapped back to 'oidc' instead of using actual provider ID Closes #5141 --------- Co-authored-by: Anthony Stirling <77850077+frooodle@users.noreply.github.com> Co-authored-by: Keon Chen <66115421+keonchennl@users.noreply.github.com> --- ...tomOAuth2AuthenticationSuccessHandler.java | 8 + .../security/oauth2/OAuth2Configuration.java | 24 +- ...stomSaml2AuthenticationSuccessHandler.java | 6 + .../service/UserLicenseSettingsService.java | 71 ++++- .../oauth2/OAuth2ConfigurationTest.java | 162 ++++++++++ .../UserLicenseSettingsServiceTest.java | 218 +++++++++++++ frontend/src/proprietary/auth/oauthTypes.ts | 24 ++ .../src/proprietary/auth/springAuthClient.ts | 8 +- .../src/proprietary/routes/Login.test.tsx | 178 +++++++++-- frontend/src/proprietary/routes/Login.tsx | 21 +- .../routes/login/OAuthButtons.test.tsx | 291 ++++++++++++++++++ .../proprietary/routes/login/OAuthButtons.tsx | 5 +- 12 files changed, 961 insertions(+), 55 deletions(-) create mode 100644 app/proprietary/src/test/java/stirling/software/proprietary/security/oauth2/OAuth2ConfigurationTest.java create mode 100644 frontend/src/proprietary/auth/oauthTypes.ts create mode 100644 frontend/src/proprietary/routes/login/OAuthButtons.test.tsx diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java index e1e670394..793c6b62f 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java @@ -27,6 +27,7 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; @@ -39,6 +40,7 @@ import stirling.software.proprietary.security.service.JwtServiceInterface; import stirling.software.proprietary.security.service.LoginAttemptService; import stirling.software.proprietary.security.service.UserService; +@Slf4j @RequiredArgsConstructor public class CustomOAuth2AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @@ -77,12 +79,18 @@ public class CustomOAuth2AuthenticationSuccessHandler if (user != null && !licenseSettingsService.isOAuthEligible(user)) { // User is not grandfathered and no paid license - block OAuth login + log.warn( + "OAuth login blocked for existing user '{}' - not eligible (not grandfathered and no paid license)", + username); response.sendRedirect( request.getContextPath() + "/logout?oAuth2RequiresLicense=true"); return; } } else if (!licenseSettingsService.isOAuthEligible(null)) { // No existing user and no paid license -> block auto creation + log.warn( + "OAuth login blocked for new user '{}' - not eligible (no paid license for auto-creation)", + username); response.sendRedirect(request.getContextPath() + "/logout?oAuth2RequiresLicense=true"); return; } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java index a053c1ead..2d5f94620 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java @@ -67,10 +67,15 @@ public class OAuth2Configuration { keycloakClientRegistration().ifPresent(registrations::add); if (registrations.isEmpty()) { - log.error("No OAuth2 provider registered"); + log.error("No OAuth2 provider registered - check your OAuth2 configuration"); throw new NoProviderFoundException("At least one OAuth2 provider must be configured."); } + log.info( + "OAuth2 ClientRegistrationRepository created with {} provider(s): {}", + registrations.size(), + registrations.stream().map(ClientRegistration::getRegistrationId).toList()); + return new InMemoryClientRegistrationRepository(registrations); } @@ -165,7 +170,6 @@ public class OAuth2Configuration { githubClient.getUseAsUsername()); boolean isValid = validateProvider(github); - log.info("Initialised GitHub OAuth2 provider"); return isValid ? Optional.of( @@ -208,7 +212,19 @@ public class OAuth2Configuration { null, null); - return !isStringEmpty(oidcProvider.getIssuer()) || validateProvider(oidcProvider) + boolean isValid = + !isStringEmpty(oidcProvider.getIssuer()) || validateProvider(oidcProvider); + if (isValid) { + log.info( + "Initialised OIDC OAuth2 provider: registrationId='{}', issuer='{}', redirectUri='{}'", + name, + oauth.getIssuer(), + REDIRECT_URI_PATH + name); + } else { + log.warn("OIDC OAuth2 provider validation failed - provider will not be registered"); + } + + return isValid ? Optional.of( ClientRegistrations.fromIssuerLocation(oauth.getIssuer()) .registrationId(name) @@ -217,7 +233,7 @@ public class OAuth2Configuration { .scope(oidcProvider.getScopes()) .userNameAttributeName(oidcProvider.getUseAsUsername().getName()) .clientName(clientName) - .redirectUri(REDIRECT_URI_PATH + "oidc") + .redirectUri(REDIRECT_URI_PATH + name) .authorizationGrantType(AUTHORIZATION_CODE) .build()) : Optional.empty(); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java index b342fdcb4..e8bce579a 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java @@ -74,12 +74,18 @@ public class CustomSaml2AuthenticationSuccessHandler if (user != null && !licenseSettingsService.isSamlEligible(user)) { // User is not grandfathered and no ENTERPRISE license - block SAML login + log.warn( + "SAML2 login blocked for existing user '{}' - not eligible (not grandfathered and no ENTERPRISE license)", + username); response.sendRedirect( request.getContextPath() + "/logout?saml2RequiresLicense=true"); return; } } else if (!licenseSettingsService.isSamlEligible(null)) { // No existing user and no ENTERPRISE license -> block auto creation + log.warn( + "SAML2 login blocked for new user '{}' - not eligible (no ENTERPRISE license for auto-creation)", + username); response.sendRedirect( request.getContextPath() + "/logout?saml2RequiresLicense=true"); return; diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java index d3bade89c..aa794e699 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/UserLicenseSettingsService.java @@ -21,6 +21,7 @@ import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.model.UserLicenseSettings; import stirling.software.proprietary.security.configuration.ee.KeygenLicenseVerifier.License; import stirling.software.proprietary.security.configuration.ee.LicenseKeyChecker; +import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.repository.UserLicenseSettingsRepository; import stirling.software.proprietary.security.service.UserService; @@ -331,28 +332,45 @@ public class UserLicenseSettingsService { } /** - * Checks if a user is eligible to use OAuth authentication. + * Checks if a user is eligible to use OAuth/SAML authentication. * *

A user is eligible if: * *

    *
  • They are grandfathered for OAuth (existing user before policy change), OR - *
  • The system has a paid license (SERVER or ENTERPRISE) + *
  • The system has an ENTERPRISE license (SSO is enterprise-only) *
* * @param user The user to check - * @return true if the user can use OAuth + * @return true if the user can use OAuth/SAML */ - public boolean isOAuthEligible(stirling.software.proprietary.security.model.User user) { + public boolean isOAuthEligible(User user) { + String username = (user != null) ? user.getUsername() : ""; + log.info("OAuth eligibility check for user: {}", username); + // Grandfathered users always have OAuth access if (user != null && user.isOauthGrandfathered()) { log.debug("User {} is grandfathered for OAuth", user.getUsername()); return true; } + // todo: remove + if (user != null) { + log.info( + "User {} is NOT grandfathered (isOauthGrandfathered={})", + username, + user.isOauthGrandfathered()); + } else { + log.info("New user attempting OAuth login - checking license requirement"); + } + // Users can use OAuth with SERVER or ENTERPRISE license boolean hasPaid = hasPaidLicense(); - log.debug("OAuth eligibility check: hasPaidLicense={}", hasPaid); + log.info( + "OAuth eligibility result: hasPaidLicense={}, user={}, eligible={}", + hasPaid, + username, + hasPaid); return hasPaid; } @@ -369,16 +387,32 @@ public class UserLicenseSettingsService { * @param user The user to check * @return true if the user can use SAML */ - public boolean isSamlEligible(stirling.software.proprietary.security.model.User user) { + public boolean isSamlEligible(User user) { + String username = (user != null) ? user.getUsername() : ""; + log.info("SAML2 eligibility check for user: {}", username); + // Grandfathered users always have SAML access if (user != null && user.isOauthGrandfathered()) { - log.debug("User {} is grandfathered for SAML", user.getUsername()); + log.info("User {} is grandfathered for SAML2 - ELIGIBLE", username); return true; } + if (user != null) { + log.info( + "User {} is NOT grandfathered (isOauthGrandfathered={})", + username, + user.isOauthGrandfathered()); + } else { + log.info("New user attempting SAML2 login - checking license requirement"); + } + // Users can use SAML only with ENTERPRISE license boolean hasEnterprise = hasEnterpriseLicense(); - log.debug("SAML eligibility check: hasEnterpriseLicense={}", hasEnterprise); + log.info( + "SAML2 eligibility result: hasEnterpriseLicense={}, user={}, eligible={}", + hasEnterprise, + username, + hasEnterprise); return hasEnterprise; } @@ -521,12 +555,17 @@ public class UserLicenseSettingsService { if (checker == null) { return false; } + License license = checker.getPremiumLicenseEnabledResult(); - return license == License.SERVER || license == License.ENTERPRISE; + boolean hasPaid = (license == License.SERVER || license == License.ENTERPRISE); + log.info("License check result: type={}, requiresPaid=true, hasPaid={}", license, hasPaid); + + return hasPaid; } /** - * Checks if the system has an ENTERPRISE license. Used for enterprise-only features like SAML. + * Checks if the system has an ENTERPRISE license. Used for enterprise-only features like SSO + * (OAuth/SAML). * * @return true if ENTERPRISE license is active */ @@ -535,7 +574,19 @@ public class UserLicenseSettingsService { if (checker == null) { return false; } + License license = checker.getPremiumLicenseEnabledResult(); + log.info( + "License check result: type={}, requiresEnterprise=true, hasEnterprise={}", + license, + (license == License.ENTERPRISE)); + + if (license != License.ENTERPRISE) { + log.warn( + "SAML2 requires ENTERPRISE license but found: {}. SAML2 login will be blocked.", + license); + } + return license == License.ENTERPRISE; } } diff --git a/app/proprietary/src/test/java/stirling/software/proprietary/security/oauth2/OAuth2ConfigurationTest.java b/app/proprietary/src/test/java/stirling/software/proprietary/security/oauth2/OAuth2ConfigurationTest.java new file mode 100644 index 000000000..750696b77 --- /dev/null +++ b/app/proprietary/src/test/java/stirling/software/proprietary/security/oauth2/OAuth2ConfigurationTest.java @@ -0,0 +1,162 @@ +package stirling.software.proprietary.security.oauth2; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for OAuth2Configuration redirect URI logic. + * + *

These tests validate the critical fix for GitHub issue #5141: The redirect URI path segment + * MUST match the registration ID. Previously, the redirect URI was hardcoded to 'oidc', causing + * InvalidClientRegistrationIdException when custom provider names were used. + * + *

Note: These are conceptual tests documenting the expected behavior. Full integration testing + * with actual OIDC discovery would require: 1. Mock HTTP server for OIDC discovery endpoints 2. + * Valid OIDC configuration responses 3. Network mocking infrastructure + */ +class OAuth2ConfigurationTest { + + /** + * Tests the redirect URI pattern for OIDC provider configurations. + * + *

Critical behavior (GitHub issue #5141 fix): The redirect URI path segment MUST match the + * registration ID. For example: - Provider name: "authentik" → Redirect URI: + * "/login/oauth2/code/authentik" - Provider name: "mycompany" → Redirect URI: + * "/login/oauth2/code/mycompany" - Provider name: "oidc" → Redirect URI: + * "/login/oauth2/code/oidc" + * + *

Previously, the redirect URI was hardcoded to 'oidc', causing Spring Security to look for + * a registration with ID 'oidc' when the provider redirected back. This caused + * InvalidClientRegistrationIdException when custom provider names were used. + */ + @Test + void testRedirectUriPattern_usesProviderNameNotHardcodedOidc() { + // Verify the redirect URI pattern constant + String redirectUriBase = "{baseUrl}/login/oauth2/code/"; + + // Test cases: provider name → expected redirect URI + String[][] testCases = { + {"authentik", redirectUriBase + "authentik"}, + {"mycompany", redirectUriBase + "mycompany"}, + {"oidc", redirectUriBase + "oidc"}, + {"okta", redirectUriBase + "okta"}, + {"auth0", redirectUriBase + "auth0"} + }; + + for (String[] testCase : testCases) { + String providerName = testCase[0]; + String expectedRedirectUri = testCase[1]; + + // The fix ensures: .redirectUri(REDIRECT_URI_PATH + name) + // instead of: .redirectUri(REDIRECT_URI_PATH + "oidc") + String actualRedirectUri = redirectUriBase + providerName; + + assertEquals( + expectedRedirectUri, + actualRedirectUri, + String.format( + "Redirect URI for provider '%s' must use provider name, not hardcoded 'oidc'", + providerName)); + } + } + + /** + * Documents the critical fix for OAuth2 redirect URI mismatch. + * + *

This test validates the logic that was changed in OAuth2Configuration.java line 220: + * + *

+     * // BEFORE (bug):
+     * .redirectUri(REDIRECT_URI_PATH + "oidc")  // Always "oidc"
+     *
+     * // AFTER (fix):
+     * .redirectUri(REDIRECT_URI_PATH + name)  // Dynamic provider name
+     * 
+ */ + @Test + void testCriticalFix_redirectUriMatchesRegistrationId() { + // The redirect URI path segment extraction by Spring Security + String callbackUrl = "http://localhost:8080/login/oauth2/code/authentik?code=abc123"; + + // Spring extracts the path segment between "code/" and "?" + String extractedRegistrationId = extractRegistrationIdFromCallback(callbackUrl); + + // The extracted ID MUST match an actual registration ID + assertEquals("authentik", extractedRegistrationId); + + // If we had used hardcoded "oidc", the callback would be: + String buggyCallbackUrl = "http://localhost:8080/login/oauth2/code/oidc?code=abc123"; + String buggyExtractedId = extractRegistrationIdFromCallback(buggyCallbackUrl); + + // This would look for registration with ID "oidc" but we registered "authentik" + assertEquals("oidc", buggyExtractedId); + + // The mismatch: registrationId="authentik", but Spring looks for "oidc" + // Result: InvalidClientRegistrationIdException + assertNotNull(buggyExtractedId, "This demonstrates the bug that was fixed"); + } + + /** Helper method simulating Spring's extraction of registration ID from callback URL */ + private String extractRegistrationIdFromCallback(String callbackUrl) { + // Simplified version of what Spring Security does + // Actual: OAuth2AuthorizationRequestRedirectFilter extracts from path + String path = callbackUrl.split("\\?")[0]; + String[] parts = path.split("/"); + return parts[parts.length - 1]; // Last path segment + } + + /** + * Validates the frontend-backend flow for custom provider names. + * + *

Complete flow: 1. Backend: Provider configured as "authentik" in settings.yml 2. Backend: + * ClientRegistration created with registrationId="authentik" 3. Backend: Redirect URI set to + * "{baseUrl}/login/oauth2/code/authentik" 4. Backend: Login endpoint returns providerList with + * "/oauth2/authorization/authentik" 5. Frontend: Extracts "authentik" from path and uses it for + * OAuth login 6. Frontend: Redirects to "/oauth2/authorization/authentik" 7. Backend: Spring + * Security redirects to provider with redirect_uri containing "authentik" 8. Provider: + * Redirects back to "/login/oauth2/code/authentik?code=..." 9. Backend: Spring Security + * extracts "authentik" from callback URL 10. Backend: Looks up ClientRegistration with ID + * "authentik" ✅ SUCCESS + * + *

If redirect URI was hardcoded to "oidc" (the bug): Step 7: Provider redirects to + * "/login/oauth2/code/oidc?code=..." Step 9: Spring Security looks for registration ID "oidc" + * Step 10: FAIL - No registration found with ID "oidc" (we registered "authentik") Result: + * InvalidClientRegistrationIdException + */ + @Test + void testEndToEndFlow_registrationIdConsistency() { + String providerName = "authentik"; + + // Step 2: Registration ID + String registrationId = providerName; + assertEquals("authentik", registrationId); + + // Step 3: Redirect URI (MUST use same name) + String redirectUri = "{baseUrl}/login/oauth2/code/" + providerName; + assertEquals("{baseUrl}/login/oauth2/code/authentik", redirectUri); + + // Step 4: Provider list endpoint + String authorizationPath = "/oauth2/authorization/" + providerName; + assertEquals("/oauth2/authorization/authentik", authorizationPath); + + // Step 5: Frontend extracts provider ID + String frontendProviderId = + authorizationPath.substring(authorizationPath.lastIndexOf('/') + 1); + assertEquals("authentik", frontendProviderId); + + // Step 6-8: OAuth flow (external) + + // Step 9: Callback URL from provider + String callbackUrl = + "http://localhost:8080/login/oauth2/code/" + providerName + "?code=abc123"; + String extractedId = extractRegistrationIdFromCallback(callbackUrl); + + // Step 10: Registration lookup + assertEquals( + registrationId, + extractedId, + "Registration ID from callback MUST match original registration ID"); + } +} diff --git a/app/proprietary/src/test/java/stirling/software/proprietary/service/UserLicenseSettingsServiceTest.java b/app/proprietary/src/test/java/stirling/software/proprietary/service/UserLicenseSettingsServiceTest.java index 139146d70..7f9445ad7 100644 --- a/app/proprietary/src/test/java/stirling/software/proprietary/service/UserLicenseSettingsServiceTest.java +++ b/app/proprietary/src/test/java/stirling/software/proprietary/service/UserLicenseSettingsServiceTest.java @@ -267,4 +267,222 @@ class UserLicenseSettingsServiceTest { verify(userService, times(1)).grandfatherAllOAuthUsers(); verify(userService, times(1)).grandfatherPendingSsoUsersWithoutSession(); } + + // ===== OAuth Eligibility Tests ===== + + @Test + void isOAuthEligible_grandfatheredUser_returnsTrue() { + // Grandfathered user should be eligible regardless of license + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("grandfathered-user"); + user.setOauthGrandfathered(true); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.NORMAL); + + boolean result = service.isOAuthEligible(user); + + assertEquals(true, result, "Grandfathered user should be eligible for OAuth"); + } + + @Test + void isOAuthEligible_nonGrandfatheredUserWithServerLicense_returnsTrue() { + // Non-grandfathered user with SERVER license should be eligible + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.SERVER); + + boolean result = service.isOAuthEligible(user); + + assertEquals(true, result, "Non-grandfathered user with SERVER license should be eligible"); + } + + @Test + void isOAuthEligible_nonGrandfatheredUserWithEnterpriseLicense_returnsTrue() { + // Non-grandfathered user with ENTERPRISE license should be eligible + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.ENTERPRISE); + + boolean result = service.isOAuthEligible(user); + + assertEquals( + true, result, "Non-grandfathered user with ENTERPRISE license should be eligible"); + } + + @Test + void isOAuthEligible_nonGrandfatheredUserWithNoLicense_returnsFalse() { + // Non-grandfathered user without license should NOT be eligible + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.NORMAL); + + boolean result = service.isOAuthEligible(user); + + assertEquals( + false, + result, + "Non-grandfathered user without paid license should NOT be eligible"); + } + + @Test + void isOAuthEligible_newUserWithServerLicense_returnsTrue() { + // New user (null) with SERVER license should be eligible for auto-creation + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.SERVER); + + boolean result = service.isOAuthEligible(null); + + assertEquals( + true, result, "New user with SERVER license should be eligible for auto-creation"); + } + + @Test + void isOAuthEligible_newUserWithNoLicense_returnsFalse() { + // New user (null) without license should NOT be eligible + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.NORMAL); + + boolean result = service.isOAuthEligible(null); + + assertEquals( + false, + result, + "New user without paid license should NOT be eligible for auto-creation"); + } + + @Test + void isOAuthEligible_licenseCheckerUnavailable_returnsFalse() { + // If LicenseKeyChecker is unavailable, OAuth should be blocked + when(licenseKeyCheckerProvider.getIfAvailable()).thenReturn(null); + + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + boolean result = service.isOAuthEligible(user); + + assertEquals( + false, result, "OAuth should be blocked when LicenseKeyChecker is unavailable"); + } + + // ===== SAML Eligibility Tests ===== + + @Test + void isSamlEligible_grandfatheredUser_returnsTrue() { + // Grandfathered user should be eligible for SAML regardless of license + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("grandfathered-user"); + user.setOauthGrandfathered(true); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.NORMAL); + + boolean result = service.isSamlEligible(user); + + assertEquals(true, result, "Grandfathered user should be eligible for SAML"); + } + + @Test + void isSamlEligible_nonGrandfatheredUserWithEnterpriseLicense_returnsTrue() { + // Non-grandfathered user with ENTERPRISE license should be eligible + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.ENTERPRISE); + + boolean result = service.isSamlEligible(user); + + assertEquals( + true, + result, + "Non-grandfathered user with ENTERPRISE license should be eligible for SAML"); + } + + @Test + void isSamlEligible_nonGrandfatheredUserWithServerLicense_returnsFalse() { + // Non-grandfathered user with SERVER license should NOT be eligible for SAML + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.SERVER); + + boolean result = service.isSamlEligible(user); + + assertEquals( + false, + result, + "Non-grandfathered user with SERVER license should NOT be eligible for SAML"); + } + + @Test + void isSamlEligible_nonGrandfatheredUserWithNoLicense_returnsFalse() { + // Non-grandfathered user without license should NOT be eligible + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.NORMAL); + + boolean result = service.isSamlEligible(user); + + assertEquals( + false, + result, + "Non-grandfathered user without ENTERPRISE license should NOT be eligible for SAML"); + } + + @Test + void isSamlEligible_newUserWithEnterpriseLicense_returnsTrue() { + // New user (null) with ENTERPRISE license should be eligible for auto-creation + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.ENTERPRISE); + + boolean result = service.isSamlEligible(null); + + assertEquals( + true, + result, + "New user with ENTERPRISE license should be eligible for SAML auto-creation"); + } + + @Test + void isSamlEligible_newUserWithServerLicense_returnsFalse() { + // New user (null) with SERVER license should NOT be eligible for SAML + when(licenseKeyChecker.getPremiumLicenseEnabledResult()).thenReturn(License.SERVER); + + boolean result = service.isSamlEligible(null); + + assertEquals( + false, + result, + "New user with SERVER license should NOT be eligible for SAML (requires ENTERPRISE)"); + } + + @Test + void isSamlEligible_licenseCheckerUnavailable_returnsFalse() { + // If LicenseKeyChecker is unavailable, SAML should be blocked + when(licenseKeyCheckerProvider.getIfAvailable()).thenReturn(null); + + stirling.software.proprietary.security.model.User user = + new stirling.software.proprietary.security.model.User(); + user.setUsername("test-user"); + user.setOauthGrandfathered(false); + + boolean result = service.isSamlEligible(user); + + assertEquals(false, result, "SAML should be blocked when LicenseKeyChecker is unavailable"); + } } diff --git a/frontend/src/proprietary/auth/oauthTypes.ts b/frontend/src/proprietary/auth/oauthTypes.ts new file mode 100644 index 000000000..2d38f1b3e --- /dev/null +++ b/frontend/src/proprietary/auth/oauthTypes.ts @@ -0,0 +1,24 @@ +/** + * Known OAuth providers with dedicated UI support. + * Custom providers are also supported - the backend determines availability. + */ +export const KNOWN_OAUTH_PROVIDERS = [ + 'github', + 'google', + 'apple', + 'azure', + 'keycloak', + 'cloudron', + 'authentik', + 'oidc', +] as const; + +export type KnownOAuthProvider = typeof KNOWN_OAUTH_PROVIDERS[number]; + +/** + * OAuth provider ID - can be any known provider or custom string. + * The backend configuration determines which providers are available. + * + * @example 'github' | 'google' | 'mycompany' | 'authentik' + */ +export type OAuthProvider = KnownOAuthProvider | (string & {}); diff --git a/frontend/src/proprietary/auth/springAuthClient.ts b/frontend/src/proprietary/auth/springAuthClient.ts index 2f1aa36cb..646b71182 100644 --- a/frontend/src/proprietary/auth/springAuthClient.ts +++ b/frontend/src/proprietary/auth/springAuthClient.ts @@ -10,6 +10,7 @@ import apiClient from '@app/services/apiClient'; import { AxiosError } from 'axios'; import { BASE_PATH } from '@app/constants/app'; +import { type OAuthProvider } from '@app/auth/oauthTypes'; // Helper to extract error message from axios error function getErrorMessage(error: unknown, fallback: string): string { @@ -248,11 +249,14 @@ class SpringAuthClient { } /** - * Sign in with OAuth provider (GitHub, Google, etc.) + * Sign in with OAuth provider (GitHub, Google, Authentik, etc.) * This redirects to the Spring OAuth2 authorization endpoint + * + * @param params.provider - OAuth provider ID (e.g., 'github', 'google', 'authentik', 'mycompany') + * Can be any known provider or custom string - the backend determines available providers */ async signInWithOAuth(params: { - provider: 'github' | 'google' | 'apple' | 'azure' | 'keycloak' | 'oidc'; + provider: OAuthProvider; options?: { redirectTo?: string; queryParams?: Record }; }): Promise<{ error: AuthError | null }> { try { diff --git a/frontend/src/proprietary/routes/Login.test.tsx b/frontend/src/proprietary/routes/Login.test.tsx index 62679f22a..996176c01 100644 --- a/frontend/src/proprietary/routes/Login.test.tsx +++ b/frontend/src/proprietary/routes/Login.test.tsx @@ -7,6 +7,7 @@ import Login from '@app/routes/Login'; import { useAuth } from '@app/auth/UseSession'; import { springAuth } from '@app/auth/springAuthClient'; import { PreferencesProvider } from '@app/contexts/PreferencesContext'; +import apiClient from '@app/services/apiClient'; // Mock i18n to return fallback text vi.mock('react-i18next', () => ({ @@ -36,8 +37,13 @@ vi.mock('@app/hooks/useDocumentMeta', () => ({ useDocumentMeta: vi.fn(), })); -// Mock fetch for provider list -global.fetch = vi.fn(); +// Mock apiClient for provider list +vi.mock('@app/services/apiClient', () => ({ + default: { + get: vi.fn(), + post: vi.fn(), + }, +})); const mockNavigate = vi.fn(); const mockBackendProbeState = { @@ -89,14 +95,13 @@ describe('Login', () => { refreshSession: vi.fn(), }); - // Mock fetch for login UI data - vi.mocked(fetch).mockResolvedValue({ - ok: true, - json: async () => ({ + // Mock apiClient for login UI data + vi.mocked(apiClient.get).mockResolvedValue({ + data: { enableLogin: true, providerList: {}, - }), - } as Response); + }, + }); }); it('should render login form', async () => { @@ -239,6 +244,136 @@ describe('Login', () => { }); }); + it('should use actual provider ID for OAuth login (authentik)', async () => { + const user = userEvent.setup(); + + // Mock provider list with authentik + vi.mocked(apiClient.get).mockResolvedValue({ + data: { + enableLogin: true, + providerList: { + '/oauth2/authorization/authentik': 'Authentik', + }, + }, + }); + + vi.mocked(springAuth.signInWithOAuth).mockResolvedValueOnce({ + error: null, + }); + + render( + + + + + + ); + + // Wait for OAuth button to appear + await waitFor(() => { + const button = screen.queryByText('Authentik'); + expect(button).toBeTruthy(); + }, { timeout: 3000 }); + + const oauthButton = screen.getByText('Authentik'); + await user.click(oauthButton); + + await waitFor(() => { + // Should use 'authentik' directly, NOT map to 'oidc' + expect(springAuth.signInWithOAuth).toHaveBeenCalledWith({ + provider: 'authentik', + options: { redirectTo: '/auth/callback' } + }); + }); + }); + + it('should use actual provider ID for OAuth login (custom provider)', async () => { + const user = userEvent.setup(); + + // Mock provider list with custom provider 'mycompany' + vi.mocked(apiClient.get).mockResolvedValue({ + data: { + enableLogin: true, + providerList: { + '/oauth2/authorization/mycompany': 'My Company SSO', + }, + }, + }); + + vi.mocked(springAuth.signInWithOAuth).mockResolvedValueOnce({ + error: null, + }); + + render( + + + + + + ); + + // Wait for OAuth button to appear (will show 'Mycompany' as label) + await waitFor(() => { + const button = screen.queryByText('Mycompany'); + expect(button).toBeTruthy(); + }, { timeout: 3000 }); + + const oauthButton = screen.getByText('Mycompany'); + await user.click(oauthButton); + + await waitFor(() => { + // Should use 'mycompany' directly - this is the critical fix + // Previously it would map unknown providers to 'oidc' + expect(springAuth.signInWithOAuth).toHaveBeenCalledWith({ + provider: 'mycompany', + options: { redirectTo: '/auth/callback' } + }); + }); + }); + + it('should use oidc provider ID when explicitly configured', async () => { + const user = userEvent.setup(); + + // Mock provider list with 'oidc' + vi.mocked(apiClient.get).mockResolvedValue({ + data: { + enableLogin: true, + providerList: { + '/oauth2/authorization/oidc': 'OIDC', + }, + }, + }); + + vi.mocked(springAuth.signInWithOAuth).mockResolvedValueOnce({ + error: null, + }); + + render( + + + + + + ); + + // Wait for OAuth button to appear + await waitFor(() => { + const button = screen.queryByText('OIDC'); + expect(button).toBeTruthy(); + }, { timeout: 3000 }); + + const oauthButton = screen.getByText('OIDC'); + await user.click(oauthButton); + + await waitFor(() => { + // Should use 'oidc' when explicitly configured + expect(springAuth.signInWithOAuth).toHaveBeenCalledWith({ + provider: 'oidc', + options: { redirectTo: '/auth/callback' } + }); + }); + }); + it('should show error on failed login', async () => { const user = userEvent.setup(); const errorMessage = 'Invalid credentials'; @@ -359,13 +494,12 @@ describe('Login', () => { it('should redirect to home when login disabled', async () => { mockBackendProbeState.loginDisabled = true; mockProbe.mockResolvedValueOnce({ status: 'up', loginDisabled: true, loading: false }); - vi.mocked(fetch).mockResolvedValueOnce({ - ok: true, - json: async () => ({ + vi.mocked(apiClient.get).mockResolvedValueOnce({ + data: { enableLogin: false, providerList: {}, - }), - } as Response); + }, + }); render( @@ -381,15 +515,14 @@ describe('Login', () => { }); it('should handle OAuth provider click', async () => { - vi.mocked(fetch).mockResolvedValueOnce({ - ok: true, - json: async () => ({ + vi.mocked(apiClient.get).mockResolvedValueOnce({ + data: { enableLogin: true, providerList: { '/oauth2/authorization/github': 'GitHub', }, - }), - } as Response); + }, + }); vi.mocked(springAuth.signInWithOAuth).mockResolvedValueOnce({ error: null, @@ -416,13 +549,12 @@ describe('Login', () => { }); it('should show email form by default when no SSO providers', async () => { - vi.mocked(fetch).mockResolvedValueOnce({ - ok: true, - json: async () => ({ + vi.mocked(apiClient.get).mockResolvedValueOnce({ + data: { enableLogin: true, providerList: {}, // No providers - }), - } as Response); + }, + }); render( diff --git a/frontend/src/proprietary/routes/Login.tsx b/frontend/src/proprietary/routes/Login.tsx index 80a12e1d0..cf6004e50 100644 --- a/frontend/src/proprietary/routes/Login.tsx +++ b/frontend/src/proprietary/routes/Login.tsx @@ -10,6 +10,7 @@ import AuthLayout from '@app/routes/authShared/AuthLayout'; import { useBackendProbe } from '@app/hooks/useBackendProbe'; import apiClient from '@app/services/apiClient'; import { BASE_PATH } from '@app/constants/app'; +import { type OAuthProvider } from '@app/auth/oauthTypes'; // Import login components import LoginHeader from '@app/routes/login/LoginHeader'; @@ -31,7 +32,7 @@ export default function Login() { const [showEmailForm, setShowEmailForm] = useState(false); const [email, setEmail] = useState(() => searchParams.get('email') ?? ''); const [password, setPassword] = useState(''); - const [enabledProviders, setEnabledProviders] = useState([]); + const [enabledProviders, setEnabledProviders] = useState([]); const [hasSSOProviders, setHasSSOProviders] = useState(false); const [_enableLogin, setEnableLogin] = useState(null); const backendProbe = useBackendProbe(); @@ -226,25 +227,17 @@ export default function Login() { ); } - // Known OAuth providers that have dedicated backend support - const KNOWN_OAUTH_PROVIDERS = ['github', 'google', 'apple', 'azure', 'keycloak', 'oidc'] as const; - type KnownOAuthProvider = typeof KNOWN_OAUTH_PROVIDERS[number]; - - const signInWithProvider = async (provider: string) => { + const signInWithProvider = async (provider: OAuthProvider) => { try { setIsSigningIn(true); setError(null); - // Map unknown providers to 'oidc' for the backend redirect - const backendProvider: KnownOAuthProvider = KNOWN_OAUTH_PROVIDERS.includes(provider as KnownOAuthProvider) - ? (provider as KnownOAuthProvider) - : 'oidc'; + console.log(`[Login] Signing in with provider: ${provider}`); - console.log(`[Login] Signing in with ${provider} (backend: ${backendProvider})`); - - // Redirect to Spring OAuth2 endpoint + // Redirect to Spring OAuth2 endpoint using the actual provider ID from backend + // The backend returns the correct registration ID (e.g., 'authentik', 'oidc', 'keycloak') const { error } = await springAuth.signInWithOAuth({ - provider: backendProvider, + provider: provider, options: { redirectTo: `${BASE_PATH}/auth/callback` } }); diff --git a/frontend/src/proprietary/routes/login/OAuthButtons.test.tsx b/frontend/src/proprietary/routes/login/OAuthButtons.test.tsx new file mode 100644 index 000000000..62f121d68 --- /dev/null +++ b/frontend/src/proprietary/routes/login/OAuthButtons.test.tsx @@ -0,0 +1,291 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { MantineProvider } from '@mantine/core'; +import OAuthButtons from '@app/routes/login/OAuthButtons'; + +// Mock i18n +vi.mock('react-i18next', () => ({ + useTranslation: () => ({ + t: (key: string, fallback?: string) => fallback || key, + }), +})); + +const TestWrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +); + +describe('OAuthButtons', () => { + const mockOnProviderClick = vi.fn(); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should render known providers with correct labels', () => { + const enabledProviders = ['google', 'github', 'authentik']; + + render( + + + + ); + + // Check that known providers are rendered with their labels + expect(screen.getByText('Google')).toBeTruthy(); + expect(screen.getByText('GitHub')).toBeTruthy(); + expect(screen.getByText('Authentik')).toBeTruthy(); + }); + + it('should render unknown provider with capitalized label and generic icon', () => { + const enabledProviders = ['mycompany']; + + render( + + + + ); + + // Unknown provider should be capitalized + expect(screen.getByText('Mycompany')).toBeTruthy(); + + // Check that button has generic OIDC icon + const button = screen.getByText('Mycompany').closest('button'); + expect(button).toBeTruthy(); + const img = button?.querySelector('img'); + expect(img?.src).toContain('oidc.svg'); + }); + + it('should call onProviderClick with actual provider ID (not "oidc")', async () => { + const user = userEvent.setup(); + const enabledProviders = ['mycompany']; + + render( + + + + ); + + const button = screen.getByText('Mycompany'); + await user.click(button); + + // Should use actual provider ID 'mycompany', NOT 'oidc' + expect(mockOnProviderClick).toHaveBeenCalledWith('mycompany'); + }); + + it('should call onProviderClick with "authentik" when authentik is clicked', async () => { + const user = userEvent.setup(); + const enabledProviders = ['authentik']; + + render( + + + + ); + + const button = screen.getByText('Authentik'); + await user.click(button); + + expect(mockOnProviderClick).toHaveBeenCalledWith('authentik'); + }); + + it('should call onProviderClick with "oidc" when OIDC is explicitly configured', async () => { + const user = userEvent.setup(); + const enabledProviders = ['oidc']; + + render( + + + + ); + + const button = screen.getByText('OIDC'); + await user.click(button); + + expect(mockOnProviderClick).toHaveBeenCalledWith('oidc'); + }); + + it('should disable buttons when isSubmitting is true', () => { + const enabledProviders = ['google', 'github']; + + render( + + + + ); + + const googleButton = screen.getByText('Google').closest('button') as HTMLButtonElement; + const githubButton = screen.getByText('GitHub').closest('button') as HTMLButtonElement; + + expect(googleButton.disabled).toBe(true); + expect(githubButton.disabled).toBe(true); + }); + + it('should render nothing when no providers are enabled', () => { + const { container } = render( + + + + ); + + // Should render null/nothing (excluding Mantine's style tags) + const hasContent = Array.from(container.children).some( + child => child.tagName.toLowerCase() !== 'style' + ); + expect(hasContent).toBe(false); + }); + + it('should render multiple unknown providers with correct IDs', async () => { + const user = userEvent.setup(); + const enabledProviders = ['company1', 'company2', 'company3']; + + render( + + + + ); + + // All should be capitalized + expect(screen.getByText('Company1')).toBeTruthy(); + expect(screen.getByText('Company2')).toBeTruthy(); + expect(screen.getByText('Company3')).toBeTruthy(); + + // Click each and verify correct ID is passed + await user.click(screen.getByText('Company1')); + expect(mockOnProviderClick).toHaveBeenCalledWith('company1'); + + await user.click(screen.getByText('Company2')); + expect(mockOnProviderClick).toHaveBeenCalledWith('company2'); + + await user.click(screen.getByText('Company3')); + expect(mockOnProviderClick).toHaveBeenCalledWith('company3'); + }); + + it('should use correct icon for known providers', () => { + const enabledProviders = ['google', 'github', 'authentik', 'keycloak']; + + render( + + + + ); + + // Check that each known provider has its specific icon + const googleButton = screen.getByText('Google').closest('button'); + expect(googleButton?.querySelector('img')?.src).toContain('google.svg'); + + const githubButton = screen.getByText('GitHub').closest('button'); + expect(githubButton?.querySelector('img')?.src).toContain('github.svg'); + + const authentikButton = screen.getByText('Authentik').closest('button'); + expect(authentikButton?.querySelector('img')?.src).toContain('authentik.svg'); + + const keycloakButton = screen.getByText('Keycloak').closest('button'); + expect(keycloakButton?.querySelector('img')?.src).toContain('keycloak.svg'); + }); + + it('should handle mixed known and unknown providers', async () => { + const user = userEvent.setup(); + const enabledProviders = ['google', 'mycompany', 'authentik', 'custom']; + + render( + + + + ); + + // Known providers with correct labels + expect(screen.getByText('Google')).toBeTruthy(); + expect(screen.getByText('Authentik')).toBeTruthy(); + + // Unknown providers with capitalized labels + expect(screen.getByText('Mycompany')).toBeTruthy(); + expect(screen.getByText('Custom')).toBeTruthy(); + + // Click each and verify IDs are preserved + await user.click(screen.getByText('Google')); + expect(mockOnProviderClick).toHaveBeenCalledWith('google'); + + await user.click(screen.getByText('Mycompany')); + expect(mockOnProviderClick).toHaveBeenCalledWith('mycompany'); + + await user.click(screen.getByText('Authentik')); + expect(mockOnProviderClick).toHaveBeenCalledWith('authentik'); + + await user.click(screen.getByText('Custom')); + expect(mockOnProviderClick).toHaveBeenCalledWith('custom'); + }); + + it('should maintain provider ID consistency - critical for OAuth redirect', async () => { + const user = userEvent.setup(); + + // This test ensures the fix for GitHub issue #5141 + // The provider ID used in the button click MUST match the backend registration ID + // Previously, unknown providers were mapped to 'oidc', breaking the OAuth flow + + const enabledProviders = ['authentik', 'okta', 'auth0']; + + render( + + + + ); + + // Each provider should use its actual ID, not 'oidc' + await user.click(screen.getByText('Authentik')); + expect(mockOnProviderClick).toHaveBeenLastCalledWith('authentik'); + + await user.click(screen.getByText('Okta')); + expect(mockOnProviderClick).toHaveBeenLastCalledWith('okta'); + + await user.click(screen.getByText('Auth0')); + expect(mockOnProviderClick).toHaveBeenLastCalledWith('auth0'); + + // Verify none were called with 'oidc' instead of their actual ID + expect(mockOnProviderClick).not.toHaveBeenCalledWith('oidc'); + }); +}); diff --git a/frontend/src/proprietary/routes/login/OAuthButtons.tsx b/frontend/src/proprietary/routes/login/OAuthButtons.tsx index aaa280519..d62edfdc1 100644 --- a/frontend/src/proprietary/routes/login/OAuthButtons.tsx +++ b/frontend/src/proprietary/routes/login/OAuthButtons.tsx @@ -1,5 +1,6 @@ import { useTranslation } from 'react-i18next'; import { BASE_PATH } from '@app/constants/app'; +import { type OAuthProvider } from '@app/auth/oauthTypes'; // Debug flag to show all providers for UI testing // Set to true to see all SSO options regardless of backend configuration @@ -22,10 +23,10 @@ export const oauthProviderConfig: Record void + onProviderClick: (provider: OAuthProvider) => void isSubmitting: boolean layout?: 'vertical' | 'grid' | 'icons' - enabledProviders?: string[] // List of enabled provider IDs from backend + enabledProviders?: OAuthProvider[] // List of enabled provider IDs from backend } export default function OAuthButtons({ onProviderClick, isSubmitting, layout = 'vertical', enabledProviders = [] }: OAuthButtonsProps) { From bb201ef9c10609398576fb4cc1d2033a9d4034e4 Mon Sep 17 00:00:00 2001 From: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:22:32 +0000 Subject: [PATCH 19/56] Chore/bump gradle version number (#5176) bump version number --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2ae135594..85f6a480d 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ repositories { allprojects { group = 'stirling.software' - version = '2.1.0' + version = '2.1.1' configurations.configureEach { exclude group: 'commons-logging', module: 'commons-logging' From 7faf7e50facf487e95b1ae1917b4611a3b30bfe8 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Sat, 6 Dec 2025 00:06:11 +0000 Subject: [PATCH 20/56] Chang etext on intro (#5160) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .../public/locales/ar-AR/translation.toml | 6 +++--- .../public/locales/az-AZ/translation.toml | 2 +- .../public/locales/bg-BG/translation.toml | 2 +- .../public/locales/ca-CA/translation.toml | 10 +++++----- .../public/locales/cs-CZ/translation.toml | 4 ++-- .../public/locales/da-DK/translation.toml | 8 ++++---- .../public/locales/de-DE/translation.toml | 2 +- .../public/locales/el-GR/translation.toml | 6 +++--- .../public/locales/en-GB/translation.toml | 2 +- .../public/locales/es-ES/translation.toml | 2 +- .../public/locales/eu-ES/translation.toml | 2 +- .../public/locales/fa-IR/translation.toml | 8 ++++---- .../public/locales/fr-FR/translation.toml | 8 ++++---- .../public/locales/ga-IE/translation.toml | 6 +++--- .../public/locales/hi-IN/translation.toml | 20 +++++++++---------- .../public/locales/hr-HR/translation.toml | 2 +- .../public/locales/hu-HU/translation.toml | 2 +- .../public/locales/id-ID/translation.toml | 6 +++--- .../public/locales/it-IT/translation.toml | 4 ++-- .../public/locales/ja-JP/translation.toml | 2 +- .../public/locales/ko-KR/translation.toml | 2 +- .../public/locales/ml-ML/translation.toml | 2 +- .../public/locales/nl-NL/translation.toml | 2 +- .../public/locales/no-NB/translation.toml | 2 +- .../public/locales/pl-PL/translation.toml | 8 ++++---- .../public/locales/pt-BR/translation.toml | 4 ++-- .../public/locales/pt-PT/translation.toml | 2 +- .../public/locales/ro-RO/translation.toml | 8 ++++---- .../public/locales/ru-RU/translation.toml | 2 +- .../public/locales/sk-SK/translation.toml | 2 +- .../public/locales/sl-SI/translation.toml | 2 +- .../locales/sr-LATN-RS/translation.toml | 4 ++-- .../public/locales/sv-SE/translation.toml | 2 +- .../public/locales/th-TH/translation.toml | 6 +++--- .../public/locales/tr-TR/translation.toml | 2 +- .../public/locales/uk-UA/translation.toml | 4 ++-- .../public/locales/vi-VN/translation.toml | 4 ++-- .../public/locales/zh-BO/translation.toml | 4 ++-- .../public/locales/zh-CN/translation.toml | 2 +- .../public/locales/zh-TW/translation.toml | 2 +- .../onboarding/slides/ServerLicenseSlide.tsx | 2 +- 41 files changed, 86 insertions(+), 86 deletions(-) diff --git a/frontend/public/locales/ar-AR/translation.toml b/frontend/public/locales/ar-AR/translation.toml index 4c437dbf4..4376a1dea 100644 --- a/frontend/public/locales/ar-AR/translation.toml +++ b/frontend/public/locales/ar-AR/translation.toml @@ -3828,8 +3828,8 @@ title = "التحليلات" description = "تساعدنا هذه الملفات على فهم كيفية استخدام أدواتنا، كي نركّز على بناء الميزات الأكثر قيمة لمجتمعنا. كن مطمئنًا—‏Stirling PDF لا يمكنه ولن يتتبع محتوى المستندات التي تعمل عليها." [cookieBanner.services] -posthog = "PostHog Analytics" -scarf = "Scarf Pixel" +posthog = "تحليلات PostHog" +scarf = "Scarf بكسل" [removeMetadata] submit = "إزالة البيانات الوصفية" @@ -5177,7 +5177,7 @@ upgrade = "الترقية الآن →" freeTitle = "ترخيص الخادم" overLimitTitle = "مطلوب ترخيص خادم" overLimitBody = "ترخيصنا يسمح حتى {{freeTierLimit}} مستخدمين مجاناً لكل خادم. لديك {{overLimitUserCopy}} مستخدمي Stirling. للمتابعة دون انقطاع، ارقَ إلى خطة خادم Stirling - مقاعد غير محدودة، تحرير نصوص PDF، وتحكم إداري كامل مقابل $99/خادم/شهرياً." -freeBody = "ترخيص Open-Core لدينا يسمح حتى {{freeTierLimit}} مستخدمين مجاناً لكل خادم. للتوسع بسلاسة والحصول على وصول مبكر إلى أداة تحرير نصوص PDF الجديدة، نوصي بخطة خادم Stirling - تحرير كامل ومقاعد غير محدودة مقابل $99/خادم/شهرياً." +freeBody = "يتيح ترخيصنا Open-Core ما يصل إلى {{freeTierLimit}} مستخدمًا مجانًا لكل خادم. للتوسع دون انقطاع، نوصي بخطة Stirling Server - مقاعد غير محدودة ودعم SSO مقابل $99/server/mo." [onboarding.desktopInstall] title = "تنزيل" diff --git a/frontend/public/locales/az-AZ/translation.toml b/frontend/public/locales/az-AZ/translation.toml index 092b0fda7..fe13e4d0f 100644 --- a/frontend/public/locales/az-AZ/translation.toml +++ b/frontend/public/locales/az-AZ/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "İndi yüksəlt →" freeTitle = "Server lisenziyası" overLimitTitle = "Server lisenziyası tələb olunur" overLimitBody = "Lisenziyalaşmamız hər server üçün pulsuz olaraq maksimum {{freeTierLimit}} istifadəçiyə icazə verir. Sizdə {{overLimitUserCopy}} Stirling istifadəçisi var. Fasiləsiz davam etmək üçün Stirling Server planına yüksəldin - limitsiz yerlər, PDF mətn redaktəsi və tam admin nəzarəti cəmi $99/server/ay." -freeBody = "Bizim Open-Core lisenziyası hər server üçün pulsuz olaraq maksimum {{freeTierLimit}} istifadəçiyə icazə verir. Fasiləsiz miqyaslanmaq və yeni PDF mətn redaktəsi alətimizə erkən çıxış əldə etmək üçün Stirling Server planını tövsiyə edirik — tam redaktə və limitsiz yerlər $99/server/ay." +freeBody = "Bizim Open-Core lisenziyalaşdırmamız hər server üçün pulsuz olaraq ən çox {{freeTierLimit}} istifadəçiyə icazə verir. Fasiləsiz miqyaslama üçün Stirling Server planını tövsiyə edirik - limitsiz yerlərSSO dəstəyi $99/server/ay." [onboarding.desktopInstall] title = "Yüklə" diff --git a/frontend/public/locales/bg-BG/translation.toml b/frontend/public/locales/bg-BG/translation.toml index 13ae29767..adc099082 100644 --- a/frontend/public/locales/bg-BG/translation.toml +++ b/frontend/public/locales/bg-BG/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Надградете сега →" freeTitle = "Лиценз за сървър" overLimitTitle = "Необходим е лиценз за сървър" overLimitBody = "Нашият лиценз позволява до {{freeTierLimit}} безплатни потребители на сървър. Имате {{overLimitUserCopy}} потребители на Stirling. За да продължите без прекъсвания, надградете до плана Stirling Server – неограничени места, редакция на PDF текст и пълен админ контрол за $99/сървър/месец." -freeBody = "Нашият Open-Core лиценз позволява до {{freeTierLimit}} безплатни потребители на сървър. За да мащабирате без прекъсвания и да получите ранен достъп до нашия нов инструмент за редакция на PDF текст, препоръчваме плана Stirling Server – пълно редактиране и неограничени места за $99/сървър/месец." +freeBody = "Нашият лицензен модел Open-Core позволява до {{freeTierLimit}} потребители безплатно на сървър. За безпрепятствено мащабиране препоръчваме плана Stirling Server - неограничени места и поддръжка на SSO за $99/server/mo." [onboarding.desktopInstall] title = "Изтегляне" diff --git a/frontend/public/locales/ca-CA/translation.toml b/frontend/public/locales/ca-CA/translation.toml index 85090e5a5..d521141f4 100644 --- a/frontend/public/locales/ca-CA/translation.toml +++ b/frontend/public/locales/ca-CA/translation.toml @@ -352,7 +352,7 @@ teams = "Equips" title = "Configuració" systemSettings = "Configuració del sistema" features = "Funcions" -endpoints = "Endpoints" +endpoints = "Punts finals" database = "Base de dades" advanced = "Avançat" @@ -561,7 +561,7 @@ totalEndpoints = "Total d'endpoints" totalVisits = "Total de visites" showing = "Mostrant" selectedVisits = "Visites seleccionades" -endpoint = "Endpoint" +endpoint = "Punt final" visits = "Visites" percentage = "Percentatge" loading = "Carregant..." @@ -4366,7 +4366,7 @@ features = "Banderes de funcions" processing = "Processament" [admin.settings.advanced.endpoints] -label = "Endpoints" +label = "Punts finals" manage = "Gestiona els endpoints de l'API" description = "La gestió d'endpoints es configura via YAML. Consulteu la documentació per a detalls sobre com habilitar/deshabilitar endpoints específics." @@ -5177,7 +5177,7 @@ upgrade = "Actualitza ara →" freeTitle = "Llicència del servidor" overLimitTitle = "Cal una llicència de servidor" overLimitBody = "La nostra llicència permet fins a {{freeTierLimit}} usuaris gratuïts per servidor. Tens {{overLimitUserCopy}} usuaris de Stirling. Per continuar sense interrupcions, actualitza al pla Stirling Server: seients il·limitats, edició de text de PDF i control d'administració complet per 99 $/servidor/mes." -freeBody = "La nostra llicència Open-Core permet fins a {{freeTierLimit}} usuaris gratuïts per servidor. Per escalar sense interrupcions i obtenir accés anticipat a la nova eina d'edició de text PDF, recomanem el pla Stirling Server: edició completa i seients il·limitats per 99 $/servidor/mes." +freeBody = "La nostra llicència Open-Core permet fins a {{freeTierLimit}} usuaris gratuïts per servidor. Per escalar sense interrupcions, recomanem el pla Stirling Server - places il·limitades i suport SSO per $99/servidor/mes." [onboarding.desktopInstall] title = "Baixa" @@ -5754,7 +5754,7 @@ title = "Gràfic d'ús dels endpoints" [usage.table] title = "Estadístiques detallades" -endpoint = "Endpoint" +endpoint = "Punt final" visits = "Visites" percentage = "Percentatge" noData = "No hi ha dades disponibles" diff --git a/frontend/public/locales/cs-CZ/translation.toml b/frontend/public/locales/cs-CZ/translation.toml index d1ffd5b7f..4d580e79a 100644 --- a/frontend/public/locales/cs-CZ/translation.toml +++ b/frontend/public/locales/cs-CZ/translation.toml @@ -4176,7 +4176,7 @@ description = "Sledovat akce uživatelů a systémové události pro compliance [admin.settings.security.audit.level] label = "Úroveň auditu" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=VYPNUTO, 1=ZÁKLADNÍ, 2=STANDARDNÍ, 3=PODROBNÝ" [admin.settings.security.audit.retentionDays] label = "Doba uchování auditů (dny)" @@ -5177,7 +5177,7 @@ upgrade = "Upgradovat nyní →" freeTitle = "Serverová licence" overLimitTitle = "Vyžadována serverová licence" overLimitBody = "Naše licencování umožňuje až {{freeTierLimit}} uživatelů zdarma na server. Máte {{overLimitUserCopy}} uživatelů Stirling. Pro nepřerušené používání přejděte na plán Stirling Server – neomezený počet míst, úpravy textu PDF a plná správa za 99 $/server/měsíc." -freeBody = "Naše licencování Open-Core umožňuje až {{freeTierLimit}} uživatelů zdarma na server. Pro nepřerušený růst a přednostní přístup k našemu novému nástroji pro úpravu textu PDF doporučujeme plán Stirling Server – plné úpravy a neomezený počet míst za 99 $/server/měsíc." +freeBody = "Naše licencování Open-Core umožňuje až {{freeTierLimit}} uživatelů zdarma na server. Pro nepřerušované škálování doporučujeme plán Stirling Server - neomezený počet míst a podpora SSO za $99/server/měs." [onboarding.desktopInstall] title = "Stáhnout" diff --git a/frontend/public/locales/da-DK/translation.toml b/frontend/public/locales/da-DK/translation.toml index d3a6cca28..9ed522f5a 100644 --- a/frontend/public/locales/da-DK/translation.toml +++ b/frontend/public/locales/da-DK/translation.toml @@ -1221,9 +1221,9 @@ pdfaDigitalSignatureWarning = "PDF'en indeholder en digital signatur. Dette vil fileFormat = "Filformat" wordDoc = "Word-dokument" wordDocExt = "Word-dokument (.docx)" -odtExt = "OpenDocument Text (.odt)" +odtExt = "OpenDocument-tekst (.odt)" pptExt = "PowerPoint (.pptx)" -odpExt = "OpenDocument Presentation (.odp)" +odpExt = "OpenDocument-præsentation (.odp)" txtExt = "Almindelig tekst (.txt)" rtfExt = "Rich Text Format (.rtf)" selectedFiles = "Valgte filer" @@ -3790,7 +3790,7 @@ version = "Nuværende udgivelse" title = "API-dokumentation" header = "API-dokumentation" desc = "Se og test Stirling PDF API-endpoints" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,dokumentation,swagger,endepunkter,udvikling" [cookieBanner.popUp] title = "Sådan bruger vi cookies" @@ -5177,7 +5177,7 @@ upgrade = "Opgrader nu →" freeTitle = "Serverlicens" overLimitTitle = "Serverlicens påkrævet" overLimitBody = "Vores licens tillader op til {{freeTierLimit}} brugere gratis pr. server. Du har {{overLimitUserCopy}} Stirling-brugere. For at fortsætte uden afbrydelser skal du opgradere til Stirling Server-abonnementet – ubegrænsede pladser, PDF-tekstredigering og fuld admin-kontrol for $99/server/md." -freeBody = "Vores Open-Core-licens tillader op til {{freeTierLimit}} brugere gratis pr. server. For at skalere uden afbrydelser og få tidlig adgang til vores nye PDF-tekstredigeringsværktøj anbefaler vi Stirling Server-planen – fuld redigering og ubegrænsede pladser for $99/server/md." +freeBody = "Vores Open-Core-licens tillader op til {{freeTierLimit}} brugere gratis pr. server. For at skalere uden afbrydelser anbefaler vi Stirling Server-planen – ubegrænsede pladser og SSO-understøttelse for $99/server/md." [onboarding.desktopInstall] title = "Download" diff --git a/frontend/public/locales/de-DE/translation.toml b/frontend/public/locales/de-DE/translation.toml index 70dcf86b2..29dc3bf9f 100644 --- a/frontend/public/locales/de-DE/translation.toml +++ b/frontend/public/locales/de-DE/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Jetzt upgraden →" freeTitle = "Server-Lizenz" overLimitTitle = "Server-Lizenz erforderlich" overLimitBody = "Unsere Lizenz erlaubt bis zu {{freeTierLimit}} Nutzer pro Server kostenlos. Sie haben {{overLimitUserCopy}} Stirling-Nutzer. Um ohne Unterbrechung fortzufahren, upgraden Sie auf den Stirling-Server-Plan – unbegrenzte Plätze, PDF-Textbearbeitung und volle Admin-Kontrolle für $99/Server/Monat." -freeBody = "Unsere Open-Core-Lizenz erlaubt bis zu {{freeTierLimit}} Nutzer pro Server kostenlos. Für unterbrechungsfreies Skalieren und frühen Zugriff auf unser neues PDF-Textbearbeitungs-Tool empfehlen wir den Stirling-Server-Plan – volle Bearbeitung und unbegrenzte Plätze für $99/Server/Monat." +freeBody = "Unsere Open-Core-Lizenz erlaubt bis zu {{freeTierLimit}} Nutzern pro Server kostenlos. Um unterbrechungsfrei zu skalieren, empfehlen wir den Stirling Server-Plan - unbegrenzte Plätze und SSO-Unterstützung für $99/Server/Monat." [onboarding.desktopInstall] title = "Download" diff --git a/frontend/public/locales/el-GR/translation.toml b/frontend/public/locales/el-GR/translation.toml index d3cf4c860..5b47558c7 100644 --- a/frontend/public/locales/el-GR/translation.toml +++ b/frontend/public/locales/el-GR/translation.toml @@ -3790,7 +3790,7 @@ version = "Τρέχουσα έκδοση" title = "Τεκμηρίωση API" header = "Τεκμηρίωση API" desc = "Προβάλετε και δοκιμάστε τα endpoints του Stirling PDF API" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,τεκμηρίωση,swagger,τελικά σημεία,ανάπτυξη" [cookieBanner.popUp] title = "Πώς χρησιμοποιούμε τα cookies" @@ -4482,7 +4482,7 @@ label = "Ενεργοποίηση προσκλήσεων μέσω email" description = "Να επιτρέπεται στους διαχειριστές να προσκαλούν χρήστες μέσω email με αυτόματα παραγόμενους κωδικούς" [admin.settings.mail.frontendUrl] -label = "Frontend URL" +label = "URL front-end" description = "Βασικό URL για το frontend (π.χ. https://pdf.example.com). Χρησιμοποιείται για τη δημιουργία συνδέσμων πρόσκλησης στα email. Αφήστε κενό για χρήση του backend URL." [admin.settings.legal] @@ -5177,7 +5177,7 @@ upgrade = "Αναβάθμιση τώρα →" freeTitle = "Άδεια διακομιστή" overLimitTitle = "Απαιτείται άδεια διακομιστή" overLimitBody = "Η αδειοδότηση μας επιτρέπει έως {{freeTierLimit}} χρήστες δωρεάν ανά διακομιστή. Έχετε {{overLimitUserCopy}} χρήστες Stirling. Για να συνεχίσετε χωρίς διακοπές, αναβαθμίστε στο πλάνο Stirling Server - απεριόριστες θέσεις, επεξεργασία κειμένου PDF και πλήρης έλεγχος διαχειριστή για $99/server/μήνα." -freeBody = "Η αδειοδότηση Open-Core μας επιτρέπει έως {{freeTierLimit}} χρήστες δωρεάν ανά διακομιστή. Για απρόσκοπτη κλιμάκωση και έγκαιρη πρόσβαση στο νέο εργαλείο επεξεργασίας κειμένου PDF, προτείνουμε το πλάνο Stirling Server - πλήρης επεξεργασία και απεριόριστες θέσεις για $99/server/μήνα." +freeBody = "Οι άδειες χρήσης Open-Core επιτρέπουν έως και {{freeTierLimit}} χρήστες δωρεάν ανά διακομιστή. Για απρόσκοπτη κλιμάκωση, προτείνουμε το πλάνο Stirling Server - απεριόριστες θέσεις και υποστήριξη SSO με $99/διακομιστή/μήνα." [onboarding.desktopInstall] title = "Λήψη" diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index c60df3a85..fcdcf592f 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -5263,7 +5263,7 @@ upgrade = "Upgrade now →" freeTitle = "Server License" overLimitTitle = "Server License Needed" overLimitBody = "Our licensing permits up to {{freeTierLimit}} users for free per server. You have {{overLimitUserCopy}} Stirling users. To continue uninterrupted, upgrade to the Stirling Server plan - unlimited seats, PDF text editing, and full admin control for $99/server/mo." -freeBody = "Our Open-Core licensing permits up to {{freeTierLimit}} users for free per server. To scale uninterrupted and get early access to our new PDF text editing tool, we recommend the Stirling Server plan - full editing and unlimited seats for $99/server/mo." +freeBody = "Our Open-Core licensing permits up to {{freeTierLimit}} users for free per server. To scale uninterrupted, we recommend the Stirling Server plan - unlimited seats and SSO support for $99/server/mo." [onboarding.desktopInstall] title = "Download" diff --git a/frontend/public/locales/es-ES/translation.toml b/frontend/public/locales/es-ES/translation.toml index 437c0ac2c..fb0969a1a 100644 --- a/frontend/public/locales/es-ES/translation.toml +++ b/frontend/public/locales/es-ES/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Actualizar ahora →" freeTitle = "Licencia del servidor" overLimitTitle = "Se necesita licencia de servidor" overLimitBody = "Nuestra licencia permite hasta {{freeTierLimit}} usuarios gratis por servidor. Tiene {{overLimitUserCopy}} usuarios de Stirling. Para continuar sin interrupciones, actualice al plan Stirling Server: plazas ilimitadas, edición de texto PDF y control total de administración por 99 $/servidor/mes." -freeBody = "Nuestra licencia Open-Core permite hasta {{freeTierLimit}} usuarios gratis por servidor. Para escalar sin interrupciones y obtener acceso anticipado a nuestra nueva herramienta de edición de texto PDF, recomendamos el plan Stirling Server: edición completa y plazas ilimitadas por 99 $/servidor/mes." +freeBody = "Nuestra licencia Open-Core permite hasta {{freeTierLimit}} usuarios gratis por servidor. Para escalar sin interrupciones, recomendamos el plan Stirling Server - plazas ilimitadas y soporte SSO por $99/servidor/mes." [onboarding.desktopInstall] title = "Descargar" diff --git a/frontend/public/locales/eu-ES/translation.toml b/frontend/public/locales/eu-ES/translation.toml index 3fc897147..96dfbfcdc 100644 --- a/frontend/public/locales/eu-ES/translation.toml +++ b/frontend/public/locales/eu-ES/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Eguneratu orain →" freeTitle = "Zerbitzari-lizentzia" overLimitTitle = "Beharrezkoa da zerbitzari-lizentzia" overLimitBody = "Gure lizentziak baimentzen ditu {{freeTierLimit}} erabiltzaile doan zerbitzari bakoitzeko. {{overLimitUserCopy}} Stirling erabiltzaile dituzu. Jarraitzeko etenik gabe, eguneratu Stirling Server planera - eserleku mugagabeak, PDF testu-edizioa, eta admin kontrol osoa $99/zerbitzari/hilean." -freeBody = "Gure Open-Core lizentziak {{freeTierLimit}} erabiltzaile arte baimentzen ditu doan zerbitzari bakoitzeko. Etenik gabe eskalatzeko eta gure PDF testu-edizio tresna berrirako sarbide goiztiarra lortzeko, gomendatzen dugu Stirling Server plana - edizio osoa eta eserleku mugagabeak $99/zerbitzari/hilean." +freeBody = "Gure Open-Core lizentziak zerbitzari bakoitzeko doan gehienez {{freeTierLimit}} erabiltzaile baimentzen ditu. Etenik gabe eskalatzeko, Stirling Server plana gomendatzen dugu - eserleku mugagabeak eta SSO euskarria $99/server/mo." [onboarding.desktopInstall] title = "Deskargatu" diff --git a/frontend/public/locales/fa-IR/translation.toml b/frontend/public/locales/fa-IR/translation.toml index 8102a9c7c..26bebba53 100644 --- a/frontend/public/locales/fa-IR/translation.toml +++ b/frontend/public/locales/fa-IR/translation.toml @@ -4258,11 +4258,11 @@ label = "URL صادرکننده" description = "Issuer URL ارائه‌دهنده OAuth2" [admin.settings.connections.oauth2.clientId] -label = "Client ID" +label = "شناسهٔ کلاینت" description = "Client ID مربوط به OAuth2 از ارائه‌دهنده شما" [admin.settings.connections.oauth2.clientSecret] -label = "Client Secret" +label = "راز کلاینت" description = "Client Secret مربوط به OAuth2 از ارائه‌دهنده شما" [admin.settings.connections.oauth2.useAsUsername] @@ -4293,7 +4293,7 @@ label = "ارائه‌دهنده" description = "نام ارائه‌دهنده SAML2" [admin.settings.connections.saml2.registrationId] -label = "Registration ID" +label = "شناسهٔ ثبت‌نام" description = "شناسه ثبت‌نام SAML2" [admin.settings.connections.saml2.autoCreateUser] @@ -5177,7 +5177,7 @@ upgrade = "همین حالا ارتقا بده →" freeTitle = "لایسنس سرور" overLimitTitle = "نیاز به لایسنس سرور" overLimitBody = "مجوز ما تا {{freeTierLimit}} کاربر رایگان به‌ازای هر سرور را مجاز می‌داند. شما {{overLimitUserCopy}} کاربر Stirling دارید. برای ادامه بدون وقفه، به پلن Stirling Server ارتقا دهید - صندلی نامحدود، ویرایش متن PDF و کنترل کامل ادمین با 99$ به‌ازای هر سرور در ماه." -freeBody = "مجوز Open-Core ما تا {{freeTierLimit}} کاربر رایگان به‌ازای هر سرور را مجاز می‌داند. برای مقیاس‌پذیری بدون وقفه و دسترسی زودهنگام به ابزار ویرایش متن PDF جدیدمان، پلن Stirling Server را پیشنهاد می‌کنیم - ویرایش کامل و صندلی نامحدود با 99$ به‌ازای هر سرور در ماه." +freeBody = "مجوز Open-Core ما به‌ازای هر سرور اجازهٔ استفادهٔ رایگان برای حداکثر {{freeTierLimit}} کاربر را می‌دهد. برای مقیاس‌دهی بدون وقفه، طرح Stirling Server را توصیه می‌کنیم - تعداد کاربران نامحدود و پشتیبانی از SSO با $99/سرور/ماه." [onboarding.desktopInstall] title = "دانلود" diff --git a/frontend/public/locales/fr-FR/translation.toml b/frontend/public/locales/fr-FR/translation.toml index 5ae44d3f7..1f413e927 100644 --- a/frontend/public/locales/fr-FR/translation.toml +++ b/frontend/public/locales/fr-FR/translation.toml @@ -363,7 +363,7 @@ connections = "Connexions" [settings.licensingAnalytics] title = "Licences et analyses" -plan = "Plan" +plan = "Forfait" audit = "Audit" usageAnalytics = "Analyses d'utilisation" @@ -4550,7 +4550,7 @@ successMessage = "Fichier de licence téléversé et activé avec succès. Aucun title = "Licence active" file = "Source: Fichier de licence ({{path}})" key = "Source: Clé de licence" -type = "Type: {{type}}" +type = "Type : {{type}}" noInput = "Veuillez fournir une clé de licence ou téléverser un fichier de certificat" success = "Succès" @@ -5177,7 +5177,7 @@ upgrade = "Mettre à niveau maintenant →" freeTitle = "Licence serveur" overLimitTitle = "Licence serveur requise" overLimitBody = "Notre licence autorise jusqu’à {{freeTierLimit}} utilisateurs gratuits par serveur. Vous avez {{overLimitUserCopy}} utilisateurs Stirling. Pour continuer sans interruption, passez au plan Stirling Server — places illimitées, édition de texte PDF et contrôle d’administration complet pour 99 $/serveur/mois." -freeBody = "Notre licence Open-Core autorise jusqu’à {{freeTierLimit}} utilisateurs gratuits par serveur. Pour évoluer sans interruption et accéder en avant-première à notre nouvel outil d’édition de texte PDF, nous recommandons le plan Stirling Server — édition complète et places illimitées pour 99 $/serveur/mois." +freeBody = "Notre régime de licence Open-Core autorise jusqu'à {{freeTierLimit}} utilisateurs gratuitement par serveur. Pour évoluer sans interruption, nous recommandons le forfait Stirling Server - places illimitées et prise en charge du SSO pour 99 $/serveur/mois." [onboarding.desktopInstall] title = "Télécharger" @@ -5892,7 +5892,7 @@ paragraph = "Page de paragraphe" sparse = "Texte clairsemé" [pdfTextEditor.groupingMode] -auto = "Auto" +auto = "Automatique" paragraph = "Paragraphe" singleLine = "Ligne unique" diff --git a/frontend/public/locales/ga-IE/translation.toml b/frontend/public/locales/ga-IE/translation.toml index 254c8578a..77d27e093 100644 --- a/frontend/public/locales/ga-IE/translation.toml +++ b/frontend/public/locales/ga-IE/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Uasghrádaigh anois →" freeTitle = "Ceadúnas Freastalaí" overLimitTitle = "Ceadúnas Freastalaí de dhíth" overLimitBody = "Ceadaíonn ár gceadúnú suas le {{freeTierLimit}} úsáideoir in aisce in aghaidh freastalaí. Tá {{overLimitUserCopy}} úsáideoir Stirling agat. Chun leanúint gan bhriseadh, uasghrádaigh go plean Freastalaí Stirling - suíocháin neamhtheoranta, eagarthóireacht téacs PDF, agus lánrialú riaracháin ar $99/freastalaí/mí." -freeBody = "Ceadaíonn ár gceadúnú Open-Core suas le {{freeTierLimit}} úsáideoir in aisce in aghaidh freastalaí. Chun méadú gan bhriseadh agus rochtain luath a fháil ar ár uirlis eagarthóireachta téacs PDF nua, molaimid Plean Freastalaí Stirling - eagarthóireacht iomlán agus suíocháin neamhtheoranta ar $99/freastalaí/mí." +freeBody = "Ceadaíonn ár gceadúnú Open-Core suas le {{freeTierLimit}} úsáideoirí saor in aisce in aghaidh an fhreastalaí. Chun scálú gan bhriseadh, molaimid an plean Stirling Server - suíocháin neamhtheoranta agus tacaíocht SSO ar $99/server/mo." [onboarding.desktopInstall] title = "Íoslódáil" @@ -5333,8 +5333,8 @@ emailDisabled = "Teastaíonn cumraíocht SMTP agus mail.enableInvites=true sna s [workspace.people.license] users = "úsáideoirí" availableSlots = "Áiteanna Ar Fáil" -grandfathered = "Grandfathered" -grandfatheredShort = "{{count}} grandfathered" +grandfathered = "Ceadaithe roimhe seo" +grandfatheredShort = "{{count}} ceadaithe roimhe seo" fromLicense = "ón gceadúnas" slotsAvailable = "{{count}} áit(í) úsáideora ar fáil" noSlotsAvailable = "Níl aon áiteanna ar fáil" diff --git a/frontend/public/locales/hi-IN/translation.toml b/frontend/public/locales/hi-IN/translation.toml index c569e48ba..011479c9f 100644 --- a/frontend/public/locales/hi-IN/translation.toml +++ b/frontend/public/locales/hi-IN/translation.toml @@ -834,7 +834,7 @@ title = "PDF हस्ताक्षर सत्यापित करें" desc = "PDF दस्तावेजों में डिजिटल हस्ताक्षर और प्रमाणपत्रों को सत्यापित करें" [home.swagger] -tags = "API,documentation,test" +tags = "API,दस्तावेज़ीकरण,परीक्षण" title = "API दस्तावेज़ीकरण" desc = "API दस्तावेज़ देखें और एंडपॉइंट टेस्ट करें" @@ -883,7 +883,7 @@ title = "रंग बदलें/उलटें" desc = "PDF दस्तावेज़ों में रंगों को प्रतिस्थापित या उलटें" [home.devApi] -tags = "API,development,documentation" +tags = "API,विकास,दस्तावेज़ीकरण" title = "API" desc = "API दस्तावेज़ के लिए लिंक" @@ -922,7 +922,7 @@ title = "PDF टेक्स्ट एडिटर" desc = "PDF फ़ाइलों के भीतर मौजूदा टेक्स्ट और इमेज संपादित करें" [home.addText] -tags = "text,annotation,label" +tags = "पाठ,टिप्पणी,लेबल" title = "टेक्स्ट जोड़ें" desc = "अपने PDF में कहीं भी कस्टम टेक्स्ट जोड़ें" @@ -1840,7 +1840,7 @@ title = "उन्नत" tags = "कम्प्रेस,छोटा,छोटा" [unlockPDFForms] -tags = "remove,delete,form,field,readonly" +tags = "हटाएं,मिटाएं,फॉर्म,फ़ील्ड,रीड-ओनली" title = "फॉर्म फ़ील्ड से Read-Only हटाएं" header = "PDF फॉर्म अनलॉक करें" submit = "Remove" @@ -2747,7 +2747,7 @@ submit = "जमा करें" failed = "मल्टी-पृष्ठ लेआउट बनाते समय त्रुटि हुई।" [bookletImposition] -tags = "booklet,imposition,printing,binding,folding,signature" +tags = "बुकलेट,इम्पोज़िशन,प्रिंटिंग,बाइंडिंग,फोल्डिंग,सिग्नेचर" title = "बुकलेट इम्पोज़िशन" header = "बुकलेट इम्पोज़िशन" submit = "बुकलेट बनाएँ" @@ -2846,7 +2846,7 @@ scaleFactor = "एक पृष्ठ का ज़ूम स्तर (क् submit = "जमा करें" [adjustPageScale] -tags = "resize,modify,dimension,adapt" +tags = "आकार बदलें,संशोधित करें,आयाम,अनुकूलित करें" title = "पृष्ठ स्केल समायोजित करें" header = "पृष्ठ स्केल समायोजित करें" submit = "पृष्ठ स्केल समायोजित करें" @@ -3396,7 +3396,7 @@ certHint = "कस्टम ट्रस्ट स्रोत के विर title = "सत्यापन सेटिंग्स" [replaceColor] -tags = "Replace Colour,Page operations,Back end,server side" +tags = "रंग बदलें,पृष्ठ संचालन,Back end,server side" [replaceColor.labels] settings = "सेटिंग्स" @@ -3790,7 +3790,7 @@ version = "वर्तमान रिलीज़" title = "API दस्तावेज़ीकरण" header = "API दस्तावेज़ीकरण" desc = "Stirling PDF API एंडपॉइंट्स देखें और परीक्षण करें" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,दस्तावेज़ीकरण,swagger,endpoints,विकास" [cookieBanner.popUp] title = "हम कुकीज़ का उपयोग कैसे करते हैं" @@ -5177,7 +5177,7 @@ upgrade = "अभी अपग्रेड करें →" freeTitle = "सर्वर लाइसेंस" overLimitTitle = "सर्वर लाइसेंस आवश्यक" overLimitBody = "हमारा लाइसेंसिंग प्रति सर्वर अधिकतम {{freeTierLimit}} उपयोगकर्ताओं को मुफ्त अनुमति देता है। आपके पास {{overLimitUserCopy}} Stirling उपयोगकर्ता हैं। बिना बाधा के जारी रखने के लिए, Stirling Server प्लान में अपग्रेड करें - अनलिमिटेड सीट्स, PDF टेक्स्ट एडिटिंग, और पूर्ण एडमिन नियंत्रण $99/server/mo में।" -freeBody = "हमारा Open-Core लाइसेंसिंग प्रति सर्वर अधिकतम {{freeTierLimit}} उपयोगकर्ताओं को मुफ्त अनुमति देता है। बिना बाधा स्केल करने और हमारे नए PDF टेक्स्ट एडिटिंग टूल की प्रारंभिक पहुँच पाने के लिए हम Stirling Server प्लान की सलाह देते हैं - पूर्ण एडिटिंग और अनलिमिटेड सीट्स $99/server/mo में।" +freeBody = "हमारा Open-Core लाइसेंसिंग प्रति सर्वर अधिकतम {{freeTierLimit}} उपयोगकर्ताओं को निःशुल्क अनुमति देता है। बिना रुकावट स्केल करने के लिए, हम Stirling Server प्लान की अनुशंसा करते हैं - असीमित सीटें और SSO समर्थन $99/सर्वर/माह पर।" [onboarding.desktopInstall] title = "डाउनलोड" @@ -6005,7 +6005,7 @@ insufficientPermissions = "आपके पास यह क्रिया क [addText] title = "टेक्स्ट जोड़ें" header = "PDFs में टेक्स्ट जोड़ें" -tags = "text,annotation,label" +tags = "पाठ,टिप्पणी,लेबल" applySignatures = "टेक्स्ट लागू करें" [addText.text] diff --git a/frontend/public/locales/hr-HR/translation.toml b/frontend/public/locales/hr-HR/translation.toml index 3e68d5ce5..4a97a3558 100644 --- a/frontend/public/locales/hr-HR/translation.toml +++ b/frontend/public/locales/hr-HR/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Nadogradi odmah →" freeTitle = "Poslužiteljska licenca" overLimitTitle = "Potrebna poslužiteljska licenca" overLimitBody = "Naše licenciranje dopušta do {{freeTierLimit}} korisnika besplatno po poslužitelju. Imate {{overLimitUserCopy}} Stirling korisnika. Za nesmetan nastavak, nadogradite na Stirling Server plan - neograničena mjesta, uređivanje teksta u PDF-u i puna admin kontrola za $99/server/mo." -freeBody = "Naše Open-Core licenciranje dopušta do {{freeTierLimit}} korisnika besplatno po poslužitelju. Za nesmetano skaliranje i rani pristup našem novom alatu za uređivanje teksta u PDF-u, preporučujemo Stirling Server plan - potpuno uređivanje i neograničena mjesta za $99/server/mo." +freeBody = "Naše licenciranje Open-Core omogućuje do {{freeTierLimit}} korisnika besplatno po poslužitelju. Za neometano skaliranje preporučujemo Stirling Server plan - neograničena mjesta i podrška za SSO za $99/poslužitelj/mj." [onboarding.desktopInstall] title = "Preuzimanje" diff --git a/frontend/public/locales/hu-HU/translation.toml b/frontend/public/locales/hu-HU/translation.toml index 5c70e8a2e..edbacf219 100644 --- a/frontend/public/locales/hu-HU/translation.toml +++ b/frontend/public/locales/hu-HU/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Frissítés most →" freeTitle = "Szerverlicenc" overLimitTitle = "Szerverlicenc szükséges" overLimitBody = "Licencelésünk szerverenként legfeljebb {{freeTierLimit}} felhasználót enged ingyen. Önnek {{overLimitUserCopy}} Stirling felhasználója van. A zavartalan használathoz váltson a Stirling Server csomagra – korlátlan hely, PDF szövegszerkesztés és teljes adminisztrátori vezérlés $99/szerver/hó áron." -freeBody = "Az Open-Core licencelésünk szerverenként legfeljebb {{freeTierLimit}} felhasználót enged ingyen. A zavartalan bővüléshez és az új PDF szövegszerkesztő eszköz korai eléréséhez a Stirling Server csomagot ajánljuk – teljes szerkesztés és korlátlan hely $99/szerver/hó áron." +freeBody = "A Open-Core licencünk szerverenként legfeljebb {{freeTierLimit}} felhasználót engedélyez ingyenesen. A zökkenőmentes skálázáshoz a Stirling Server csomagot ajánljuk - korlátlan felhasználó és SSO támogatás $99/szerver/hó." [onboarding.desktopInstall] title = "Letöltés" diff --git a/frontend/public/locales/id-ID/translation.toml b/frontend/public/locales/id-ID/translation.toml index 78fff6735..d260fe551 100644 --- a/frontend/public/locales/id-ID/translation.toml +++ b/frontend/public/locales/id-ID/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Upgrade sekarang →" freeTitle = "Lisensi Server" overLimitTitle = "Perlu Lisensi Server" overLimitBody = "Lisensi kami mengizinkan hingga {{freeTierLimit}} pengguna gratis per server. Anda memiliki {{overLimitUserCopy}} pengguna Stirling. Untuk terus berjalan tanpa gangguan, upgrade ke paket Stirling Server - kursi tanpa batas, pengeditan teks PDF, dan kontrol admin penuh seharga $99/server/bulan." -freeBody = "Lisensi Open-Core kami mengizinkan hingga {{freeTierLimit}} pengguna gratis per server. Untuk skala tanpa hambatan dan mendapatkan akses awal ke alat pengeditan teks PDF baru kami, kami sarankan paket Stirling Server - pengeditan penuh dan kursi tanpa batas seharga $99/server/bulan." +freeBody = "Lisensi Open-Core kami mengizinkan hingga {{freeTierLimit}} pengguna gratis per server. Untuk meningkatkan skala tanpa gangguan, kami merekomendasikan paket Stirling Server - pengguna tanpa batas dan dukungan SSO seharga $99/server/mo." [onboarding.desktopInstall] title = "Unduh" @@ -5433,7 +5433,7 @@ hideComparison = "Sembunyikan Perbandingan Fitur" featureComparison = "Perbandingan Fitur" from = "Mulai" perMonth = "/bulan" -perSeat = "/seat" +perSeat = "/pengguna" withServer = "+ Paket Server" licensedSeats = "Berlisensi: {{count}} seat" includedInCurrent = "Termasuk dalam Paket Anda" @@ -5594,7 +5594,7 @@ modalTitle = "Mulai - {{planName}}" title = "Pilih Periode Penagihan" savingsNote = "Hemat {{percent}}% dengan penagihan tahunan" basePrice = "Harga Dasar" -seatPrice = "Per Seat" +seatPrice = "Per Pengguna" totalForSeats = "Total ({{count}} seat)" selectMonthly = "Pilih Bulanan" selectYearly = "Pilih Tahunan" diff --git a/frontend/public/locales/it-IT/translation.toml b/frontend/public/locales/it-IT/translation.toml index 806cfa571..79f6e0e7a 100644 --- a/frontend/public/locales/it-IT/translation.toml +++ b/frontend/public/locales/it-IT/translation.toml @@ -4176,7 +4176,7 @@ description = "Traccia azioni degli utenti ed eventi di sistema per conformità [admin.settings.security.audit.level] label = "Livello audit" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=SPENTO, 1=BASE, 2=STANDARD, 3=DETTAGLIATO" [admin.settings.security.audit.retentionDays] label = "Conservazione audit (giorni)" @@ -5177,7 +5177,7 @@ upgrade = "Esegui upgrade ora →" freeTitle = "Licenza server" overLimitTitle = "Licenza server necessaria" overLimitBody = "La nostra licenza consente fino a {{freeTierLimit}} utenti gratuiti per server. Hai {{overLimitUserCopy}} utenti Stirling. Per continuare senza interruzioni, esegui l'upgrade al piano Stirling Server - posti illimitati, modifica del testo PDF e pieno controllo admin a $99/server/mese." -freeBody = "La nostra licenza Open-Core consente fino a {{freeTierLimit}} utenti gratuiti per server. Per scalare senza interruzioni e ottenere accesso anticipato al nuovo strumento di modifica testo PDF, consigliamo il piano Stirling Server - modifica completa e posti illimitati a $99/server/mese." +freeBody = "La nostra licenza Open-Core consente fino a {{freeTierLimit}} utenti gratuiti per server. Per scalare senza interruzioni, consigliamo il piano Stirling Server - posti illimitati e supporto SSO a $99/server/mese." [onboarding.desktopInstall] title = "Download" diff --git a/frontend/public/locales/ja-JP/translation.toml b/frontend/public/locales/ja-JP/translation.toml index bceb6975f..67a4affb3 100644 --- a/frontend/public/locales/ja-JP/translation.toml +++ b/frontend/public/locales/ja-JP/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "今すぐアップグレード →" freeTitle = "サーバーライセンス" overLimitTitle = "サーバーライセンスが必要です" overLimitBody = "当社のライセンスでは、サーバーごとに {{freeTierLimit}} ユーザーまで無料です。現在 {{overLimitUserCopy}} の Stirling ユーザーがいます。中断なく利用を続けるには、Stirling Server プランにアップグレードしてください - 無制限席数、PDF テキスト編集、完全な管理機能が $99/サーバー/月 です。" -freeBody = "当社の オープンコア ライセンスでは、サーバーごとに最大 {{freeTierLimit}} ユーザーまで無料です。中断なく拡張し、新しい PDF テキスト編集ツール に早期アクセスするには、Stirling Server プランをお勧めします。完全編集と 無制限席数 が $99/サーバー/月 です。" +freeBody = "当社のOpen-Coreライセンスでは、サーバーごとに最大{{freeTierLimit}}ユーザーまで無料でご利用いただけます。中断なくスケールするには、Stirling Server プランをおすすめします - 無制限の席数SSO サポートで $99/サーバー/月。" [onboarding.desktopInstall] title = "ダウンロード" diff --git a/frontend/public/locales/ko-KR/translation.toml b/frontend/public/locales/ko-KR/translation.toml index 3dcd0c237..63f274a25 100644 --- a/frontend/public/locales/ko-KR/translation.toml +++ b/frontend/public/locales/ko-KR/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "지금 업그레이드 →" freeTitle = "서버 라이선스" overLimitTitle = "서버 라이선스 필요" overLimitBody = "당사의 라이선스는 서버당 무료로 최대 {{freeTierLimit}}명의 사용자를 허용합니다. 현재 {{overLimitUserCopy}}명의 Stirling 사용자가 있습니다. 중단 없이 계속 사용하려면 Stirling Server 플랜으로 업그레이드하세요 - 무제한 좌석, PDF 텍스트 편집, 전체 관리자 제어 제공, $99/서버/월." -freeBody = "당사의 Open-Core 라이선스는 서버당 최대 {{freeTierLimit}}명의 사용자를 무료로 허용합니다. 중단 없이 확장하고 새로운 PDF 텍스트 편집 도구에 조기 액세스하려면 Stirling Server 플랜을 권장합니다 - 전체 편집과 무제한 좌석을 $99/서버/월에 제공합니다." +freeBody = "당사의 Open-Core 라이선스는 서버당 최대 {{freeTierLimit}}명의 사용자를 무료로 허용합니다. 중단 없이 확장하려면 Stirling Server 플랜을 권장합니다 - 무제한 좌석SSO 지원, $99/서버/월." [onboarding.desktopInstall] title = "다운로드" diff --git a/frontend/public/locales/ml-ML/translation.toml b/frontend/public/locales/ml-ML/translation.toml index 92106dd93..4cfe475f0 100644 --- a/frontend/public/locales/ml-ML/translation.toml +++ b/frontend/public/locales/ml-ML/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "ഇപ്പോൾ അപ്‌ഗ്രേഡ് ചെയ്യു freeTitle = "സെർവർ ലൈസൻസ്" overLimitTitle = "സെർവർ ലൈസൻസ് ആവശ്യമാണ്" overLimitBody = "ഞങ്ങളുടെ ലൈസൻസിംഗ് ഓരോ സെർവർക്കും പരമാവധി {{freeTierLimit}} ഉപയോക്താക്കളെ സൗജന്യമായി അനുവദിക്കുന്നു. നിങ്ങള്ക്ക് {{overLimitUserCopy}} Stirling ഉപയോക്താക്കളുണ്ട്. തടസ്സമില്ലാതെ തുടരാൻ, Stirling Server പ്ലാനിലേക്ക് അപ്‌ഗ്രേഡ് ചെയ്യുക - unlimited seats, PDF text editing, പൂർണ്ണ അഡ്മിൻ നിയന്ത്രണം, $99/server/mo." -freeBody = "ഞങ്ങളുടെ Open-Core ലൈസൻസിംഗ് ഓരോ സെർവർക്കും പരമാവധി {{freeTierLimit}} ഉപയോക്താക്കളെ സൗജന്യമായി അനുവദിക്കുന്നു. തടസ്സമില്ലാതെ സ്കെയിൽ ചെയ്യാനും പുതിയ PDF text editing tool ന് മുൻകാല ആക്സസ് നേടാനും, Stirling Server പ്ലാൻ ഞങ്ങൾ ശുപാർശ ചെയ്യുന്നു - പൂർണ്ണ എഡിറ്റിംഗും unlimited seats ഉം $99/server/mo." +freeBody = "ഞങ്ങളുടെ Open-Core ലൈസൻസിംഗ് ഓരോ സെർവർക്കും പരമാവധി {{freeTierLimit}} ഉപയോക്താക്കളെ സൗജന്യമായി അനുവദിക്കുന്നു. തടസ്സമില്ലാതെ സ്‌കെയിൽ ചെയ്യാൻ, ഞങ്ങൾ Stirling Server പ്ലാൻ ശുപാർശ ചെയ്യുന്നു - പരിമിതിയില്ലാത്ത സീറ്റുകൾയും SSO പിന്തുണയും for $99/server/mo." [onboarding.desktopInstall] title = "ഡൗൺലോഡ്" diff --git a/frontend/public/locales/nl-NL/translation.toml b/frontend/public/locales/nl-NL/translation.toml index b5c5cf99b..97532092b 100644 --- a/frontend/public/locales/nl-NL/translation.toml +++ b/frontend/public/locales/nl-NL/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Nu upgraden →" freeTitle = "Serverlicentie" overLimitTitle = "Serverlicentie vereist" overLimitBody = "Onze licentie staat tot {{freeTierLimit}} gebruikers gratis per server toe. Je hebt {{overLimitUserCopy}} Stirling-gebruikers. Om zonder onderbreking door te gaan, upgrade naar het Stirling Server-plan - onbeperkte plaatsen, PDF-tekstbewerking en volledige admincontrole voor $99/server/maand." -freeBody = "Onze Open-Core-licentie staat tot {{freeTierLimit}} gebruikers gratis per server toe. Om ononderbroken te schalen en vroege toegang te krijgen tot onze nieuwe PDF-tekstbewerkingstool, raden we het Stirling Server-plan aan - volledige bewerking en onbeperkte plaatsen voor $99/server/maand." +freeBody = "Onze Open-Core-licentie staat tot {{freeTierLimit}} gebruikers per server gratis toe. Om ononderbroken op te schalen, raden we het Stirling Server-abonnement aan - onbeperkte plaatsen en SSO-ondersteuning voor $99/server/maand." [onboarding.desktopInstall] title = "Downloaden" diff --git a/frontend/public/locales/no-NB/translation.toml b/frontend/public/locales/no-NB/translation.toml index 7dc8b431a..eaf40fae0 100644 --- a/frontend/public/locales/no-NB/translation.toml +++ b/frontend/public/locales/no-NB/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Oppgrader nå →" freeTitle = "Serverlisens" overLimitTitle = "Serverlisens kreves" overLimitBody = "Lisensieringen vår tillater opptil {{freeTierLimit}} brukere gratis per server. Du har {{overLimitUserCopy}} Stirling-brukere. For å fortsette uten avbrudd, oppgrader til Stirling Server-planen – ubegrensede plasser, PDF-tekstredigering og full admin-kontroll for $99/server/mnd." -freeBody = "Vår Open-Core-lisensiering tillater opptil {{freeTierLimit}} brukere gratis per server. For å skalere uten avbrudd og få tidlig tilgang til vårt nye PDF-tekstredigeringsverktøy, anbefaler vi Stirling Server-planen – full redigering og ubegrensede plasser for $99/server/mnd." +freeBody = "Vår Open-Core-lisensiering tillater opptil {{freeTierLimit}} brukere gratis per server. For å skalere uten avbrudd anbefaler vi Stirling Server-planen - ubegrensede plasser og SSO-støtte for $99/server/mnd." [onboarding.desktopInstall] title = "Last ned" diff --git a/frontend/public/locales/pl-PL/translation.toml b/frontend/public/locales/pl-PL/translation.toml index e652c88d2..ebf36642a 100644 --- a/frontend/public/locales/pl-PL/translation.toml +++ b/frontend/public/locales/pl-PL/translation.toml @@ -568,7 +568,7 @@ loading = "Ładowanie..." failedToLoad = "Nie udało się załadować danych punktów końcowych. Spróbuj odświeżyć." home = "Strona główna" login = "Logowanie" -top = "Top" +top = "Najlepsze" numberOfVisits = "Liczba wizyt" visitsTooltip = "Wizyty: {0} ({1}% całości)" retry = "Spróbuj ponownie" @@ -1225,7 +1225,7 @@ odtExt = "Tekst OpenDocument (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "Prezentacja OpenDocument (.odp)" txtExt = "Tekst niesformatowany (.txt)" -rtfExt = "Rich Text Format (.rtf)" +rtfExt = "Format RTF (.rtf)" selectedFiles = "Wybrane pliki" noFileSelected = "Nie wybrano pliku. Użyj panelu plików, aby dodać pliki." convertFiles = "Konwertuj pliki" @@ -5177,7 +5177,7 @@ upgrade = "Ulepsz teraz →" freeTitle = "Licencja serwera" overLimitTitle = "Wymagana licencja serwera" overLimitBody = "Nasza licencja pozwala na maks. {{freeTierLimit}} użytkowników bez opłat na serwer. Masz {{overLimitUserCopy}} użytkowników Stirling. Aby kontynuować bez przerw, przejdź na plan Stirling Server – nielimitowane miejsca, edycja tekstu PDF i pełna kontrola administracyjna za 99 USD/serwer/mies." -freeBody = "Nasza licencja Open-Core pozwala na maks. {{freeTierLimit}} użytkowników bez opłat na serwer. Aby skalować bez przerw i uzyskać wczesny dostęp do nowego narzędzia edycji tekstu PDF, polecamy plan Stirling Server – pełna edycja i nielimitowane miejsca za 99 USD/serwer/mies." +freeBody = "Nasza licencja Open-Core pozwala na maksymalnie {{freeTierLimit}} użytkowników bezpłatnie na serwer. Aby skalować bez zakłóceń, zalecamy plan Stirling Server - nielimitowana liczba miejsc i obsługa SSO za $99/serwer/mies." [onboarding.desktopInstall] title = "Pobierz" @@ -5586,7 +5586,7 @@ emailInvalid = "Wpisz poprawny adres e‑mail" title = "Podaj e‑mail" description = "Użyjemy go do wysłania klucza licencyjnego i rachunków." emailLabel = "Adres e‑mail" -emailPlaceholder = "your@email.com" +emailPlaceholder = "twoj@email.com" continue = "Kontynuuj" modalTitle = "Zaczynamy – {{planName}}" diff --git a/frontend/public/locales/pt-BR/translation.toml b/frontend/public/locales/pt-BR/translation.toml index baaa4215b..9a6d58d67 100644 --- a/frontend/public/locales/pt-BR/translation.toml +++ b/frontend/public/locales/pt-BR/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Fazer upgrade agora →" freeTitle = "Licença do servidor" overLimitTitle = "Necessária licença do servidor" overLimitBody = "Nossa licença permite até {{freeTierLimit}} usuários grátis por servidor. Você tem {{overLimitUserCopy}} usuários do Stirling. Para continuar sem interrupções, faça upgrade para o plano Stirling Server - assentos ilimitados, edição de texto em PDF e controle total de admin por US$ 99/servidor/mês." -freeBody = "Nossa licença Open-Core permite até {{freeTierLimit}} usuários grátis por servidor. Para escalar sem interrupções e ter acesso antecipado à nova ferramenta de edição de texto em PDF, recomendamos o plano Stirling Server - edição completa e assentos ilimitados por US$ 99/servidor/mês." +freeBody = "Nossa licença Open-Core permite até {{freeTierLimit}} usuários gratuitos por servidor. Para escalar sem interrupções, recomendamos o plano Stirling Server - assentos ilimitados e suporte a SSO por US$ 99/servidor/mês." [onboarding.desktopInstall] title = "Download" @@ -5586,7 +5586,7 @@ emailInvalid = "Digite um endereço de e-mail válido" title = "Informe seu e-mail" description = "Usaremos isso para enviar sua chave de licença e recibos." emailLabel = "Endereço de e-mail" -emailPlaceholder = "your@email.com" +emailPlaceholder = "seu@email.com" continue = "Continuar" modalTitle = "Começar - {{planName}}" diff --git a/frontend/public/locales/pt-PT/translation.toml b/frontend/public/locales/pt-PT/translation.toml index 0691f5f35..49a02e369 100644 --- a/frontend/public/locales/pt-PT/translation.toml +++ b/frontend/public/locales/pt-PT/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Atualizar agora →" freeTitle = "Licença do servidor" overLimitTitle = "É necessária licença de servidor" overLimitBody = "A nossa licença permite até {{freeTierLimit}} utilizadores gratuitos por servidor. Tem {{overLimitUserCopy}} utilizadores Stirling. Para continuar sem interrupções, atualize para o plano Stirling Server - lugares ilimitados, edição de texto em PDF e controlo total de administração por $99/servidor/mês." -freeBody = "A nossa licença Open-Core permite até {{freeTierLimit}} utilizadores gratuitos por servidor. Para escalar sem interrupções e obter acesso antecipado à nossa nova ferramenta de edição de texto PDF, recomendamos o plano Stirling Server - edição completa e lugares ilimitados por $99/servidor/mês." +freeBody = "O nosso licenciamento Open-Core permite até {{freeTierLimit}} utilizadores gratuitos por servidor. Para escalar sem interrupções, recomendamos o plano Stirling Server - lugares ilimitados e suporte SSO por $99/servidor/mês." [onboarding.desktopInstall] title = "Transferir" diff --git a/frontend/public/locales/ro-RO/translation.toml b/frontend/public/locales/ro-RO/translation.toml index c323b3354..005cc5f21 100644 --- a/frontend/public/locales/ro-RO/translation.toml +++ b/frontend/public/locales/ro-RO/translation.toml @@ -3948,7 +3948,7 @@ files = "Fișiere" activity = "Jurnal" help = "Ajutor" account = "Cont" -config = "Config" +config = "Configurare" settings = "Setări" adminSettings = "Setări admin" allTools = "All Tools" @@ -4176,7 +4176,7 @@ description = "Urmărește acțiunile utilizatorilor și evenimentele de sistem [admin.settings.security.audit.level] label = "Nivel audit" -description = "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE" +description = "0=OPRIT, 1=DE BAZĂ, 2=STANDARD, 3=DETALIAT" [admin.settings.security.audit.retentionDays] label = "Păstrare audit (zile)" @@ -5177,7 +5177,7 @@ upgrade = "Fă upgrade acum →" freeTitle = "Licență server" overLimitTitle = "Necesită licență de server" overLimitBody = "Politica noastră de licențiere permite până la {{freeTierLimit}} utilizatori gratuit per server. Ai {{overLimitUserCopy}} utilizatori Stirling. Pentru a continua fără întreruperi, fă upgrade la planul Stirling Server - locuri nelimitate, editare text PDF și control complet de admin pentru $99/server/lună." -freeBody = "Licențierea noastră Open-Core permite până la {{freeTierLimit}} utilizatori gratuit per server. Pentru a scala fără întreruperi și a primi acces timpuriu la noul nostru instrument de editare text PDF, recomandăm planul Stirling Server - editare completă și locuri nelimitate pentru $99/server/lună." +freeBody = "Licențierea noastră Open-Core permite până la {{freeTierLimit}} utilizatori gratuit per server. Pentru scalare fără întreruperi, recomandăm planul Stirling Server - locuri nelimitate și suport SSO pentru $99/server/lună." [onboarding.desktopInstall] title = "Descărcare" @@ -5984,7 +5984,7 @@ warnings = "Avertizări" suggestions = "Note" currentPageFonts = "Fonturi pe această pagină" allFonts = "Toate fonturile" -fallback = "fallback" +fallback = "rezervă" missing = "lipsește" perfectMessage = "Toate fonturile pot fi redate perfect." warningMessage = "Unele fonturi pot să nu fie redate corect." diff --git a/frontend/public/locales/ru-RU/translation.toml b/frontend/public/locales/ru-RU/translation.toml index b72009fa6..69f8f6712 100644 --- a/frontend/public/locales/ru-RU/translation.toml +++ b/frontend/public/locales/ru-RU/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Обновить сейчас →" freeTitle = "Серверная лицензия" overLimitTitle = "Требуется серверная лицензия" overLimitBody = "Наша лицензия допускает до {{freeTierLimit}} пользователей бесплатно на сервер. У вас {{overLimitUserCopy}} пользователей Stirling. Чтобы продолжить без перебоев, перейдите на тариф Stirling Server — неограниченные места, редактирование текста в PDF и полный админ‑контроль за $99/server/mo." -freeBody = "Наша лицензия Open-Core допускает до {{freeTierLimit}} пользователей бесплатно на сервер. Чтобы масштабироваться без ограничений и раньше получить доступ к новому инструменту редактирования текста в PDF, рекомендуем тариф Stirling Server — полный редактор и неограниченные места за $99/server/mo." +freeBody = "Наша лицензия Open-Core позволяет бесплатно использовать до {{freeTierLimit}} пользователей на сервер. Для бесшовного масштабирования мы рекомендуем план Stirling Server - неограниченное число мест и поддержка SSO за $99/сервер/мес." [onboarding.desktopInstall] title = "Скачать" diff --git a/frontend/public/locales/sk-SK/translation.toml b/frontend/public/locales/sk-SK/translation.toml index 183112a67..7a196d699 100644 --- a/frontend/public/locales/sk-SK/translation.toml +++ b/frontend/public/locales/sk-SK/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Upgradovať teraz →" freeTitle = "Serverová licencia" overLimitTitle = "Potrebná serverová licencia" overLimitBody = "Naše licencovanie povoľuje až {{freeTierLimit}} používateľov zdarma na server. Máte {{overLimitUserCopy}} používateľov Stirling. Ak chcete pokračovať bez prerušenia, prejdite na plán Stirling Server - neobmedzené miesta, úpravy textu PDF a plná správa pre $99/server/mo." -freeBody = "Naše licencovanie Open-Core povoľuje až {{freeTierLimit}} používateľov zdarma na server. Ak chcete škálovať bez prerušenia a získať skorý prístup k nášmu novému nástroju na úpravu textu PDF, odporúčame plán Stirling Server - plné úpravy a neobmedzené miesta za $99/server/mo." +freeBody = "Naše licencovanie Open-Core umožňuje až {{freeTierLimit}} používateľov zadarmo na server. Na plynulé škálovanie odporúčame plán Stirling Server - neobmedzený počet používateľov a podporu SSO za $99/server/mes." [onboarding.desktopInstall] title = "Stiahnuť" diff --git a/frontend/public/locales/sl-SI/translation.toml b/frontend/public/locales/sl-SI/translation.toml index f8bc31492..8233f0d42 100644 --- a/frontend/public/locales/sl-SI/translation.toml +++ b/frontend/public/locales/sl-SI/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Nadgradi zdaj →" freeTitle = "Licenca strežnika" overLimitTitle = "Potrebna licenca strežnika" overLimitBody = "Naše licenciranje brezplačno omogoča do {{freeTierLimit}} uporabnikov na strežnik. Imate {{overLimitUserCopy}} uporabnikov Stirling. Za nemoteno uporabo nadgradite na načrt Stirling Server – neomejena mesta, urejanje besedila PDF in popoln skrbniški nadzor za $99/strežnik/mesec." -freeBody = "Naše licenciranje Open-Core brezplačno omogoča do {{freeTierLimit}} uporabnikov na strežnik. Za nemoteno rast in zgodnji dostop do našega novega orodja za urejanje besedila PDF priporočamo načrt Stirling Server – polno urejanje in neomejena mesta za $99/strežnik/mesec." +freeBody = "Naše licenciranje Open-Core omogoča do {{freeTierLimit}} uporabnikov brezplačno na strežnik. Za nemoteno skaliranje priporočamo načrt Stirling Server - neomejena mesta in podpora za SSO za $99/strežnik/mesec." [onboarding.desktopInstall] title = "Prenesi" diff --git a/frontend/public/locales/sr-LATN-RS/translation.toml b/frontend/public/locales/sr-LATN-RS/translation.toml index fd433c25e..17ce6f340 100644 --- a/frontend/public/locales/sr-LATN-RS/translation.toml +++ b/frontend/public/locales/sr-LATN-RS/translation.toml @@ -1225,7 +1225,7 @@ odtExt = "OpenDocument tekst (.odt)" pptExt = "PowerPoint (.pptx)" odpExt = "OpenDocument prezentacija (.odp)" txtExt = "Običan tekst (.txt)" -rtfExt = "Rich Text Format (.rtf)" +rtfExt = "Format obogaćenog teksta (.rtf)" selectedFiles = "Izabrane datoteke" noFileSelected = "Nije izabrana nijedna datoteka. Koristite panel datoteka da dodate datoteke." convertFiles = "Konvertuj datoteke" @@ -5177,7 +5177,7 @@ upgrade = "Nadogradite sada →" freeTitle = "Serverska licenca" overLimitTitle = "Potrebna serverska licenca" overLimitBody = "Naše licenciranje dozvoljava do {{freeTierLimit}} korisnika besplatno po serveru. Imate {{overLimitUserCopy}} Stirling korisnika. Da nastavite bez prekida, pređite na Stirling Server plan - neograničena mesta, uređivanje PDF teksta i puna admin kontrola za $99/server/mes." -freeBody = "Naše Open-Core licenciranje dozvoljava do {{freeTierLimit}} korisnika besplatno po serveru. Da se bez prekida skalirate i dobijete rani pristup našem novom alatu za uređivanje PDF teksta, preporučujemo Stirling Server plan - puno uređivanje i neograničena mesta za $99/server/mes." +freeBody = "Naše licenciranje Open-Core dozvoljava do {{freeTierLimit}} korisnika besplatno po serveru. Za neometano skaliranje, preporučujemo plan Stirling Server - neograničena mesta i SSO podrška za $99/server/mo." [onboarding.desktopInstall] title = "Preuzmi" diff --git a/frontend/public/locales/sv-SE/translation.toml b/frontend/public/locales/sv-SE/translation.toml index 5c100fe78..ccafc28b9 100644 --- a/frontend/public/locales/sv-SE/translation.toml +++ b/frontend/public/locales/sv-SE/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Uppgradera nu →" freeTitle = "Serverlicens" overLimitTitle = "Serverlicens krävs" overLimitBody = "Vår licensiering tillåter upp till {{freeTierLimit}} användare gratis per server. Du har {{overLimitUserCopy}} Stirling-användare. För att fortsätta utan avbrott, uppgradera till Stirling Server-planen - obegränsade platser, PDF-textredigering och full adminkontroll för $99/server/mån." -freeBody = "Vår Open-Core-licens tillåter upp till {{freeTierLimit}} användare gratis per server. För att skala utan avbrott och få tidig åtkomst till vårt nya PDF-textredigeringsverktyg rekommenderar vi Stirling Server-planen - full redigering och obegränsade platser för $99/server/mån." +freeBody = "Vår Open-Core-licens tillåter upp till {{freeTierLimit}} användare gratis per server. För att skala utan avbrott rekommenderar vi Stirling Server plan - obegränsat antal platser och SSO-stöd för $99/server/månad." [onboarding.desktopInstall] title = "Ladda ner" diff --git a/frontend/public/locales/th-TH/translation.toml b/frontend/public/locales/th-TH/translation.toml index 386b699f8..ce03b4a13 100644 --- a/frontend/public/locales/th-TH/translation.toml +++ b/frontend/public/locales/th-TH/translation.toml @@ -1221,9 +1221,9 @@ pdfaDigitalSignatureWarning = "PDF มีลายเซ็นดิจิทั fileFormat = "รูปแบบไฟล์" wordDoc = "เอกสาร Word" wordDocExt = "เอกสาร Word (.docx)" -odtExt = "OpenDocument Text (.odt)" +odtExt = "ข้อความ OpenDocument (.odt)" pptExt = "PowerPoint (.pptx)" -odpExt = "OpenDocument Presentation (.odp)" +odpExt = "งานนำเสนอ OpenDocument (.odp)" txtExt = "ข้อความล้วน (.txt)" rtfExt = "Rich Text Format (.rtf)" selectedFiles = "ไฟล์ที่เลือก" @@ -5177,7 +5177,7 @@ upgrade = "อัปเกรดเลย →" freeTitle = "ไลเซนส์เซิร์ฟเวอร์" overLimitTitle = "ต้องใช้ไลเซนส์เซิร์ฟเวอร์" overLimitBody = "สิทธิ์การใช้งานของเรารองรับผู้ใช้ได้ฟรีสูงสุด {{freeTierLimit}} คนต่อเซิร์ฟเวอร์ ขณะนี้คุณมีผู้ใช้ Stirling {{overLimitUserCopy}} คน เพื่อใช้งานต่อเนื่อง โปรดอัปเกรดเป็นแพ็กเกจ Stirling Server - ที่นั่งไม่จำกัด แก้ไขข้อความ PDF และควบคุมแอดมินเต็มรูปแบบ ราคา $99/ต่อเซิร์ฟเวอร์/เดือน" -freeBody = "ไลเซนส์แบบ Open-Core ของเรารองรับผู้ใช้ได้ฟรีสูงสุด {{freeTierLimit}} คนต่อเซิร์ฟเวอร์ เพื่อขยายการใช้งานได้ต่อเนื่องและเข้าถึง เครื่องมือแก้ไขข้อความ PDF ล่วงหน้า เราแนะนำแพ็กเกจ Stirling Server - แก้ไขได้เต็มรูปแบบและ ที่นั่งไม่จำกัด ราคา $99/ต่อเซิร์ฟเวอร์/เดือน" +freeBody = "สัญญาอนุญาตแบบ Open-Core ของเราอนุญาตให้ใช้งานฟรีได้สูงสุด {{freeTierLimit}} ผู้ใช้ต่อเซิร์ฟเวอร์หนึ่งเครื่อง เพื่อขยายการใช้งานอย่างต่อเนื่อง เราขอแนะนำแผน Stirling Server - ที่นั่งไม่จำกัด และ รองรับ SSO ในราคา $99/เซิร์ฟเวอร์/เดือน" [onboarding.desktopInstall] title = "ดาวน์โหลด" diff --git a/frontend/public/locales/tr-TR/translation.toml b/frontend/public/locales/tr-TR/translation.toml index 52d46d7fe..342452574 100644 --- a/frontend/public/locales/tr-TR/translation.toml +++ b/frontend/public/locales/tr-TR/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "Şimdi yükselt →" freeTitle = "Sunucu Lisansı" overLimitTitle = "Sunucu Lisansı Gerekli" overLimitBody = "Lisansımız, sunucu başına ücretsiz olarak en fazla {{freeTierLimit}} kullanıcıya izin verir. {{overLimitUserCopy}} Stirling kullanıcınız var. Kesintisiz devam etmek için Stirling Server planına yükseltin - sınırsız koltuk, PDF metin düzenleme ve tam yönetici kontrolü $99/server/ay." -freeBody = "Open-Core lisansımız, sunucu başına ücretsiz olarak en fazla {{freeTierLimit}} kullanıcıya izin verir. Kesintisiz ölçeklemek ve yeni PDF metin düzenleme aracımıza erken erişim almak için Stirling Server planını öneririz - tam düzenleme ve sınırsız koltuk $99/server/ay." +freeBody = "Open-Core lisanslamamız, sunucu başına en fazla {{freeTierLimit}} kullanıcıya ücretsiz izin verir. Kesintisiz ölçeklendirme için Stirling Server planını öneririz - sınırsız kullanıcı ve SSO desteği için $99/sunucu/ay." [onboarding.desktopInstall] title = "İndir" diff --git a/frontend/public/locales/uk-UA/translation.toml b/frontend/public/locales/uk-UA/translation.toml index b261dc02a..a23945990 100644 --- a/frontend/public/locales/uk-UA/translation.toml +++ b/frontend/public/locales/uk-UA/translation.toml @@ -3790,7 +3790,7 @@ version = "Текущий релиз" title = "Документація API" header = "Документація API" desc = "Переглядайте та тестуйте кінцеві точки API Stirling PDF" -tags = "api,documentation,swagger,endpoints,development" +tags = "api,документація,swagger,кінцеві точки,розробка" [cookieBanner.popUp] title = "Як ми використовуємо файли cookie" @@ -5177,7 +5177,7 @@ upgrade = "Оновити зараз →" freeTitle = "Ліцензія сервера" overLimitTitle = "Потрібна ліцензія сервера" overLimitBody = "Наша ліцензія дозволяє до {{freeTierLimit}} користувачів безкоштовно на сервер. У вас {{overLimitUserCopy}} користувачів Stirling. Щоб працювати без перерв, перейдіть на план Stirling Server — необмежена кількість місць, редагування тексту PDF та повний адмін-контроль за $99/server/mo." -freeBody = "Наша Open-Core ліцензія дозволяє до {{freeTierLimit}} користувачів безкоштовно на сервер. Щоб масштабуватися безперервно та отримати ранній доступ до нового інструмента редагування тексту PDF, рекомендуємо план Stirling Server — повне редагування та необмежена кількість місць за $99/server/mo." +freeBody = "Наша ліцензія Open-Core дозволяє до {{freeTierLimit}} користувачів безкоштовно на сервер. Щоб масштабуватися без перерв, рекомендуємо план Stirling Server — необмежена кількість місць і підтримка SSO за $99/сервер/міс." [onboarding.desktopInstall] title = "Завантажити" diff --git a/frontend/public/locales/vi-VN/translation.toml b/frontend/public/locales/vi-VN/translation.toml index 7e9860bb9..b73cc807d 100644 --- a/frontend/public/locales/vi-VN/translation.toml +++ b/frontend/public/locales/vi-VN/translation.toml @@ -301,7 +301,7 @@ saveSettings = "Lưu cài đặt thao tác" pipelineNamePrompt = "Nhập tên pipeline tại đây" selectOperation = "Chọn thao tác" addOperationButton = "Thêm thao tác" -pipelineHeader = "Pipeline:" +pipelineHeader = "Chuỗi xử lý:" saveButton = "Tải xuống" validateButton = "Xác thực" @@ -5177,7 +5177,7 @@ upgrade = "Nâng cấp ngay →" freeTitle = "Giấy phép Server" overLimitTitle = "Cần giấy phép Server" overLimitBody = "Giấy phép của chúng tôi cho phép tối đa {{freeTierLimit}} người dùng miễn phí mỗi server. Bạn có {{overLimitUserCopy}} người dùng Stirling. Để tiếp tục không gián đoạn, hãy nâng cấp lên gói Stirling Server - số ghế không giới hạn, chỉnh sửa văn bản PDF và toàn quyền quản trị với $99/server/tháng." -freeBody = "Giấy phép Open-Core của chúng tôi cho phép tối đa {{freeTierLimit}} người dùng miễn phí mỗi server. Để mở rộng không gián đoạn và truy cập sớm công cụ chỉnh sửa văn bản PDF mới, chúng tôi khuyến nghị gói Stirling Server - chỉnh sửa đầy đủ và số ghế không giới hạn với $99/server/tháng." +freeBody = "Giấy phép Open-Core của chúng tôi cho phép tối đa {{freeTierLimit}} người dùng miễn phí cho mỗi máy chủ. Để mở rộng quy mô liền mạch, chúng tôi khuyến nghị gói Stirling Server - số lượng người dùng không giới hạnhỗ trợ SSO với giá $99/máy chủ/tháng." [onboarding.desktopInstall] title = "Tải xuống" diff --git a/frontend/public/locales/zh-BO/translation.toml b/frontend/public/locales/zh-BO/translation.toml index 847e423d0..e14cbeb6b 100644 --- a/frontend/public/locales/zh-BO/translation.toml +++ b/frontend/public/locales/zh-BO/translation.toml @@ -1181,7 +1181,7 @@ selectFilesPlaceholder = "在主视图中选择文件以开始" settings = "设置" conversionCompleted = "转换完成" results = "结果" -defaultFilename = "converted_file" +defaultFilename = "已转换_文件" conversionResults = "转换结果" convertFrom = "从以下格式转换" convertTo = "转换为" @@ -5177,7 +5177,7 @@ upgrade = "立即升级 →" freeTitle = "服务器许可证" overLimitTitle = "需要服务器许可证" overLimitBody = "我们的许可每台服务器最多允许 {{freeTierLimit}} 名用户免费使用。您共有 {{overLimitUserCopy}} 名 Stirling 用户。为避免中断,请升级到 Stirling Server 方案 - 无限席位、PDF 文本编辑,以及每台服务器 $99/月 的完整管理员控制。" -freeBody = "我们的 开源内核(Open-Core) 许可允许每台服务器最多 {{freeTierLimit}} 名用户免费使用。为顺畅扩展并抢先体验全新的 PDF 文本编辑工具,我们推荐 Stirling Server 方案 - 完整编辑与 无限席位,$99/服务器/月。" +freeBody = "我们的Open-Core许可允许每台服务器最多{{freeTierLimit}}名用户免费使用。为实现不中断的扩展,我们推荐 Stirling Server 方案 - 不限席位并提供SSO 支持,$99/服务器/月。" [onboarding.desktopInstall] title = "下载" diff --git a/frontend/public/locales/zh-CN/translation.toml b/frontend/public/locales/zh-CN/translation.toml index fed6c1d60..f79e74cab 100644 --- a/frontend/public/locales/zh-CN/translation.toml +++ b/frontend/public/locales/zh-CN/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "立即升级 →" freeTitle = "服务器许可证" overLimitTitle = "需要服务器许可证" overLimitBody = "我们的许可允许每台服务器最多免费 {{freeTierLimit}} 名用户。您有 {{overLimitUserCopy}} 名 Stirling 用户。为不间断使用,请升级至 Stirling Server 方案 - 无限席位、PDF 文本编辑,以及 $99/server/mo 的完整管理员控制。" -freeBody = "我们的 Open-Core 许可允许每台服务器最多免费 {{freeTierLimit}} 名用户。为无缝扩展并抢先体验全新的 PDF 文本编辑工具,推荐 Stirling Server 方案 - 完整编辑与 无限席位,$99/server/mo。" +freeBody = "我们的 Open-Core 许可允许每台服务器最多 {{freeTierLimit}} 名用户免费使用。为实现不间断扩展,我们推荐 Stirling Server 方案 - 无限席位SSO 支持,$99/server/mo." [onboarding.desktopInstall] title = "下载" diff --git a/frontend/public/locales/zh-TW/translation.toml b/frontend/public/locales/zh-TW/translation.toml index 8b2f97b5d..6dff92e6a 100644 --- a/frontend/public/locales/zh-TW/translation.toml +++ b/frontend/public/locales/zh-TW/translation.toml @@ -5177,7 +5177,7 @@ upgrade = "立即升級 →" freeTitle = "伺服器授權" overLimitTitle = "需要伺服器授權" overLimitBody = "我們的授權允許每台伺服器最多 {{freeTierLimit}} 位使用者免費使用。你有 {{overLimitUserCopy}} 位 Stirling 使用者。若要不中斷使用,請升級至 Stirling Server 方案 - 不限席次、PDF 文字編輯,以及完整管理控制,每台伺服器 $99/月。" -freeBody = "我們的 Open-Core 授權允許每台伺服器最多 {{freeTierLimit}} 位使用者免費使用。若要無縫擴充並搶先體驗全新的 PDF 文字編輯工具,建議升級至 Stirling Server 方案 - 完整編輯與 不限席次,每台伺服器 $99/月。" +freeBody = "我們的 Open-Core 授權允許每台伺服器最多 {{freeTierLimit}} 位使用者免費使用。若要無縫擴充,我們建議選用 Stirling Server 方案 - 不限席次SSO 支援,每伺服器每月 $99。" [onboarding.desktopInstall] title = "下載" diff --git a/frontend/src/core/components/onboarding/slides/ServerLicenseSlide.tsx b/frontend/src/core/components/onboarding/slides/ServerLicenseSlide.tsx index f118d2ac0..3da69103b 100644 --- a/frontend/src/core/components/onboarding/slides/ServerLicenseSlide.tsx +++ b/frontend/src/core/components/onboarding/slides/ServerLicenseSlide.tsx @@ -39,7 +39,7 @@ export default function ServerLicenseSlide({ licenseNotice }: ServerLicenseSlide components={{ strong: , }} - defaults="Our Open-Core licensing permits up to {{freeTierLimit}} users for free per server. To scale uninterrupted and get early access to our new PDF text editing tool, we recommend the Stirling Server plan - full editing and unlimited seats for $99/server/mo." + defaults="Our Open-Core licensing permits up to {{freeTierLimit}} users for free per server. To scale uninterrupted, we recommend the Stirling Server plan - unlimited seats and SSO support for $99/server/mo." /> ); From fa4d2bc09a2331d6e77297d79187061ef1335e37 Mon Sep 17 00:00:00 2001 From: James Brunton Date: Tue, 9 Dec 2025 11:43:18 +0000 Subject: [PATCH 21/56] Fix path to sample file in tour (#5186) # Description of Changes Fix path to sample file in tour --- frontend/src/core/contexts/TourOrchestrationContext.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/core/contexts/TourOrchestrationContext.tsx b/frontend/src/core/contexts/TourOrchestrationContext.tsx index f8364ba5c..a594e8322 100644 --- a/frontend/src/core/contexts/TourOrchestrationContext.tsx +++ b/frontend/src/core/contexts/TourOrchestrationContext.tsx @@ -1,4 +1,5 @@ import React, { createContext, useContext, useCallback, useRef } from 'react'; +import { BASE_PATH } from '@app/constants/app'; import { useFileHandler } from '@app/hooks/useFileHandler'; import { useFilesModalContext } from '@app/contexts/FilesModalContext'; import { useNavigationActions } from '@app/contexts/NavigationContext'; @@ -110,7 +111,7 @@ export const TourOrchestrationProvider: React.FC<{ children: React.ReactNode }> const loadSampleFile = useCallback(async () => { try { - const response = await fetch('samples/Sample.pdf'); + const response = await fetch(`${BASE_PATH}/samples/Sample.pdf`); const blob = await response.blob(); const file = new File([blob], 'Sample.pdf', { type: 'application/pdf' }); From c980ee10c0c8bebc77d6dc4a1432ffde09bfe488 Mon Sep 17 00:00:00 2001 From: James Brunton Date: Tue, 9 Dec 2025 11:45:01 +0000 Subject: [PATCH 22/56] Backport fixes from SaaS (#5187) # Description of Changes - Add new skeleton loader style type (block - nothing's currently using it but it might as well be available) - Make Dev API overridable (and set to the new docs that actually work while Swagger docs don't work properly) --- .../core/components/shared/SkeletonLoader.tsx | 67 +++++++++++++------ frontend/src/core/constants/links.ts | 1 + .../core/data/useTranslatedToolRegistry.tsx | 3 +- 3 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 frontend/src/core/constants/links.ts diff --git a/frontend/src/core/components/shared/SkeletonLoader.tsx b/frontend/src/core/components/shared/SkeletonLoader.tsx index 63c4bd22a..a95949e8f 100644 --- a/frontend/src/core/components/shared/SkeletonLoader.tsx +++ b/frontend/src/core/components/shared/SkeletonLoader.tsx @@ -2,23 +2,44 @@ import React from 'react'; import { Box, Group, Stack } from '@mantine/core'; interface SkeletonLoaderProps { - type: 'pageGrid' | 'fileGrid' | 'controls' | 'viewer'; + type: 'pageGrid' | 'fileGrid' | 'controls' | 'viewer' | 'block'; count?: number; animated?: boolean; + width?: number | string; + height?: number | string; + radius?: number | string; } -const SkeletonLoader: React.FC = ({ - type, - count = 8, - animated = true +const SkeletonLoader: React.FC = ({ + type, + count = 8, + animated = true, + width, + height, + radius = 8, }) => { const animationStyle = animated ? { animation: 'pulse 2s infinite' } : {}; + // Generic block skeleton for inline text/inputs/etc. + const renderBlock = () => ( + + ); + const renderPageGridSkeleton = () => ( -

{Array.from({ length: count }).map((_, i) => ( = ({ w="100%" h={240} bg="gray.1" - style={{ + style={{ borderRadius: '8px', ...animationStyle, animationDelay: animated ? `${i * 0.1}s` : undefined @@ -37,10 +58,10 @@ const SkeletonLoader: React.FC = ({ ); const renderFileGridSkeleton = () => ( -
{Array.from({ length: count }).map((_, i) => ( = ({ w="100%" h={280} bg="gray.1" - style={{ + style={{ borderRadius: '8px', ...animationStyle, animationDelay: animated ? `${i * 0.1}s` : undefined @@ -76,18 +97,20 @@ const SkeletonLoader: React.FC = ({ {/* Main content skeleton */} - ); switch (type) { + case 'block': + return renderBlock(); case 'pageGrid': return renderPageGridSkeleton(); case 'fileGrid': @@ -101,4 +124,4 @@ const SkeletonLoader: React.FC = ({ } }; -export default SkeletonLoader; \ No newline at end of file +export default SkeletonLoader; diff --git a/frontend/src/core/constants/links.ts b/frontend/src/core/constants/links.ts new file mode 100644 index 000000000..c48ea04ab --- /dev/null +++ b/frontend/src/core/constants/links.ts @@ -0,0 +1 @@ +export const devApiLink = "https://registry.scalar.com/@stirlingpdf/apis/stirling-pdf-processing-api/"; diff --git a/frontend/src/core/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx index 0844b94d1..3208e4ef7 100644 --- a/frontend/src/core/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -1,6 +1,7 @@ import { useMemo } from "react"; import LocalIcon from "@app/components/shared/LocalIcon"; import { useTranslation } from "react-i18next"; +import { devApiLink } from "@app/constants/links"; import SplitPdfPanel from "@app/tools/Split"; import CompressPdfPanel from "@app/tools/Compress"; import OCRPanel from "@app/tools/OCR"; @@ -784,7 +785,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { description: t("home.devApi.desc", "Link to API documentation"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, - link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html", + link: devApiLink, synonyms: getSynonyms(t, "devApi"), supportsAutomate: false, automationSettings: null From 9c03914edd87b57d140045f32227007b23053052 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:10:40 +0000 Subject: [PATCH 23/56] Add admin password reset option for users (#5180) ## Summary - add backend support for admins to reset user passwords and optionally email notifications when SMTP is enabled - surface mail capability in admin settings data for the UI - add a shared change-password modal hooked into People and Team user actions with random password generation and email options ## Testing - not run (not requested) ------ [Codex Task](https://chatgpt.com/codex/tasks/task_b_6934b978fe3c83289b5b95dec79b3d38) --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../api/ProprietaryUIDataController.java | 4 +- .../controller/api/UserController.java | 77 +++++ .../proprietary/security/model/User.java | 11 + .../security/service/EmailService.java | 49 +++ .../public/locales/en-GB/translation.toml | 25 ++ .../orchestrator/useOnboardingOrchestrator.ts | 33 +- .../shared/ChangeUserPasswordModal.tsx | 283 ++++++++++++++++++ .../config/configSections/PeopleSection.tsx | 39 ++- .../configSections/TeamDetailsSection.tsx | 30 ++ .../services/userManagementService.ts | 37 +++ 10 files changed, 577 insertions(+), 11 deletions(-) create mode 100644 frontend/src/proprietary/components/shared/ChangeUserPasswordModal.tsx diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java index d335eb9c2..7e290f0ae 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java @@ -328,6 +328,7 @@ public class ProprietaryUIDataController { data.setGrandfatheredUserCount(grandfatheredCount); data.setLicenseMaxUsers(licenseMaxUsers); data.setPremiumEnabled(premiumEnabled); + data.setMailEnabled(applicationProperties.getMail().isEnabled()); return ResponseEntity.ok(data); } @@ -376,7 +377,7 @@ public class ProprietaryUIDataController { data.setUsername(username); data.setRole(user.get().getRolesAsString()); data.setSettings(settingsJson); - data.setChangeCredsFlag(user.get().isFirstLogin()); + data.setChangeCredsFlag(user.get().isFirstLogin() || user.get().isForcePasswordChange()); data.setOAuth2Login(isOAuth2Login); data.setSaml2Login(isSaml2Login); @@ -510,6 +511,7 @@ public class ProprietaryUIDataController { private int grandfatheredUserCount; private int licenseMaxUsers; private boolean premiumEnabled; + private boolean mailEnabled; } @Data diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index f2b3fd510..6a18aeff0 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.UUID; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -18,6 +19,7 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.web.bind.annotation.*; +import jakarta.mail.MessagingException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.transaction.Transactional; @@ -236,6 +238,8 @@ public class UserController { return ResponseEntity.status(HttpStatus.UNAUTHORIZED) .body(Map.of("error", "incorrectPassword", "message", "Incorrect password")); } + // Set flags before changing password so they're saved together + user.setForcePasswordChange(false); userService.changePassword(user, newPassword); userService.changeFirstUse(user, false); // Logout using Spring's utility @@ -584,6 +588,79 @@ public class UserController { return ResponseEntity.ok(Map.of("message", "User role updated successfully")); } + @PreAuthorize("hasRole('ROLE_ADMIN')") + @PostMapping("/admin/changePasswordForUser") + public ResponseEntity changePasswordForUser( + @RequestParam(name = "username") String username, + @RequestParam(name = "newPassword", required = false) String newPassword, + @RequestParam(name = "generateRandom", defaultValue = "false") boolean generateRandom, + @RequestParam(name = "sendEmail", defaultValue = "false") boolean sendEmail, + @RequestParam(name = "includePassword", defaultValue = "false") boolean includePassword, + @RequestParam(name = "forcePasswordChange", defaultValue = "false") + boolean forcePasswordChange, + HttpServletRequest request, + Authentication authentication) + throws SQLException, UnsupportedProviderException, MessagingException { + Optional userOpt = userService.findByUsernameIgnoreCase(username); + if (userOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); + } + + String currentUsername = authentication.getName(); + if (currentUsername.equalsIgnoreCase(username)) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot change your own password.")); + } + + User user = userOpt.get(); + + String finalPassword = newPassword; + if (generateRandom) { + finalPassword = UUID.randomUUID().toString().replace("-", "").substring(0, 12); + } + + if (finalPassword == null || finalPassword.trim().isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "New password is required.")); + } + + // Set force password change flag before changing password so both are saved together + user.setForcePasswordChange(forcePasswordChange); + userService.changePassword(user, finalPassword); + + // Invalidate all active sessions to force reauthentication + userService.invalidateUserSessions(username); + + if (sendEmail) { + if (emailService.isEmpty() || !applicationProperties.getMail().isEnabled()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Email is not configured.")); + } + + String userEmail = user.getUsername(); + // Check if username is a valid email format + if (userEmail == null || userEmail.isBlank() || !userEmail.contains("@")) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + Map.of( + "error", + "User's email is not a valid email address. Notifications are disabled.")); + } + + String loginUrl = buildLoginUrl(request); + emailService + .get() + .sendPasswordChangedNotification( + userEmail, + user.getUsername(), + includePassword ? finalPassword : null, + loginUrl); + } + + return ResponseEntity.ok(Map.of("message", "User password updated successfully")); + } + @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/admin/changeUserEnabled/{username}") public ResponseEntity changeUserEnabled( diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 8207eae28..c53893a8b 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -59,6 +59,9 @@ public class User implements UserDetails, Serializable { @Column(name = "hasCompletedInitialSetup") private Boolean hasCompletedInitialSetup = false; + @Column(name = "forcePasswordChange") + private Boolean forcePasswordChange = false; + @Column(name = "roleName") private String roleName; @@ -117,6 +120,14 @@ public class User implements UserDetails, Serializable { this.hasCompletedInitialSetup = hasCompletedInitialSetup; } + public boolean isForcePasswordChange() { + return forcePasswordChange != null && forcePasswordChange; + } + + public void setForcePasswordChange(boolean forcePasswordChange) { + this.forcePasswordChange = forcePasswordChange; + } + public void setAuthenticationType(AuthenticationType authenticationType) { this.authenticationType = authenticationType.toString().toLowerCase(); } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java index 8df76fca3..d4ecf8161 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java @@ -223,4 +223,53 @@ public class EmailService { sendPlainEmail(to, subject, body, true); } + + @Async + public void sendPasswordChangedNotification( + String to, String username, String newPassword, String loginUrl) throws MessagingException { + String subject = "Your Stirling PDF password has been updated"; + + String passwordSection = + newPassword == null + ? "" + : """ +
+

Temporary Password: %s

+
+ """ + .formatted(newPassword); + + String body = + """ + +
+
+
+ \"Stirling +
+
+

Your password was changed

+

Hello %s,

+

An administrator has updated the password for your Stirling PDF account.

+ %s +

If you did not expect this change, please contact your administrator immediately.

+ +

Or copy and paste this link in your browser:

+
+ %s +
+
+
+ © 2025 Stirling PDF. All rights reserved. +
+
+
+ + """ + .formatted(username, passwordSection, loginUrl, loginUrl); + + sendPlainEmail(to, subject, body, true); + } } diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index fcdcf592f..9d9278922 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -5368,6 +5368,31 @@ error = "Failed to update user status" success = "User deleted successfully" error = "Failed to delete user" +[workspace.people.changePassword] +action = "Change password" +title = "Change password" +subtitle = "Update the password for" +newPassword = "New password" +confirmPassword = "Confirm password" +placeholder = "Enter a new password" +confirmPlaceholder = "Re-enter the new password" +passwordRequired = "Please enter a new password" +passwordMismatch = "Passwords do not match" +generateRandom = "Generate secure password" +generatedPreview = "Generated password:" +copyTooltip = "Copy to clipboard" +copiedToClipboard = "Password copied to clipboard" +copyFailed = "Failed to copy password" +sendEmail = "Email the user about this change" +includePassword = "Include the new password in the email" +forcePasswordChange = "Force user to change password on next login" +emailUnavailable = "This user's email is not a valid email address. Notifications are disabled." +smtpDisabled = "Email notifications require SMTP to be enabled in settings." +notifyOnly = "An email will be sent without the password, letting the user know an admin changed it." +submit = "Update password" +success = "Password updated successfully" +error = "Failed to update password" + [workspace.people.emailInvite] tab = "Email Invite" description = "Type or paste in emails below, separated by commas. Users will receive login credentials via email." diff --git a/frontend/src/core/components/onboarding/orchestrator/useOnboardingOrchestrator.ts b/frontend/src/core/components/onboarding/orchestrator/useOnboardingOrchestrator.ts index 45d1ef454..514b98e1c 100644 --- a/frontend/src/core/components/onboarding/orchestrator/useOnboardingOrchestrator.ts +++ b/frontend/src/core/components/onboarding/orchestrator/useOnboardingOrchestrator.ts @@ -195,7 +195,7 @@ export function useOnboardingOrchestrator( accountService.getAccountData(), accountService.getLoginPageData(), ]); - + setRuntimeState((prev) => ({ ...prev, requiresPasswordChange: accountData.changeCredsFlag, @@ -226,8 +226,12 @@ export function useOnboardingOrchestrator( }), [serverExperience, runtimeState]); const activeFlow = useMemo(() => { + // If password change is required, ONLY show the first-login step + if (runtimeState.requiresPasswordChange) { + return ONBOARDING_STEPS.filter((step) => step.id === 'first-login'); + } return ONBOARDING_STEPS.filter((step) => step.condition(conditionContext)); - }, [conditionContext]); + }, [conditionContext, runtimeState.requiresPasswordChange]); // Wait for config AND admin status before calculating initial step const adminStatusResolved = !configLoading && ( @@ -238,23 +242,31 @@ export function useOnboardingOrchestrator( useEffect(() => { if (configLoading || !adminStatusResolved || activeFlow.length === 0) return; - + let firstUnseenIndex = -1; for (let i = 0; i < activeFlow.length; i++) { - if (!hasSeenStep(activeFlow[i].id)) { + // Special case: first-login step should always be considered "unseen" if requiresPasswordChange is true + const isFirstLoginStep = activeFlow[i].id === 'first-login'; + const shouldTreatAsUnseen = isFirstLoginStep ? runtimeState.requiresPasswordChange : !hasSeenStep(activeFlow[i].id); + + if (shouldTreatAsUnseen) { firstUnseenIndex = i; break; } } - - if (firstUnseenIndex === -1) { + + // Force reset index when password change is required (overrides initialIndexSet) + if (runtimeState.requiresPasswordChange && firstUnseenIndex === 0) { + setCurrentStepIndex(0); + initialIndexSet.current = true; + } else if (firstUnseenIndex === -1) { setCurrentStepIndex(activeFlow.length); initialIndexSet.current = true; } else if (!initialIndexSet.current) { setCurrentStepIndex(firstUnseenIndex); initialIndexSet.current = true; } - }, [activeFlow, configLoading, adminStatusResolved]); + }, [activeFlow, configLoading, adminStatusResolved, runtimeState.requiresPasswordChange]); const totalSteps = activeFlow.length; @@ -303,10 +315,13 @@ export function useOnboardingOrchestrator( if (!currentStep || isLoading) { return; } - if (hasSeenStep(currentStep.id)) { + // Special case: never auto-complete first-login step if requiresPasswordChange is true + const isFirstLoginStep = currentStep.id === 'first-login'; + + if (!isFirstLoginStep && hasSeenStep(currentStep.id)) { complete(); } - }, [currentStep, isLoading, complete]); + }, [currentStep, isLoading, complete, runtimeState.requiresPasswordChange]); const updateRuntimeState = useCallback((updates: Partial) => { persistRuntimeState(updates); diff --git a/frontend/src/proprietary/components/shared/ChangeUserPasswordModal.tsx b/frontend/src/proprietary/components/shared/ChangeUserPasswordModal.tsx new file mode 100644 index 000000000..9e0cd222c --- /dev/null +++ b/frontend/src/proprietary/components/shared/ChangeUserPasswordModal.tsx @@ -0,0 +1,283 @@ +import { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { + ActionIcon, + Button, + Checkbox, + CloseButton, + Group, + Modal, + PasswordInput, + Stack, + Text, + Tooltip, +} from '@mantine/core'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { alert } from '@app/components/toast'; +import { ChangeUserPasswordRequest, User, userManagementService } from '@app/services/userManagementService'; +import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; + +interface ChangeUserPasswordModalProps { + opened: boolean; + onClose: () => void; + user: User | null; + onSuccess: () => void; + mailEnabled: boolean; +} + +function generateSecurePassword() { + const charset = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789@$!%*?&'; + const length = 14; + let password = ''; + const charsetLength = charset.length; + const uint8Array = new Uint8Array(length); + window.crypto.getRandomValues(uint8Array); + // To avoid modulo bias, discard values >= 256 - (256 % charsetLength) + for (let i = 0; password.length < length; ) { + const randomByte = uint8Array[i]; + i++; + if (randomByte >= Math.floor(256 / charsetLength) * charsetLength) { + // Discard and generate a new random value + if (i >= uint8Array.length) { + // Exhausted the array, fill a new one + window.crypto.getRandomValues(uint8Array); + i = 0; + } + continue; + } + const randomIndex = randomByte % charsetLength; + password += charset[randomIndex]; + } + return password; +} + +export default function ChangeUserPasswordModal({ opened, onClose, user, onSuccess, mailEnabled }: ChangeUserPasswordModalProps) { + const { t } = useTranslation(); + const [form, setForm] = useState({ + newPassword: '', + confirmPassword: '', + generateRandom: false, + sendEmail: false, + includePassword: false, + forcePasswordChange: false, + }); + const [processing, setProcessing] = useState(false); + + const disabled = !user; + + const handleGeneratePassword = () => { + const generated = generateSecurePassword(); + setForm((prev) => ({ ...prev, newPassword: generated, confirmPassword: generated, generateRandom: true })); + }; + + const handleCopyPassword = async () => { + if (!form.newPassword) return; + try { + await navigator.clipboard.writeText(form.newPassword); + alert({ alertType: 'success', title: t('workspace.people.changePassword.copiedToClipboard', 'Password copied to clipboard') }); + } catch (_error) { + alert({ alertType: 'error', title: t('workspace.people.changePassword.copyFailed', 'Failed to copy password') }); + } + }; + + const resetState = () => { + setForm({ + newPassword: '', + confirmPassword: '', + generateRandom: false, + sendEmail: false, + includePassword: false, + forcePasswordChange: false, + }); + }; + + const handleClose = () => { + if (processing) return; + resetState(); + onClose(); + }; + + const handleSubmit = async () => { + if (!user) return; + + if (!form.generateRandom && !form.newPassword.trim()) { + alert({ alertType: 'error', title: t('workspace.people.changePassword.passwordRequired', 'Please enter a new password') }); + return; + } + + if (!form.generateRandom && form.newPassword !== form.confirmPassword) { + alert({ alertType: 'error', title: t('workspace.people.changePassword.passwordMismatch', 'Passwords do not match') }); + return; + } + + const payload: ChangeUserPasswordRequest = { + username: user.username, + newPassword: form.newPassword, // Always send the password (frontend generates it when generateRandom is true) + generateRandom: false, // Not needed since we're generating on frontend + sendEmail: form.sendEmail, + includePassword: form.includePassword, + forcePasswordChange: form.forcePasswordChange, + }; + + try { + setProcessing(true); + await userManagementService.changeUserPassword(payload); + alert({ alertType: 'success', title: t('workspace.people.changePassword.success', 'Password updated successfully') }); + onSuccess(); + handleClose(); + } catch (error: any) { + const errorMessage = error.response?.data?.message || error.response?.data?.error || error.message || t('workspace.people.changePassword.error', 'Failed to update password'); + alert({ alertType: 'error', title: errorMessage }); + } finally { + setProcessing(false); + } + }; + + useEffect(() => { + if (opened) { + setForm({ + newPassword: '', + confirmPassword: '', + generateRandom: false, + sendEmail: false, + includePassword: false, + forcePasswordChange: false, + }); + } + }, [opened, user?.username]); + + // Check if username is a valid email format + const isValidEmail = (email: string | undefined) => { + if (!email) return false; + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); + }; + + const canEmail = mailEnabled && isValidEmail(user?.username); + const passwordPreview = useMemo(() => form.newPassword && form.generateRandom ? form.newPassword : '', [form.generateRandom, form.newPassword]); + + return ( + +
+ + + + + + {t('workspace.people.changePassword.title', 'Change password')} + + + {t('workspace.people.changePassword.subtitle', 'Update the password for')} {user?.username} + + + + + setForm({ ...form, newPassword: event.currentTarget.value, generateRandom: false })} + disabled={processing || disabled || form.generateRandom} + data-autofocus + /> + setForm({ ...form, confirmPassword: event.currentTarget.value, generateRandom: false })} + disabled={processing || disabled || form.generateRandom} + error={!form.generateRandom && form.confirmPassword && form.newPassword !== form.confirmPassword ? t('workspace.people.changePassword.passwordMismatch', 'Passwords do not match') : undefined} + /> + + { + const checked = event.currentTarget.checked; + setForm((prev) => ({ ...prev, generateRandom: checked })); + if (event.currentTarget.checked) { + handleGeneratePassword(); + } + }} + /> + {passwordPreview && ( + + + {t('workspace.people.changePassword.generatedPreview', 'Generated password:')} {passwordPreview} + + + + + + + + )} + + + + + setForm({ ...form, sendEmail: event.currentTarget.checked })} + disabled={!canEmail || processing} + /> + setForm({ ...form, includePassword: event.currentTarget.checked })} + disabled={!canEmail || !form.sendEmail || processing} + /> + setForm({ ...form, forcePasswordChange: event.currentTarget.checked })} + disabled={processing || disabled} + /> + {!canEmail && ( + + {mailEnabled + ? t('workspace.people.changePassword.emailUnavailable', "This user's email is not a valid email address. Notifications are disabled.") + : t('workspace.people.changePassword.smtpDisabled', 'Email notifications require SMTP to be enabled in settings.')} + + )} + {canEmail && !form.includePassword && form.sendEmail && ( + + {t('workspace.people.changePassword.notifyOnly', 'An email will be sent without the password, letting the user know an admin changed it.')} + + )} + + + + +
+
+ ); +} diff --git a/frontend/src/proprietary/components/shared/config/configSections/PeopleSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/PeopleSection.tsx index 9c4f56ba0..bc2f69c3a 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/PeopleSection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/PeopleSection.tsx @@ -30,6 +30,7 @@ import LoginRequiredBanner from '@app/components/shared/config/LoginRequiredBann import { useNavigate } from 'react-router-dom'; import UpdateSeatsButton from '@app/components/shared/UpdateSeatsButton'; import { useLicense } from '@app/contexts/LicenseContext'; +import ChangeUserPasswordModal from '@app/components/shared/ChangeUserPasswordModal'; export default function PeopleSection() { const { t } = useTranslation(); @@ -43,8 +44,11 @@ export default function PeopleSection() { const [searchQuery, setSearchQuery] = useState(''); const [inviteModalOpened, setInviteModalOpened] = useState(false); const [editUserModalOpened, setEditUserModalOpened] = useState(false); + const [changePasswordModalOpened, setChangePasswordModalOpened] = useState(false); + const [passwordUser, setPasswordUser] = useState(null); const [selectedUser, setSelectedUser] = useState(null); const [processing, setProcessing] = useState(false); + const [mailEnabled, setMailEnabled] = useState(false); // License information const [licenseInfo, setLicenseInfo] = useState<{ @@ -119,6 +123,7 @@ export default function PeopleSection() { premiumEnabled: adminData.premiumEnabled, totalUsers: adminData.totalUsers, }); + setMailEnabled(adminData.mailEnabled); } else { // Provide example data when login is disabled const exampleUsers: User[] = [ @@ -179,6 +184,7 @@ export default function PeopleSection() { setUsers(exampleUsers); setTeams(exampleTeams); + setMailEnabled(false); // Example license information setLicenseInfo({ @@ -267,6 +273,16 @@ export default function PeopleSection() { setEditUserModalOpened(true); }; + const openChangePasswordModal = (user: User) => { + setPasswordUser(user); + setChangePasswordModalOpened(true); + }; + + const closeChangePasswordModal = () => { + setChangePasswordModalOpened(false); + setPasswordUser(null); + }; + const closeEditModal = () => { setEditUserModalOpened(false); setSelectedUser(null); @@ -562,7 +578,20 @@ export default function PeopleSection() { - openEditModal(user)} disabled={!loginEnabled}>{t('workspace.people.editRole')} + } + onClick={() => openEditModal(user)} + disabled={!loginEnabled} + > + {t('workspace.people.editRole')} + + } + onClick={() => openChangePasswordModal(user)} + disabled={!loginEnabled} + > + {t('workspace.people.changePassword.action', 'Change password')} + : } onClick={() => handleToggleEnabled(user)} @@ -591,6 +620,14 @@ export default function PeopleSection() { onSuccess={fetchData} /> + + {/* Edit User Modal */} >({}); const [addMemberModalOpened, setAddMemberModalOpened] = useState(false); const [changeTeamModalOpened, setChangeTeamModalOpened] = useState(false); + const [changePasswordModalOpened, setChangePasswordModalOpened] = useState(false); + const [passwordUser, setPasswordUser] = useState(null); const [selectedUser, setSelectedUser] = useState(null); const [selectedUserId, setSelectedUserId] = useState(''); const [selectedTeamId, setSelectedTeamId] = useState(''); @@ -47,6 +50,7 @@ export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectio const [licenseInfo, setLicenseInfo] = useState<{ availableSlots: number; } | null>(null); + const [mailEnabled, setMailEnabled] = useState(false); useEffect(() => { fetchTeamDetails(); @@ -70,6 +74,7 @@ export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectio setLicenseInfo({ availableSlots: adminData.availableSlots, }); + setMailEnabled(adminData.mailEnabled); } catch (error) { console.error('Failed to fetch team details:', error); alert({ alertType: 'error', title: t('workspace.teams.loadError', 'Failed to load team details') }); @@ -172,6 +177,16 @@ export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectio setChangeTeamModalOpened(true); }; + const openChangePasswordModal = (user: User) => { + setPasswordUser(user); + setChangePasswordModalOpened(true); + }; + + const closeChangePasswordModal = () => { + setChangePasswordModalOpened(false); + setPasswordUser(null); + }; + const handleChangeTeam = async () => { if (!selectedUser || !selectedTeamId) { alert({ alertType: 'error', title: t('workspace.teams.changeTeam.selectTeamRequired', 'Please select a team') }); @@ -398,6 +413,13 @@ export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectio > {t('workspace.teams.changeTeam.label', 'Change Team')} + } + onClick={() => openChangePasswordModal(user)} + disabled={processing} + > + {t('workspace.people.changePassword.action', 'Change password')} + {team.name !== 'Internal' && team.name !== 'Default' && ( } @@ -427,6 +449,14 @@ export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectio + + {/* Add Member Modal */} ('/api/v1/invite/cleanup'); return response.data; }, + + /** + * Change another user's password (admin only) + */ + async changeUserPassword(data: ChangeUserPasswordRequest): Promise { + const formData = new FormData(); + formData.append('username', data.username); + if (data.newPassword) { + formData.append('newPassword', data.newPassword); + } + if (data.generateRandom !== undefined) { + formData.append('generateRandom', data.generateRandom.toString()); + } + if (data.sendEmail !== undefined) { + formData.append('sendEmail', data.sendEmail.toString()); + } + if (data.includePassword !== undefined) { + formData.append('includePassword', data.includePassword.toString()); + } + if (data.forcePasswordChange !== undefined) { + formData.append('forcePasswordChange', data.forcePasswordChange.toString()); + } + + await apiClient.post('/api/v1/user/admin/changePasswordForUser', formData, { + suppressErrorToast: true, // Component will handle error display + } as any); + }, }; From 7c5aa3685feae094f48de0d9fb17d908ccbc7709 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:10:54 +0000 Subject: [PATCH 24/56] Add configurable SMTP TLS/SSL options (#5204) ## Summary - add optional STARTTLS and SSL-related fields to mail settings with defaults matching prior behavior - apply the new mail properties in the SMTP JavaMail configuration, including trust and hostname verification overrides - update mail settings template and tests to cover default behavior and explicit TLS/SSL overrides - clarify STARTTLS naming and sslTrust usage with examples in property comments and the settings template - default sslTrust to a wildcard when unset so TLS connections accept any host by default unless tightened ## Testing - ./gradlew :proprietary:test --tests stirling.software.proprietary.security.service.MailConfigTest --console plain ------ [Codex Task](https://chatgpt.com/codex/tasks/task_b_693864b2a6648328ae75c7e88a726a65) --- .../common/model/ApplicationProperties.java | 10 ++++++ .../src/main/resources/settings.yml.template | 5 +++ .../security/configuration/MailConfig.java | 29 ++++++++++++++-- .../security/service/MailConfigTest.java | 33 ++++++++++++++++++- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java index f6afa62ea..35ddddeaa 100644 --- a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java +++ b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java @@ -574,6 +574,16 @@ public class ApplicationProperties { private String username; @ToString.Exclude private String password; private String from; + // STARTTLS upgrades a plain SMTP connection to TLS after connecting (RFC 3207) + private Boolean startTlsEnable = true; + private Boolean startTlsRequired; + // SSL/TLS wrapper for implicit TLS (typically port 465) + private Boolean sslEnable; + // Hostnames or patterns (e.g., "smtp.example.com" or "*") to trust for TLS certificates; + // defaults to "*" (trust all) when not set + private String sslTrust; + // Enables hostname verification for TLS connections + private Boolean sslCheckServerIdentity; } @Data diff --git a/app/core/src/main/resources/settings.yml.template b/app/core/src/main/resources/settings.yml.template index 4c2ec003e..5a50ef903 100644 --- a/app/core/src/main/resources/settings.yml.template +++ b/app/core/src/main/resources/settings.yml.template @@ -104,6 +104,11 @@ mail: username: '' # SMTP server username password: '' # SMTP server password from: '' # sender email address + startTlsEnable: true # enable STARTTLS (explicit TLS upgrade after connecting) when supported by the SMTP server + startTlsRequired: false # require STARTTLS; connection fails if the upgrade command is not supported + sslEnable: false # enable SSL/TLS wrapper for implicit TLS (typically used with port 465) + sslTrust: '' # optional trusted host override, e.g. "smtp.example.com" or "*"; defaults to "*" (trust all) when empty + sslCheckServerIdentity: false # enable hostname verification when using SSL/TLS legal: termsAndConditions: https://www.stirling.com/legal/terms-of-service # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java index 6a565cade..6538b7ee9 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java @@ -33,7 +33,8 @@ public class MailConfig { // Creates a new instance of JavaMailSenderImpl, which is a Spring implementation JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); - mailSender.setHost(mailProperties.getHost()); + String host = mailProperties.getHost(); + mailSender.setHost(host); mailSender.setPort(mailProperties.getPort()); mailSender.setDefaultEncoding("UTF-8"); @@ -70,8 +71,32 @@ public class MailConfig { log.info("SMTP authentication disabled - no credentials provided"); } + boolean startTlsEnabled = + mailProperties.getStartTlsEnable() == null || mailProperties.getStartTlsEnable(); // Enables STARTTLS to encrypt the connection if supported by the SMTP server - props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.starttls.enable", Boolean.toString(startTlsEnabled)); + if (mailProperties.getStartTlsRequired() != null) { + props.put( + "mail.smtp.starttls.required", mailProperties.getStartTlsRequired().toString()); + } + + if (mailProperties.getSslEnable() != null) { + props.put("mail.smtp.ssl.enable", mailProperties.getSslEnable().toString()); + } + + // Trust the configured host to allow STARTTLS with self-signed certificates + String sslTrust = mailProperties.getSslTrust(); + if (sslTrust == null || sslTrust.trim().isEmpty()) { + sslTrust = "*"; + } + if (sslTrust != null && !sslTrust.trim().isEmpty()) { + props.put("mail.smtp.ssl.trust", sslTrust); + } + if (mailProperties.getSslCheckServerIdentity() != null) { + props.put( + "mail.smtp.ssl.checkserveridentity", + mailProperties.getSslCheckServerIdentity().toString()); + } // Returns the configured mail sender, ready to send emails return mailSender; diff --git a/app/proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java b/app/proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java index 3db3493f4..5df56f8ef 100644 --- a/app/proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java +++ b/app/proprietary/src/test/java/stirling/software/proprietary/security/service/MailConfigTest.java @@ -27,6 +27,11 @@ class MailConfigTest { when(mailProps.getPort()).thenReturn(587); when(mailProps.getUsername()).thenReturn("user@example.com"); when(mailProps.getPassword()).thenReturn("password"); + when(mailProps.getStartTlsEnable()).thenReturn(null); + when(mailProps.getStartTlsRequired()).thenReturn(null); + when(mailProps.getSslEnable()).thenReturn(null); + when(mailProps.getSslTrust()).thenReturn(null); + when(mailProps.getSslCheckServerIdentity()).thenReturn(null); } @Test @@ -50,6 +55,32 @@ class MailConfigTest { () -> assertEquals("password", impl.getPassword()), () -> assertEquals("UTF-8", impl.getDefaultEncoding()), () -> assertEquals("true", props.getProperty("mail.smtp.auth")), - () -> assertEquals("true", props.getProperty("mail.smtp.starttls.enable"))); + () -> assertEquals("true", props.getProperty("mail.smtp.starttls.enable")), + () -> assertEquals(null, props.getProperty("mail.smtp.starttls.required")), + () -> assertEquals(null, props.getProperty("mail.smtp.ssl.enable")), + () -> assertEquals("*", props.getProperty("mail.smtp.ssl.trust"))); + } + + @Test + void shouldRespectExplicitTlsOverrides() { + ApplicationProperties appProps = mock(ApplicationProperties.class); + when(mailProps.getStartTlsEnable()).thenReturn(false); + when(mailProps.getStartTlsRequired()).thenReturn(true); + when(mailProps.getSslEnable()).thenReturn(true); + when(mailProps.getSslTrust()).thenReturn("*"); + when(mailProps.getSslCheckServerIdentity()).thenReturn(true); + when(appProps.getMail()).thenReturn(mailProps); + + MailConfig config = new MailConfig(appProps); + JavaMailSenderImpl impl = (JavaMailSenderImpl) config.javaMailSender(); + + Properties props = impl.getJavaMailProperties(); + + assertAll( + () -> assertEquals("false", props.getProperty("mail.smtp.starttls.enable")), + () -> assertEquals("true", props.getProperty("mail.smtp.starttls.required")), + () -> assertEquals("true", props.getProperty("mail.smtp.ssl.enable")), + () -> assertEquals("*", props.getProperty("mail.smtp.ssl.trust")), + () -> assertEquals("true", props.getProperty("mail.smtp.ssl.checkserveridentity"))); } } From 291e1a392bdbb03e2104b8ed5192f297503bc54d Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:11:16 +0000 Subject: [PATCH 25/56] extra font support in text editor (#5208) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .../service/PdfJsonFallbackFontService.java | 66 +++++++++++++++++- .../fonts/NotoSansDevanagari-Regular.ttf | Bin 0 -> 185012 bytes .../fonts/NotoSansMalayalam-Regular.ttf | Bin 0 -> 77312 bytes .../static/fonts/NotoSansTC-Regular.ttf | Bin 0 -> 5683368 bytes .../static/fonts/NotoSerifTibetan-Regular.ttf | Bin 0 -> 609640 bytes 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 app/core/src/main/resources/static/fonts/NotoSansDevanagari-Regular.ttf create mode 100644 app/core/src/main/resources/static/fonts/NotoSansMalayalam-Regular.ttf create mode 100644 app/core/src/main/resources/static/fonts/NotoSansTC-Regular.ttf create mode 100644 app/core/src/main/resources/static/fonts/NotoSerifTibetan-Regular.ttf diff --git a/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonFallbackFontService.java b/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonFallbackFontService.java index 4cf0fc8a1..107abbe2b 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonFallbackFontService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonFallbackFontService.java @@ -33,8 +33,12 @@ public class PdfJsonFallbackFontService { public static final String FALLBACK_FONT_CJK_ID = "fallback-noto-cjk"; public static final String FALLBACK_FONT_JP_ID = "fallback-noto-jp"; public static final String FALLBACK_FONT_KR_ID = "fallback-noto-korean"; + public static final String FALLBACK_FONT_TC_ID = "fallback-noto-tc"; public static final String FALLBACK_FONT_AR_ID = "fallback-noto-arabic"; public static final String FALLBACK_FONT_TH_ID = "fallback-noto-thai"; + public static final String FALLBACK_FONT_DEVANAGARI_ID = "fallback-noto-devanagari"; + public static final String FALLBACK_FONT_MALAYALAM_ID = "fallback-noto-malayalam"; + public static final String FALLBACK_FONT_TIBETAN_ID = "fallback-noto-tibetan"; // Font name aliases map PDF font names to available fallback fonts // This provides better visual consistency when editing PDFs @@ -59,6 +63,22 @@ public class PdfJsonFallbackFontService { Map.entry("dejavuserif", "fallback-dejavu-serif"), Map.entry("dejavumono", "fallback-dejavu-mono"), Map.entry("dejavusansmono", "fallback-dejavu-mono"), + // Traditional Chinese fonts (Taiwan, Hong Kong, Macau) + Map.entry("mingliu", "fallback-noto-tc"), + Map.entry("pmingliu", "fallback-noto-tc"), + Map.entry("microsoftjhenghei", "fallback-noto-tc"), + Map.entry("jhenghei", "fallback-noto-tc"), + Map.entry("kaiti", "fallback-noto-tc"), + Map.entry("kaiu", "fallback-noto-tc"), + Map.entry("dfkaib5", "fallback-noto-tc"), + Map.entry("dfkai", "fallback-noto-tc"), + // Simplified Chinese fonts (Mainland China) - more common + Map.entry("simsun", "fallback-noto-cjk"), + Map.entry("simhei", "fallback-noto-cjk"), + Map.entry("microsoftyahei", "fallback-noto-cjk"), + Map.entry("yahei", "fallback-noto-cjk"), + Map.entry("songti", "fallback-noto-cjk"), + Map.entry("heiti", "fallback-noto-cjk"), // Noto Sans - Google's universal font (use as last resort generic fallback) Map.entry("noto", "fallback-noto-sans"), Map.entry("notosans", "fallback-noto-sans")); @@ -83,6 +103,12 @@ public class PdfJsonFallbackFontService { "classpath:/static/fonts/NotoSansKR-Regular.ttf", "NotoSansKR-Regular", "ttf")), + Map.entry( + FALLBACK_FONT_TC_ID, + new FallbackFontSpec( + "classpath:/static/fonts/NotoSansTC-Regular.ttf", + "NotoSansTC-Regular", + "ttf")), Map.entry( FALLBACK_FONT_AR_ID, new FallbackFontSpec( @@ -95,6 +121,24 @@ public class PdfJsonFallbackFontService { "classpath:/static/fonts/NotoSansThai-Regular.ttf", "NotoSansThai-Regular", "ttf")), + Map.entry( + FALLBACK_FONT_DEVANAGARI_ID, + new FallbackFontSpec( + "classpath:/static/fonts/NotoSansDevanagari-Regular.ttf", + "NotoSansDevanagari-Regular", + "ttf")), + Map.entry( + FALLBACK_FONT_MALAYALAM_ID, + new FallbackFontSpec( + "classpath:/static/fonts/NotoSansMalayalam-Regular.ttf", + "NotoSansMalayalam-Regular", + "ttf")), + Map.entry( + FALLBACK_FONT_TIBETAN_ID, + new FallbackFontSpec( + "classpath:/static/fonts/NotoSerifTibetan-Regular.ttf", + "NotoSerifTibetan-Regular", + "ttf")), // Liberation Sans family Map.entry( "fallback-liberation-sans", @@ -484,6 +528,20 @@ public class PdfJsonFallbackFontService { */ public String resolveFallbackFontId(int codePoint) { Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint); + + // Bopomofo is primarily used in Taiwan for Traditional Chinese phonetic annotation + if (block == Character.UnicodeBlock.BOPOMOFO + || block == Character.UnicodeBlock.BOPOMOFO_EXTENDED) { + return FALLBACK_FONT_TC_ID; + } + + // Compatibility ideographs are primarily used by Traditional Chinese encodings (e.g., Big5, + // HKSCS) so prefer the Traditional Chinese fallback here. + if (block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS + || block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT) { + return FALLBACK_FONT_TC_ID; + } + if (block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B @@ -492,19 +550,23 @@ public class PdfJsonFallbackFontService { || block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E || block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F || block == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION - || block == Character.UnicodeBlock.BOPOMOFO - || block == Character.UnicodeBlock.BOPOMOFO_EXTENDED || block == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { return FALLBACK_FONT_CJK_ID; } Character.UnicodeScript script = Character.UnicodeScript.of(codePoint); return switch (script) { + // HAN script is used by both Simplified and Traditional Chinese + // 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.) case HAN -> FALLBACK_FONT_CJK_ID; case HIRAGANA, KATAKANA -> FALLBACK_FONT_JP_ID; case HANGUL -> FALLBACK_FONT_KR_ID; case ARABIC -> FALLBACK_FONT_AR_ID; case THAI -> FALLBACK_FONT_TH_ID; + case DEVANAGARI -> FALLBACK_FONT_DEVANAGARI_ID; + case MALAYALAM -> FALLBACK_FONT_MALAYALAM_ID; + case TIBETAN -> FALLBACK_FONT_TIBETAN_ID; default -> FALLBACK_FONT_ID; }; } diff --git a/app/core/src/main/resources/static/fonts/NotoSansDevanagari-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSansDevanagari-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9a8c4b105e25f52dbdf80c39a0520fad67c68353 GIT binary patch literal 185012 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 literal 0 HcmV?d00001 diff --git a/app/core/src/main/resources/static/fonts/NotoSansMalayalam-Regular.ttf b/app/core/src/main/resources/static/fonts/NotoSansMalayalam-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a5a0fe65abb3b1798870ffe5f918ceda5d7b6823 GIT binary patch literal 77312 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%0D!zMo&x;8ZMt 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 >Dj6}Up40<*37uhndg6|POq94=?yN* zb%fbH&KPg?6zu(}Be;*MJj0r%ldfDcGIFW_G_;^TSVtF8=r^O2rz93+EO3RWk(I?2 zGiTf4lT+e?f}F0D38v|x(dk!oo_|kuO>-KtA$uB(|bDsg0F`ibw#!~R~WtVKPNRl zG%~q-;eX_&=i>_`b;*UiY5dqF=F$0`5ybXjJja)5_rx6!XMYGA1nYzgM_5jXZLc>zKX3krJZx4h; z=EtvzF1*O62O#|)BORidrQbns8^E_Aa!2I11~j~bhIWV@*gN;)Yw1;d6Go|^IdM6L zMmcz1xcKuuXF6t#^}SF=uD^L>1XD&DjQ>$JH6e0l)!Ho!8t}%vmYT?Pk7sISO1>w| z)fyTaSDG^?EI2)kcFP;5*RB@VCF`%v%NUN%OK9X50EDK-#U-y>*gie2Cb_!V6%>{2 zafg>>-u#n-d{;z9iX*7Gti1Ws8C44k-%ZRYs1U*(lA)GQXh=x%xMV7CG+l#Kw#Z#H zUn;2q`?`9}P>nAcm0(05)kkN;MEPY5b*0AUPbPWgU5mg3xAe!PPRw+=8tk^Ha51-` zsb#@ZHLNb{;weu`OV2jB-L(~CQeIXWG+}CaL}hTSJIk9^8f}LF0JbLaO-}#9JIc z9=D`+JZ^c5T-W3!b_J3+8r4{z{y1cmJ;3#jJCqBpJaQ@HR307=VN6sjR)fdn^;`1#PrV^8t z$4c2Nu8Ce79UqsHlz_4EH>x;4@`n_BD?BYJITayW)CAFGN9Kzv<@<2F*YeB6?puIp~PBJ0SHfJNUcbS(bx9`cCnzajX)y{7pVf?|it?rQN<2}cunZrYMGiT!YB=KhROz>`zMA*=}6GOfI1H-4( z7tWW9x%=;!GkbRX@Et?z{xY=o?MeIhftrocj&ekKgmZ-RgYrV=1KhGloWcz^bkU)u zAsCF&8HYrsW~kZITHBkaG*4-7ohD*;i=Z`q!)JEx96mkND}oU&5#h`-oCs5`spTPM zrD|qLM2Il^1q|Lj{Mnj5;rh-_;Th~5{s(E3B^HZegmi38;-mflKC5n zVhtCL`NN-|F^7G53KdK##uuf6P!EErmdP(x%D6I%>AA*yH8lk<_X|r;04Jy6R?5 znR`j=mCnrei0EBcO`kRqS&&$pmXSVd;^a#`X2-&*GnY=FTnz`xR$oG@(a+;< z94bOO_FecRh*r@%e2kICa+kf4-eCt0*)x3^_81b$>y@ z*Z5G*QhA(Uq^4LiLvgJ_&Nnz~{#Cs^DSOp~xl4Xg)|?w7Rt^6(IH4k{dEKPRo19^x zb0eeXwC?f5i8-@h)+_}}TV}1rhs9K-9PvAmH&IFkl|HVad6SDH!+B;?qEGU)O!?jk zdAb`Rvg?;r$B8MWc!p(glcrS+bgnB~Ijw10OH+PJR(g}OLN~uYmcuC{z&?)t8&dmAES58j9w6bP;TH5s5@=H=9%36vV7ETa%$4<^GFRCoa zC`uW=p|(E1CDEGLT3XSFd@F>08uW{iwTeoH76z%BTr(l(SUZz^l^$g$6nZkaGB~qn z!{rvOe5j+heASdmi)-TUY|opLoz_$|xwXZqnWwvMxOwj79aGoUl`QP9ef?FjB)ujj ze_lCqa0Zo^9CtF%TCuw1{#q|2li&Db^a9iq5Qy82?qGOe_WwP zk7Ps?Z1hZiFHDU@ijGK6-!oJur3y(~T4Vo~kG+2W7GJH)1;my17ad+2t^t5W`? zn#AAqkq_l=0aS?>hRekZV&9Z0&rO*U7*|CZVzY!7i_OE=i9Zgt{pc5M9~M(C;478l zN67s|1&u9~S0Z@5w94Dk=t%uKj&lEWy?)smyw@cu#nt3aOHRxTsjA4DmYR^cI3_wh zJsSC>{-I;Rg!;;)*sQF0dq_q_QCw_JVM;+wbnuk0`16Urtb>-b(WgeBPsJD>Nevq? z`$&I3dex?{hVT-=fL_;vURNXze?DJ0WVefceZ;AJtcNed&2Kg($2S4@Z4ii(=NEK`z5n?CVKUCE3RDOpXcX35Uh z`sZsP8ud&hs&=s-y_F*5>Z^>ZKlVhZ@gZSoeZrlV8<{XMy0|62DklrCT(5|Uu1=4u z7L&Zr)abS{XGpL!Ic8RLtc%tU`uM790;3-!5dESt-X@1-#4Nke#fx+1o`BRiA5L^Qw@t4Fk~+>EIuWCx|pcHQQzWuMkJmG z4VY_``1LsccB9ict@l2L>6?=n?Z_}GcN&y!;!AZR`XWX6&AG&HitoF(_};rq@4LVB z9(7{LefN~ycVEdp_mbg}rOs6%%I&8DKm5g4to z6_;$Ppn8UKKzrp4BFrL^!*O{q5?ugF9xsV~&5>48;dOXSho3PAySx)J>cxK@4Ue(h z_Csyyyf;Pow6HK&W_)9OrYqRh*ceux-q^m(HT*Y{)P@>(Cw5{;2XqN-3-H0m^LS;t zN-p9X>_Te>xasb{lU~@HiF~OObzjIw!{4Z1KkqVTF?>Y5VZ?1(PBI13Fnna{RMT>N z;#3TWkF<{bdgMlO!6y-t8-^E%dk=Ds92j|7XzFF;Lhb*+f+BV2`61GiT;5?9=!q}s z;*Nhwu-Lg^_$BE__cweUq|Rii@JDhhNcMG2P1iIvLHw()LjFPZ+K~kHGp-SQy+H1~ z3?EF02v1B5k4R8|6(1WL9~T!#+8!Kf7)cm8K)x;G`rg5wV`I_gaYG1S5c>=xA68gc z+0Isx$;@w{FN^v3bA0?Wrq%49zqbqjfA;xbtro+-_5t;e%{z!)6W!W>dxx|xh+e>il)iK z1c4_{J%I-WVo^(Lc9K0bsJS^kF(Bg)^J3$2 zvyu{Wj57mzwql&~fccYavKt~*wKhAYD6}$iR#np?C-%WFYp9wXRp}{B$;Jmbq8hVm z8?ViZkIzaj_qa+&MuxW{M{qWPJZgYVQ`%lZ%^SvZxH`8{a(5HANS&p$@V9kmO71pr z&wrxs9C^>Q9JR~xFx8If^i>7;=Jtv&wSZ5)1*VJeeNf%0#KLzbzAC&0e5;tHyu_t7 zX5<@Lh8f8nrZ8IfT7%_^SFV18;}>Ub-mL#GK4Z$hENjDttjjMaeA!ojR512cVby#V zGdnAGLn1LN%Tx;R9K<9vOuZL2dgBtEw&-T^7}{_*{EO(Mq{IgR!%0a=!+U_lvcyET zF^inU-AQ0o5F)rfIWaMrV28n}K(Hj_P_6js$gQSUXxFAVMv7GpIfbbfbbbuARG96s z?*mA?Ko0NI?J9ERh;GN2sJy1z%}Tk5)9n@|Mzrg84KtNq-ELKy#O=D>rsRlsbh}+? zQk}Zpp){(qb$gI9QQf24ol32GRJXfCiplWrR?5x!cvih1Z-&~8TSYy1Lk~RxmxP&k zA)pvGdM2(LW*dAB0g|wfHvn@DxGUIi1MWx;!B;={gK*E{IEE1CAX;_-eyb2O`PhJW zDdZzmKfb(D2TN}daDAIq3|fxmX>L+=-&&;!ss zAG-jB_@Y@2!p{OUvrS4g;<+%EJoGL8@%($TsYmh;wEz_5MGvQpa?{Ypi0^-+K@X?A z135f|*gNp_K{w~ufU*|6eq|-_6qx|Zejn_7UsgX z5`He{nnk%Mee}Xy0qImDWjZ&&PH7r|AFA)g{2FzKU^OR4cG0zByAs23AYfcf@ zoP4;9Y8EKh(56G#2>p7v{&(sncsXd&BMB}fw*e>hWFJDiO!DQE(MkuA8tMbq!+j8P zsbqR#QoCM-9L6Yulu-ZR-?sm~P&BLKzmeO}8pin(>(I-q!lamlSy+T7@G=Nt7Y-4G zb*f9ag-3Wrum};MA`DxP5h7CHQG4uZ;wuUwUL=S_ktC8uibxe{B3)#NOpztBMUI#t zaz&oV7X_kF6p3Oip-V-XC>Ir?QdEg*Q6p+aotP*liF(l>8pULMQL9C;yYrexIyd^-xa&Xjbe}Zp14WeEN&6s7q^NZh`r*6;x_Rkal81j*eC7~ z`^8Vho#LnBF7Y#Qx41{#EAA8bi=T@J#Dn61_)qbW_=R{_JR%N?Uy4V?e~HJ$Ja~#9{HQI3k`C&x_w+L*=(v$No;dBwiLr#Vg|X;#KjQ_=7lxh0W{Y zPvQ;nrg%&ISsWLC5hujk;vMm>cu)LQyf6MHPKv*a55$M!l=w(|EdC)r5&smY#i!zo z_)L5*zQ9QTFL6$MDZUct#jqGrX?>)sChW0VuqS3!ZCI5#u*2t6U8-C4s9rT#4N*g} zn-Q)?sFC-~sD)|~ zX4xfbsal5FWrbR)R;kr$jasYLVZAd+tyde=Ms>2J)XVI!$d=r>is6nQEIl zOP#IGQQOtI>O9thY8`myV7pqIurRp+ux!R$2sw>nkwOd`Ou2NU4J?a{D zt=emDn?GZQI=S7tp|7W~sj$$qqNA^Cprf;=uWQ4)-p%Wr9eo=HH+Bqk5D~PoXRu>n z72EXyr52{N4mK=3`bl z)=If+S4)Yy8mlB}?US^&Li$>v`&uK(HHNRvk{%jj(>64uJ9KqPMpu{NvyT~?^k~)n zY0{fj_oYcsw!S{y_j(!qdR=;_Bs+C-os3fIpvgS74oFk$m417rY3tQ3+D6GA)b$!1 zl#%F$E@9rJ!S=C4R>+T64Jw1W6dqbe} zhCn*pDA5345d-70-Q5AcJl$jHjxnP91HJc;p*sRqact~CCUU;m2D;a;ro_n{C~a}B z>sYb6r?*$u!p(k!o3eP+&D*h|x4UoE(CT#^18YZPD65n)l~w6xgKp}1TsB#!n{=~T zH(Ol3tf1Ijz5bOx+#mwd8R7F2z_xAa9^jT>?eF7OVja4iY5UOX0oiVBEBiMLkQm#_ zo{iGaV9zFE*ay2ec5`vtyL(ox9%4^@Jw`;*DQNWuwEFHYa&!)@?%yzoUVsQUBz|K< z$G}iG#~uW7bw}??a`LipKS!DFigMko(9KF`SI1Ddk*O}Ul+iqQ`V+`6e<%O4LFV~8 zt@R^ZYdh8t_>^*^ckm-!tNbZ9`U*csH@XZz(zU{$a-#$BcUNuvFpZoT($i)i>d=Qb z8}f*~!6HW|So9o(MNbV*1*Iow!xlR%x*If+ELeOjJqrzW?0p^jh-rf|hIb=&)N&d7 zdLzeC({+KJ9dbCfbsAz|(ZzHco{$0=0ct&49AwdBSZ7!^cj(y*RSa!Von^>g-IoJ3 z9RFOb8;y_~F(7jhqK4~5NH(d416KSS?lPXd#-Jevv=qGB zsDef|1dooi9lhKPLIOC&Bt67$Dxmuc4P>#m;L%~&h|6!1ptGVbm=Nd=(Z2D~H`?hg zF4;y6N;Xr2k}XxIqAnOmb%*E+hf>`I{c(p8iqh(({@I`5?g}71sNMn2s0Du0SNA{w z=|KVcJA0|03t*6Ve?~CN_vd(^fIsae4g47%s1QIyra$c^CHxt|tc5=(#9xj1(I>%4G9?V}Q$qEfnO7fz7YWwPhbcnss0p%&(g1R@YKwHVD zM7X}Op?|2mtFxCWPv3@ho!tX8;bq#nzI$Lrci#{bUiLcJ)3>U(n;Gu)9RuBcz1=IN zyNAgEnl!Pqt78z;pq|0COxf4>ZWv^nV@3bEbscOCTD^Jw>TW432(o(myQG&vj6$nr zIGW6{&4$U8v|u_Xz44SvdZP)QZo`aD`ook?`r|pBwDP1*dZbyMWUlD%?U!1(2fNqx zjFR@=?m=B^n%Bu(a;_Ta#uQD8Lk4ya4)y54y`7kot?eH2Ws18K^k`~=b@$O+@^%ca z=;>L}Gq7TVED;Z;mMDT1{R4U~Q;=?7gy@Z>U=Q<0Bl2)WLp{A+GMtl^HiZp^oI>~D z$|3)}?(XX{GB~JvozL#(BKFDhFgYqB*r+T%A0Y;3)RU{bx3_2gV2{i;*SZb8Lp|$z zH?tZ+T|FCnbp0IbdazVxHmO=%*jU8`O@kXMOA2+fNH>dldR$e;bYWFlv7-xfZdr|7 zsK28Wc`TaTB-b4!g>qh9Qe5J|grgs$Z~w+_Y3=Op?Y}$-Lz=uZK3^h*=lcO{{kFMUr{B|FfAybMd z%vdH5JpoM09r8&zRa{uaSzTOM$SX9Myh4M?E41RW$&&*D8w*Bk{0Zy?;%tcj7Qybs z^ZizwP1x~H9f2=+O@w_CenP3ouDuDnj`T+OrFf>%q%6n1WH2#+ghVcC6dryO;S6oCZYUB5d!vVx^uEg7|}!tCi~^w+Y|Ent>hG#rR%s z7xp~O9i1E3Dcd`HFJGrD?&=vFQufl?3j5eQ6*046MiQBjC4f|tC|c;|26)Hmo(;_1 z(16UFbn{l-yp6eZLL_jfkK#}v`6k`gigN@_@q)S@F63rKycDxZIjY>RJP8|KNe!@& z9Go>vDJpnEoI^Oujnm+gxgF;7Ft>^8fp?27z)!136jfamMEtEL+zb`ltfzr@s#jzC zZP;`*>}`nsc?I_h;FpQuniP(B!bgD`%i$9n*;?vGEw zRLY@Fe~vhWSWaQX7xKVIoZ4NSmTq%~>6qzJ(~I~$&9}qZ8JS;u0*(F0ATa2=7&rlu#5-T z4@PWLMeSs?b~|`S zJev2yi?F|4g}v-X#G$zM0qz3a4|oXhC}QB&!LiT6UiC_nvr zZfImeD``Rb%*D^De5`x{`J@9q@wWjd4wvIiuA7zLfup!^J;_y#u(;>sS_r@yy{jI8 z@U9t%%M6_-BCeU7$}I}r<$D;vOqf>X5&RV83H$`kMgIWayZD)v_wlocAhdi9t$jIK zhl-X%y@kU4L@D&uqs#d4`}*6`oZ3IeLHxm5*==au&Y_l`j$U0Cw@$Du)o#t%syArFa*^ z5}Z#j$2mzg{I7?6iltfk33OS{x?ID$>|kAf%(~pK{0*@`!0|r98a=BdIy0QP&SGb! z^9kqe3=^GA&I8Up&X=66fZ2crfYpG-fKJ`s7xamuIB^c|Jm|cY;a=xo2LEa2 zolb%+&YcX;JFj*Uz#XYNjlBF6pemC`K2@3ks?sp>kkSZHm4A&KSIz;*^*CI~_BqPn z3mF2qNe}xjT;FAXr(iq9wl`sW6SmVhkNp&2QqI8l=Kunqv>6rm zTLUZRqwc!n~`8`4fl9MM`s#(k!^V4Bd*5JDKQRPJ=t1%fFDma{wFa ztE?HLCHW`B@fu=(4H~`d?*py)QG<8!50Ty$Mb=^&bXHn3BS?!2|QmA zi<%ve8yXsq88t5!eZ(f*r~NVJ9I1Fx z@*ae{5B*FY>gz9XHu?y9z%q>VPhm88MmdZ#+at@)1`_J#Hr>`NV6?I-PT*$&#Ca5!yA z_&seab~M^5?Q3ik9rJ7%jzx~;_VxCSj$X$mTdpm}ahvUV+e`Kxw%2TLK*syFQ}!;~ zY1>)bu-)vq-tKVp+P(G&dz_=to?_3k=R@w-N_J@WE?x51$aQRW+-BcpzrubE$F~b9 zxyioQu@&Y%{O&@U?zcZ=f7E`){-ph|{RQ~nYCmc}W`E26j{T%#rTt^LoO37+&Ea%} zIHDX0jx2ct8SbSt95pKr(uj6tuEb@X`S3;Nk8% zZhyarC!4+ z)xf0jbPM$PCc<6;w=1E~R)o6>x?BzT7Tm7^{U3mB(C1pju^qhY06W0@HsCvuxf5Y; z0B;xK{4QWO_&0*T2fBO@{F^}EjIg&rms>&q0QS8I^F#Qh+3}BH-VQx}0=N_KQ@~w- zp8@WMzk2}p0`3D~R)g`{iP2P19vt}x?u{N-Fv~$ZQj~`w=Mlg`z%K#+1>R$T$6`s_lBv^BG-c*=7^)P$jcM#h{oqE`N!8-sr2zUbUG~jsvO40fn;0?eD!25tx z*3;Ir)?wR1o7v{Dd2JEUDaDrc|2qFz=l?_A*>+$GbqIO825Ec|=6b+Jz!d;0YXbP; z^4?uYph;8DPnfWrXP1u827+fl$V0P2J79muSOc@pq3;0)j# zcnUxRH~}GmC_n-r4UhvUw3kyjd!y9LKM$x5+1mi~B$!c_RF~|_0VrFBUYG+qY=XH} zf}x{*o7B~QJ@~r;sAH5j_S*pa0e1r)(BUzd4+F?VKH85UEY+L;2f#8R7f;uO5guO1 z`0wbauW-y|q>7Qg*&yrotVmz5~6Jz8x_*IN?mlpOG!npl{P`GDLVM~~goCYV3F>(a<`HVkd zjB*6$IrdM_2MBS9?KiN!hwUra&K$fegQTqGP$)0hzt46X+jH6eE5;`n|CO*x>kuJ0 zjcO~~zhe9n<7*iwF<#90KEf)Va6zcKj5!AMuf%C)Eam32{R+m3jPD|BIzSlDi~#cp zAp~kU!hVm@KZ({p-#$AL}nXU}7E5pp^QdXp&2<8C6XANP~M&{7?C{&r2PPTKN zh`nr|!G2b-o$HTj2itoIn`#MTeM~W&X57Ho#5kQWc7n*Yl5s!dA2OC{NBckwG~-2S zGVWp5X>5O;@vV$+X8a{#Jc~^J(Qbf`F@BaYS{OJiU2qI4*GcRgQ7Bp8cCw$Bne#l` zY4jB0kIac>`(effghv)I=DMeT$TjLC!gzXuYTY8j>K_Pa*AvF=JhK0pu!(h3hnUatIDP+T2rSNAFJGd{)mG~=__on9%tIJI1<35^ly8;`VDjZn)0IE!O3@sk$DwQLo00)7`jLx(_!;58!s_A>05x zid&v1aFg>BaTfP8ZMcIOg?pA+xJy~7*5iicY}|rej+>6_)lKTv>JD|cNl|ZA_o;WQ z2h>N^L+bPDQT288gnCl_#N;rAnG)2q>RoaV9rXo!eYBg7XA>y>X^drGn#y+W&G@M( zJi*Q!>cds6cP6lziB&hzxmZ1uN$;P)W+T?%g;@6#V-;S?tMCe}!K<*+iGr&K`#!Z; zTNh$4ay%bY4#KjR%R^Xbzm(`>x_L<8M5I>L%~&Vi%isXyM=Vux>uBn@4r?xNc(a zoBh$AJ^Y(#SCz~N-AvQXV%@CQO}k%{1N2kn*s1!ucU`b+eG;RdIj% zIQvv_bNYbJdsN6+RorrZk55-Dh=opI9Eww?u{7|b>D)@5#n^F{B>h;CbN)P`Eyb;V z;XZ-dfgOMMS1_mQfYNlo0edZ=3D64qE$QaQiGYT1+C)H;qH24g3+pzL$ri-|d%f1CH9=#X>>x&AxrNFB5DN}$mTmC4k~t`2TZn6(tzAn% zEKypDhT7|SPqAuQTD~<&E7hv4InY*hw>t1pv*oN}ww$({)>Qc8xUiEgv_l*hJq?8p zM+-qqqun-v{SoF^Ub4L8$AJde!4}%}94a1ugykL3n@Bf6vW(e`cBjd<0Nr3mJvYCo z`+?rp?I=|wJK(2U*Mn;v^HZ&hz^xziQ>{(lHjMeH)_iaq$NW@l6u6Ve{4k(`+cf5< zYNx<$9`jSter?#n4*aRwA#mxWhJN(^G5V?6z2N?9%um&B0{7gQpQ>#Ici)(ws;vh1 zjxj%~X*S+pq&-ICr=l*C-!J@rci=3jPqCRlFn?nH-29bAwb(3fOBhNDd1jesS!vm1 zxgMuz4_FRa&_AJk9XM(F1Us0YVh{5(Xnqdye}Pge#_11^;lB2#TAhj)r(0k9L$16J zUo*b`2VaNaYu4BQ;A=1RGXFO}RU1NFU0?r0Ty5~x{q;Zi%7U+zU;o3)9%m>qmW^75 zCBb~wJZ$MQpR|}QZ)poG4(&EehWP}}F(;}!&8I9=Em7w8EbZn`aGJTxj4>`E1R-~5 z4)c5FC(VZ~Ipzn~;)BKpF$$W)nqvaa&)d;%- zVYgeJH{WlbYHl+>Y_2rVv*cRdFfX#4f*#9JgU*<{#9QWC^RRifd8@@{uD4WMTFmG> zZM&2-Ym2oF`$kJ`ZPu06KI=y7R_k`_F6%AU+pTw5AFv*@K50E-eaU*vw!nJa`o8sJ z>*v_v(QIz)?j+bUY};)4wsPANFt2$X8Q;Bv)HWGjd{jT^x*sRWPdZ<8zTrIS{M=<$ zY%ay+cE!1JT$QdC*F0AzI7?lwVW5x9aw~6BL^} z#+~IZcQ?7)-OJs5?km9Az;fM=Dpq~xNr1q1@Ac0a)pK-9=0sc7SA<`$y@CH*!?*;+dK)L3{O7d$@P@G zPbn7ffagWe8P8W<%mTf)cq={YJJp-N)&lQle6!DREX3r)| zyC=eOJK3PoHJ&&{^JaLi_T23`;Ca+ri5Q|hd%Y>1{T|GYy~WV~2(&$BSqPVW&r#1C zp5>m^ip6uxbHek1r_0leJo0jzt>-+PjJZWKa&a!_AGKX-$5!uB?`r5g?A5$(Z-k8@>p|=w8P4&)J9Nrz?J>G@h<&eGJRqNg4z1qAF zrR>0rEd_dK;U{<7 zom}@Y{vP9-p{a_SQxx_V=KO&1UaUV=WiQ)*$kK1aYE;E}7sc=+#=CHeEIfw*PXi7E zjsTtqpbz!D2tePAdL%r*2fPM220#n&ApIVs-h(-=2Q9(#4gjse^FH7t-~#}9PtV5y zv=Gl}0LFOF=YX?-bAYb^!)Sw%XpuB$CKGJ~IXDv_O`_vK)7+d)nr$b;B>$-}Q*|>9 zW;*C}m>DoBTo%kMn7J@>b(8pcx_drMv>|}>M`pH8lfOdUUlB~YLs9~>1ZF8rijPe4 zSK((?fUX2xshi|p1)B7&hFPtf#IMoAk$!ZV|8t#wT{mx2xNOBc=xbE*9^>~JpJe<2 zu$f~ef3%nJQ=ISLjT6cTlmpyb{}=X_pTv6fIo#xBe5LyBL;Q93~^FFXyO)(_lDu8;uaR}KDf|R$Lapa9*q_8tus$@N{tnt7#jOGXeclFs5Ap>xK;6M@f{%bd#+s7u?$C(; zFX6zz)J;2DA>PZJMA_s!^r{hHMS44oxbF`Oc`N2jh)M&F8Q&u zo$_EQ%7gec8(50e*igq)(B5btjCxN>A^l`3lVLNDQepwp)BsH{VRH`AVm3ISamThn zEY{tZ=YIIrQ0k}awb7OyFgLhly2RiG#|AR6wPMY4f%mXKObetqZ}TU zCn-aoqzrkIGUQ3hkS8fa9#cMfk}~9l1jv(=Ax~0(U;Q{g_ zWyq71Ax~0~J( zBxT5xlp#-2hCE3b@+4)*W6CE_QieRNef-K#QieQ98S*4$$di;IPf~_FrhM`wWytdc z$di;IPf~_FNg47aWyq71A&)7aJV_byyaDngWyq71Ax~0ba zd6F{ZNy?BXDMOy540)0=x&*UCGiEB}a)3E; zm}inpJnq1enSgt6WG3P68=0w?_mP=~IVhP~c*=v!Y?eqfrN1y;hWY8J2E_k4^CNLf zmHfwIrbuQk=8Mwb8@fp|E}Dt|RW~1oN$Z7!Y$hnbWHSl#MyYuQOCkxcvP-`5M>Y#_ zV@^u=vu?h_W*p|F#IM9`)&etd=#Vx`SFl!f~e(w5CSlSI;)%s=Zc zx%9LF`;KS*$&KEJOX)eueyed8kHTasAF^49o3=#f;J!bZk@)sCnN`Z2Y-V6COa|j?^TRQ$!&?)Hx(my5(S2PQFVq+n1bV)>m?5 zJcfMYJ)!$b!`gzhk}IhD5eKF4ZjLKjxtGmC+(@PvaKtWac1o?^2=d78~anK`(zDPwq<%}m_h zlrd!T3W#R@w0evEZ__$@y6m6YE$AI)D&J&$1>-9jZ)JQHMT?u=h4rEby&FX6`xnoO9p%KJS-2JA1FP*ZS|Z*52gd#{(iL2mza60)v^u zrh9o}d>1L_Ux#6KU4X%054`>SEV5+qKA4Fz5{9bB`CtP4LB0tLdu}(_kN5ZS^)sDn zY68Q+_kr|ceN$6fDv1_u%J~fFqm0+cr2A&WA5z zgLDu`FOQ7n3d@(=c7p}23xk>X<725pHtH%86qyLY$JjV(EWI~i!Xl6!1mVKj@rm4# zEZ8P+J)jMk1>ewK4f7BzIPn}vFXw~yUhF$h1L<2Z6Q7IVN?|Zlld)T74}O(vSH89kl^b2r~IdOR7n#hf#GJjGOP{`2VZRM?hrTVZfm zJd6uA3m67Qg~h=V!BG&*8-|9_VN4hg76WoQuwOv#CYUYE4z>lh-gvYL99zIVLA>!W z8mMalTLp^*EpcINmTH08gW9p6Y&C2HXk`Ov(H6Am3iF2{z}p`j z{T0t&(HLS`|KFl<1^xPf`d%6MH-Nnz z%n9@r3u0q|^9{8aU@tUYhaoO|usMKF2N2)p|5Z$X#ccs1F^nMeENfZJQ&{?V~+tK@^H}Oe~l&@CIaOwuvviK1HjyD2cIFZVAxJj%R-)t4~f+i zk)U)HsAZTpDr_A{(ZCsOu*HInVLW>U$c-|_VCc^f4;#!=BA5YJP=W+$!yH?H@!SAD zw}Vt1h}+O^ASmO4bK{IH`-5}o;BB}DLz~_pLJla60q-af{g3v3%$i}o4f%#zhFD^a ztr}|mXwfiJV2myt|E;6zfo|W)mTp)xw*hbL2LsNC2QzNCenTuw(8>;Q&2TVg7R~!F z&cAFj8o`dgYZ_+IF!zSBG1fagr{!DI8<1mIlZMgxv63x7{Du*a1)Je26OBC@at!PC z$2$6Pb%~&V!xd1$h#JZb4oDFsVTE~Vljt8sO5Ea!Ji^XUk5ujf~dp~Oa z824SEP9oU2U^A=-!%TXD`#1>PC1|j6ESOVNPgvo3r$EVHvHo*AKd$>JTHQbBWbv={6ITDR;Xd6Fu)ZH z!1Wr|=3jT-kM(GnVZ#VVfc(Gai35(gpd~|H3>cL_ut$JVHPrpbmIJ}qh8uGYEg0tQ zzdvORPZGmscvc$b_Fko-E=dHlr%a}H# z3~}Hj1b7kz8PlF%e$k)~9Haxl^U!dvVa^Tr9s=b07|#eW9{(uw17(K#1hC%; zN)2@kZPP(iKSswePKKwUVNDy>zTxWP!Leb4V?nNAgbk4!t{(%A4CDEKKdu(WC)7XA zNuqHs!a?hX`ym{(YPbV`+`UwA@BEkx!+dc-9EMT<>$z`;&`{Gb+lJ^2rG|Uque-!h zZdji`?x#3V`s2y+<0)f^fd|?$T*r^+v*Bv~PqVrK)cMDscZnck!_2ZlZXy^PLu@f% zZx}fySi=agb_2n;1Ms~HY-V6P1vYaSEE#Nu?=Rpdp^5Pu&_TmbXk)nGBnbjn#X;!nW=2$JXvaqtY+F<2q z39PcMa;++?c3bVYs<*mn_1b!z^-Sye)@!U!Sa(==S>If4ZS$+mZ#HLb&f7HDG~0C8 z^w~VJdA-7H#n=@SR!mzlZ^g0|8&`O(h+mPsV)u%=m8L6atz5X$ZKcOb?8?-Y@|DFa z_pG*GUBCM4+Hq?at}Wf*x}jpjyN$nZ{Az1zyUkW@J7TxOZl&EuyKpR$N!xL z{aAZ*!H4ig;aJ1lgtcCc|+?_lrX?BMPY-~e}^I8YtL4l;*Ihy4zR91c62a5(J%Ip`f4 z9GVaO!dDclzQy-g&n3O6N_^ z+njefhdT?MrOpcHBIgQcjq@Joea`2cZ#my{e(3zd`Lpv^=V2EU7c-Z!F7sX1xNLFR z>4J8_xsY7QE=-p)mtS4ZyWDWO<1*;-#^q0!4=!I_r@Ah1wQ^nS>g?*}igyij<+w^* zrLJn%3fDcZde=JFi>{5X*IaMAzHoiNb;{NmTjy+@zcpxU?$-9Lom+dhUfp_Y>+`Lz z-DbHhaognP>gMMb=mvK~xl!C`ZqaV>ZalYSw@kMjH-%e)TcO*2wELGz${M0>=0BzPS3IOU=9sP|~`xb89F@!8{xr@7|@ i9 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

- {/* Conditional divider when overflowing */} - {isOverflow && ( - - )} {/* Scrollable content area */}
((_, ref) => { >
{/* Main navigation section */} - + {mainButtons.map((config, index) => ( {renderNavButton(config, index, config.id === 'read' || config.id === 'automate')} @@ -238,14 +221,6 @@ const QuickAccessBar = forwardRef((_, ref) => { ))} - {/* Divider after main buttons (creates gap) */} - {middleButtons.length === 0 && ( - - )} - {/* Middle section */} {middleButtons.length > 0 && ( <> @@ -253,7 +228,7 @@ const QuickAccessBar = forwardRef((_, ref) => { size="xs" className="content-divider" /> - + {middleButtons.map((config, index) => ( {renderNavButton(config, index)} @@ -267,7 +242,7 @@ const QuickAccessBar = forwardRef((_, ref) => {
{/* Bottom section */} - + {bottomButtons.map((buttonConfig, index) => { // Handle help button with menu or direct action if (buttonConfig.id === 'help') { diff --git a/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx b/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx index 55b79b26c..38ed45484 100644 --- a/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx +++ b/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx @@ -13,7 +13,7 @@ */ import React, { useEffect, useRef, useState } from 'react'; -import { ActionIcon } from '@mantine/core'; +import { ActionIcon, Divider } from '@mantine/core'; import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded'; import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; import { useNavigationState, useNavigationActions } from '@app/contexts/NavigationContext'; @@ -195,6 +195,10 @@ const ActiveToolButton: React.FC = ({ setActiveButton, to className="button-text active current-tool-label" />
+
)}
diff --git a/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.css b/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.css index 2c4d3004a..6f0366fbc 100644 --- a/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.css +++ b/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.css @@ -38,9 +38,9 @@ /* Main container styles */ .quick-access-bar-main { background-color: var(--bg-muted); - width: 4rem; - min-width: 4rem; - max-width: 4rem; + width: 4.5rem; + min-width: 4.5rem; + max-width: 4.5rem; position: relative; z-index: 10; border-right: 1px solid var(--border-default); @@ -52,9 +52,9 @@ /* Rainbow mode container */ .quick-access-bar-main.rainbow-mode { background-color: var(--bg-muted); - width: 4rem; - min-width: 4rem; - max-width: 4rem; + width: 4.5rem; + min-width: 4.5rem; + max-width: 4.5rem; position: relative; z-index: 10; border-right: 1px solid var(--border-default); @@ -72,7 +72,7 @@ /* Header padding */ .quick-access-header { - padding: 1rem 0.5rem 0.5rem 0.5rem; + padding: 1rem 0.25rem 0.5rem 0.25rem; } .nav-header { @@ -84,14 +84,6 @@ gap: 0.5rem; } -/* Nav header divider */ -.nav-header-divider { - width: 3rem; - border-color: var(--color-gray-300); - margin-top: 0.5rem; - margin-bottom: 1rem; -} - /* All tools text styles */ .all-tools-text { margin-top: 0.75rem; @@ -116,16 +108,15 @@ .overflow-divider { width: 3rem; border-color: var(--color-gray-300); - margin: 0 0.5rem; + margin: 0 auto; + align-self: center; } /* Scrollable content area */ .quick-access-bar { - overflow-x: auto; - overflow-y: auto; - scrollbar-gutter: stable both-edges; - -webkit-overflow-scrolling: touch; - padding: 0 0.5rem 1rem 0.5rem; + overflow-x: hidden; + overflow-y: hidden; + padding: 0 0.25rem 1rem 0.25rem; } /* Scrollable content container */ @@ -143,21 +134,21 @@ text-rendering: optimizeLegibility; font-synthesis: none; text-align: center; - display: block; + width: 100%; } -/* Allow wrapping under the active top indicator; constrain to two lines */ +/* Allow wrapping under the active top indicator; constrain to three lines */ .current-tool-label { white-space: normal; overflow: hidden; - text-overflow: ellipsis; display: -webkit-box; - -webkit-line-clamp: 2; /* show up to two lines */ - line-clamp: 2; + -webkit-line-clamp: 3; /* show up to three lines */ + line-clamp: 3; -webkit-box-orient: vertical; - word-break: keep-all; - overflow-wrap: normal; - hyphens: manual; + word-break: break-all; + width: 100%; + box-sizing: border-box; + text-align: center; } .button-text.active { @@ -174,13 +165,14 @@ .content-divider { width: 3rem; border-color: var(--color-gray-300); - margin: 1rem 0; + margin: 1rem auto; + align-self: center; } /* Spacer */ .spacer { flex: 1; - margin-top: 1rem; + min-height: 1rem; } /* Config button text */ @@ -242,8 +234,6 @@ .current-tool-slot.visible { max-height: 8.25rem; /* icon + up to 3-line label + divider (132px) */ opacity: 1; - border-bottom: 1px solid var(--color-gray-300); - padding-bottom: 0.75rem; /* push border down for spacing */ margin-bottom: 1rem; } @@ -268,27 +258,9 @@ } } -/* Divider that animates growing from top */ +/* Divider under active tool indicator */ .current-tool-divider { width: 3rem; border-color: var(--color-gray-300); - margin: 0.5rem auto 0.5rem auto; - transform-origin: top; - animation: dividerGrowDown 350ms ease-out; - animation-fill-mode: both; -} - -@keyframes dividerGrowDown { - 0% { - transform: scaleY(0); - opacity: 0; - margin-top: 0; - margin-bottom: 0; - } - 100% { - transform: scaleY(1); - opacity: 1; - margin-top: 0.5rem; - margin-bottom: 0.5rem; - } + margin: 0.75rem auto 0; } diff --git a/frontend/src/core/components/shared/quickAccessBar/QuickAccessButton.tsx b/frontend/src/core/components/shared/quickAccessBar/QuickAccessButton.tsx new file mode 100644 index 000000000..c3ff23726 --- /dev/null +++ b/frontend/src/core/components/shared/quickAccessBar/QuickAccessButton.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { ActionIcon } from '@mantine/core'; +import FitText from '@app/components/shared/FitText'; + +interface QuickAccessButtonProps { + icon: React.ReactNode; + label: string; + isActive: boolean; + onClick?: (e: React.MouseEvent) => void; + href?: string; + ariaLabel: string; + textClassName?: 'button-text' | 'all-tools-text'; + backgroundColor?: string; + color?: string; + size?: 'sm' | 'md' | 'lg'; + className?: string; + component?: 'a' | 'button'; + dataTestId?: string; + dataTour?: string; +} + +const QuickAccessButton: React.FC = ({ + icon, + label, + isActive, + onClick, + href, + ariaLabel, + textClassName = 'button-text', + backgroundColor, + color, + size, + className, + component = 'button', + dataTestId, + dataTour, +}) => { + const buttonSize = size || (isActive ? 'lg' : 'md'); + const bgColor = backgroundColor || (isActive ? 'var(--icon-tools-bg)' : 'var(--icon-inactive-bg)'); + const textColor = color || (isActive ? 'var(--icon-tools-color)' : 'var(--icon-inactive-color)'); + + const actionIconProps = component === 'a' && href + ? { + component: 'a' as const, + href, + onClick, + 'aria-label': ariaLabel, + } + : { + onClick, + 'aria-label': ariaLabel, + }; + + return ( +
+ + {icon} + +
+ +
+
+ ); +}; + +export default QuickAccessButton; From d6a83fe6a1ef2a9997eddd62c0b032f3cccba733 Mon Sep 17 00:00:00 2001 From: Dario Ghunney Ware Date: Wed, 10 Dec 2025 19:46:48 +0000 Subject: [PATCH 33/56] Fix: SSO Login Page (#5220) Users logging in via OAuth2 were redirected to Spring's default login form instead of the React frontend login page. This happened because the OAuth2 configuration used `.loginPage("/oauth2")` which pointed to the old Thymeleaf template. ### 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. --- .../software/SPDF/config/OpenApiConfig.java | 3 +- .../configuration/SecurityConfiguration.java | 36 +++---------------- .../security/service/EmailService.java | 3 +- 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java index 514b9231c..c85e78b73 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java @@ -66,7 +66,8 @@ public class OpenApiConfig { if (swaggerServerUrl != null && !swaggerServerUrl.trim().isEmpty()) { server = new Server().url(swaggerServerUrl).description("API Server"); } else { - // Use relative path so Swagger uses the current browser origin to avoid CORS issues when accessing via different ports + // Use relative path so Swagger uses the current browser origin to avoid CORS issues + // when accessing via different ports server = new Server().url("/").description("Current Server"); } openAPI.addServersItem(server); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java index 2a0cd5734..257d243ea 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -197,7 +197,6 @@ public class SecurityConfiguration { http.csrf(CsrfConfigurer::disable); if (loginEnabledValue) { - boolean v2Enabled = appConfig.v2Enabled(); http.addFilterBefore( userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) @@ -205,19 +204,9 @@ public class SecurityConfiguration { .addFilterBefore(jwtAuthenticationFilter, UserAuthenticationFilter.class); http.sessionManagement( - sessionManagement -> { - if (v2Enabled) { + sessionManagement -> sessionManagement.sessionCreationPolicy( - SessionCreationPolicy.STATELESS); - } else { - sessionManagement - .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) - .maximumSessions(10) - .maxSessionsPreventsLogin(false) - .sessionRegistry(sessionRegistry) - .expiredUrl("/login?logout=true"); - } - }); + SessionCreationPolicy.STATELESS)); http.authenticationProvider(daoAuthenticationProvider()); http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache())); @@ -300,18 +289,7 @@ public class SecurityConfiguration { if (securityProperties.isOauth2Active()) { http.oauth2Login( oauth2 -> { - // v1: Use /oauth2 as login page for Thymeleaf templates - if (!v2Enabled) { - oauth2.loginPage("/oauth2"); - } - - // v2: Don't set loginPage, let default OAuth2 flow handle it - oauth2 - /* - This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. - If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' - is set as true, else login fails with an error message advising the same. - */ + oauth2.loginPage("/login") .successHandler( new CustomOAuth2AuthenticationSuccessHandler( loginAttemptService, @@ -345,12 +323,8 @@ public class SecurityConfiguration { .saml2Login( saml2 -> { try { - // Only set login page for v1/Thymeleaf mode - if (!v2Enabled) { - saml2.loginPage("/saml2"); - } - - saml2.relyingPartyRegistrationRepository( + saml2.loginPage("/login") + .relyingPartyRegistrationRepository( saml2RelyingPartyRegistrations) .authenticationManager( new ProviderManager(authenticationProvider)) diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java index d4ecf8161..3ae079d0f 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java @@ -226,7 +226,8 @@ public class EmailService { @Async public void sendPasswordChangedNotification( - String to, String username, String newPassword, String loginUrl) throws MessagingException { + String to, String username, String newPassword, String loginUrl) + throws MessagingException { String subject = "Your Stirling PDF password has been updated"; String passwordSection = From 2cd4175689975f5ac05cd54108223471f0ef6b47 Mon Sep 17 00:00:00 2001 From: James Brunton Date: Thu, 11 Dec 2025 08:55:37 +0000 Subject: [PATCH 34/56] Fix Mac app not being able to open files with spaces in their name (#5218) # Description of Changes Fix #5189. Fix Mac app not being able to open files with spaces in their name, which was happening because the URL was not being decoded on input. --- frontend/src-tauri/src/lib.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/src-tauri/src/lib.rs b/frontend/src-tauri/src/lib.rs index cb8faf04b..a08587cc1 100644 --- a/frontend/src-tauri/src/lib.rs +++ b/frontend/src-tauri/src/lib.rs @@ -152,15 +152,27 @@ pub fn run() { } #[cfg(target_os = "macos")] RunEvent::Opened { urls } => { + use urlencoding::decode; + add_log(format!("📂 Tauri file opened event: {:?}", urls)); let mut added_files = false; for url in urls { let url_str = url.as_str(); if url_str.starts_with("file://") { - let file_path = url_str.strip_prefix("file://").unwrap_or(url_str); + let encoded_path = url_str.strip_prefix("file://").unwrap_or(url_str); + + // Decode URL-encoded characters (%20 -> space, etc.) + let file_path = match decode(encoded_path) { + Ok(decoded) => decoded.into_owned(), + Err(e) => { + add_log(format!("⚠️ Failed to decode file path: {} - {}", encoded_path, e)); + encoded_path.to_string() // Fallback to encoded path + } + }; + add_log(format!("📂 Processing opened file: {}", file_path)); - add_opened_file(file_path.to_string()); + add_opened_file(file_path); added_files = true; } } From 43eaa84a8fcb1d118492107ec55058f5a704be3c Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Thu, 11 Dec 2025 09:20:39 +0000 Subject: [PATCH 35/56] fix tooltips on tab (#5219) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- frontend/src/core/components/shared/Tooltip.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/core/components/shared/Tooltip.tsx b/frontend/src/core/components/shared/Tooltip.tsx index db6bce849..980d2cfe7 100644 --- a/frontend/src/core/components/shared/Tooltip.tsx +++ b/frontend/src/core/components/shared/Tooltip.tsx @@ -256,10 +256,11 @@ export const Tooltip: React.FC = ({ (children.props as any)?.onBlur?.(e); return; } + clearTimers(); if (!isPinned) setOpen(false); (children.props as any)?.onBlur?.(e); }, - [isPinned, setOpen, children.props] + [isPinned, setOpen, children.props, clearTimers] ); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { From e474cc76ad9f7e5df7620127f25abf23a4c84986 Mon Sep 17 00:00:00 2001 From: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:13:20 +0000 Subject: [PATCH 36/56] Improved static upgrade flow (#5214) image image image image image image image --- .../public/locales/en-GB/translation.toml | 22 ++ .../configSections/AdminPlanSection.tsx | 240 +------------ .../plan/AvailablePlansSection.tsx | 23 +- .../configSections/plan/LicenseKeySection.tsx | 273 ++++++++++++++ .../config/configSections/plan/PlanCard.tsx | 5 +- .../plan/StaticCheckoutModal.tsx | 338 ++++++++++++++++++ .../configSections/plan/StaticPlanSection.tsx | 322 +++++++++-------- .../constants/staticStripeLinks.ts | 56 +++ .../src/proprietary/utils/planTierUtils.ts | 40 +++ 9 files changed, 917 insertions(+), 402 deletions(-) create mode 100644 frontend/src/proprietary/components/shared/config/configSections/plan/LicenseKeySection.tsx create mode 100644 frontend/src/proprietary/components/shared/config/configSections/plan/StaticCheckoutModal.tsx create mode 100644 frontend/src/proprietary/constants/staticStripeLinks.ts create mode 100644 frontend/src/proprietary/utils/planTierUtils.ts diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index 9d9278922..9be190247 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -5569,6 +5569,28 @@ contactSales = "Contact Sales" contactToUpgrade = "Contact us to upgrade or customize your plan" maxUsers = "Max Users" upTo = "Up to" +getLicense = "Get Server License" +upgradeToEnterprise = "Upgrade to Enterprise" +selectPeriod = "Select Billing Period" +monthlyBilling = "Monthly Billing" +yearlyBilling = "Yearly Billing" +checkoutOpened = "Checkout Opened" +checkoutInstructions = "Complete your purchase in the Stripe tab. After payment, return here and refresh the page to activate your license. You will also receive an email with your license key." +activateLicense = "Activate Your License" + +[plan.static.licenseActivation] +checkoutOpened = "Checkout Opened in New Tab" +instructions = "Complete your purchase in the Stripe tab. Once your payment is complete, you will receive an email with your license key." +enterKey = "Enter your license key below to activate your plan:" +keyDescription = "Paste the license key from your email" +activate = "Activate License" +doLater = "I'll do this later" +success = "License Activated!" +successMessage = "Your license has been successfully activated. You can now close this window." + +[plan.static.billingPortal] +title = "Email Verification Required" +message = "You will need to verify your email address in the Stripe billing portal. Check your email for a login link." [plan.period] month = "month" diff --git a/frontend/src/proprietary/components/shared/config/configSections/AdminPlanSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/AdminPlanSection.tsx index 2c86c9ced..0b47cf148 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/AdminPlanSection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/AdminPlanSection.tsx @@ -1,5 +1,5 @@ import React, { useState, useCallback, useEffect, useMemo } from 'react'; -import { Divider, Loader, Alert, Group, Text, Collapse, Button, TextInput, Stack, Paper, SegmentedControl, FileButton } from '@mantine/core'; +import { Divider, Loader, Alert } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import { usePlans } from '@app/hooks/usePlans'; import licenseService, { PlanTierGroup, mapLicenseToTier } from '@app/services/licenseService'; @@ -7,30 +7,25 @@ import { useCheckout } from '@app/contexts/CheckoutContext'; import { useLicense } from '@app/contexts/LicenseContext'; import AvailablePlansSection from '@app/components/shared/config/configSections/plan/AvailablePlansSection'; import StaticPlanSection from '@app/components/shared/config/configSections/plan/StaticPlanSection'; +import LicenseKeySection from '@app/components/shared/config/configSections/plan/LicenseKeySection'; import { alert } from '@app/components/toast'; -import LocalIcon from '@app/components/shared/LocalIcon'; import { InfoBanner } from '@app/components/shared/InfoBanner'; import { useLicenseAlert } from '@app/hooks/useLicenseAlert'; -import { isSupabaseConfigured } from '@app/services/supabaseClient'; import { getPreferredCurrency, setCachedCurrency } from '@app/utils/currencyDetection'; import { useLoginRequired } from '@app/hooks/useLoginRequired'; import LoginRequiredBanner from '@core/components/shared/config/LoginRequiredBanner'; +import { isSupabaseConfigured } from '@app/services/supabaseClient'; const AdminPlanSection: React.FC = () => { const { t, i18n } = useTranslation(); const { loginEnabled, validateLoginEnabled } = useLoginRequired(); const { openCheckout } = useCheckout(); - const { licenseInfo, refetchLicense } = useLicense(); + const { licenseInfo } = useLicense(); const [currency, setCurrency] = useState(() => { // Initialize with auto-detected currency on first render return getPreferredCurrency(i18n.language); }); const [useStaticVersion, setUseStaticVersion] = useState(false); - const [showLicenseKey, setShowLicenseKey] = useState(false); - const [licenseKeyInput, setLicenseKeyInput] = useState(''); - const [savingLicense, setSavingLicense] = useState(false); - const [inputMethod, setInputMethod] = useState<'text' | 'file'>('text'); - const [licenseFile, setLicenseFile] = useState(null); const { plans, loading, error, refetch } = usePlans(currency); const licenseAlert = useLicenseAlert(); @@ -43,69 +38,6 @@ const AdminPlanSection: React.FC = () => { } }, [error]); - const handleSaveLicense = async () => { - // Block save if login is disabled - if (!validateLoginEnabled()) { - return; - } - - try { - setSavingLicense(true); - - let response; - - if (inputMethod === 'file' && licenseFile) { - // Upload file - response = await licenseService.saveLicenseFile(licenseFile); - } else if (inputMethod === 'text' && licenseKeyInput.trim()) { - // Save key string (allow empty string to clear/remove license) - response = await licenseService.saveLicenseKey(licenseKeyInput.trim()); - } else { - alert({ - alertType: 'error', - title: t('admin.error', 'Error'), - body: t('admin.settings.premium.noInput', 'Please provide a license key or file'), - }); - return; - } - - if (response.success) { - // Refresh license context to update all components - await refetchLicense(); - - const successMessage = inputMethod === 'file' - ? t('admin.settings.premium.file.successMessage', 'License file uploaded and activated successfully') - : t('admin.settings.premium.key.successMessage', 'License key activated successfully'); - - alert({ - alertType: 'success', - title: t('success', 'Success'), - body: successMessage, - }); - - // Clear inputs - setLicenseKeyInput(''); - setLicenseFile(null); - setInputMethod('text'); // Reset to default - } else { - alert({ - alertType: 'error', - title: t('admin.error', 'Error'), - body: response.error || t('admin.settings.saveError', 'Failed to save license'), - }); - } - } catch (error) { - console.error('Failed to save license:', error); - alert({ - alertType: 'error', - title: t('admin.error', 'Error'), - body: t('admin.settings.saveError', 'Failed to save license'), - }); - } finally { - setSavingLicense(false); - } - }; - const currencyOptions = [ { value: 'gbp', label: 'British pound (GBP, £)' }, { value: 'usd', label: 'US dollar (USD, $)' }, @@ -280,169 +212,7 @@ const AdminPlanSection: React.FC = () => { {/* License Key Section */} -
- - - - - } - > - - {t('admin.settings.premium.licenseKey.info', 'If you have a license key or certificate file from a direct purchase, you can enter it here to activate premium or enterprise features.')} - - - - {/* Severe warning if license already exists */} - {licenseInfo?.licenseKey && ( - } - title={t('admin.settings.premium.key.overwriteWarning.title', '⚠️ Warning: Existing License Detected')} - > - - - {t('admin.settings.premium.key.overwriteWarning.line1', 'Overwriting your current license key cannot be undone.')} - - - {t('admin.settings.premium.key.overwriteWarning.line2', 'Your previous license will be permanently lost unless you have backed it up elsewhere.')} - - - {t('admin.settings.premium.key.overwriteWarning.line3', 'Important: Keep license keys private and secure. Never share them publicly.')} - - - - )} - - {/* Show current license source */} - {licenseInfo?.licenseKey && ( - } - > - - - {t('admin.settings.premium.currentLicense.title', 'Active License')} - - - {licenseInfo.licenseKey.startsWith('file:') - ? t('admin.settings.premium.currentLicense.file', 'Source: License file ({{path}})', { - path: licenseInfo.licenseKey.substring(5) - }) - : t('admin.settings.premium.currentLicense.key', 'Source: License key')} - - - {t('admin.settings.premium.currentLicense.type', 'Type: {{type}}', { - type: licenseInfo.licenseType - })} - - - - )} - - {/* Input method selector */} - { - setInputMethod(value as 'text' | 'file'); - // Clear opposite input when switching - if (value === 'text') setLicenseFile(null); - if (value === 'file') setLicenseKeyInput(''); - }} - data={[ - { - label: t('admin.settings.premium.inputMethod.text', 'License Key'), - value: 'text' - }, - { - label: t('admin.settings.premium.inputMethod.file', 'Certificate File'), - value: 'file' - } - ]} - disabled={!loginEnabled || savingLicense} - /> - - {/* Input area */} - - - {inputMethod === 'text' ? ( - /* Existing text input */ - setLicenseKeyInput(e.target.value)} - placeholder={licenseInfo?.licenseKey || '00000000-0000-0000-0000-000000000000'} - type="password" - disabled={!loginEnabled || savingLicense} - /> - ) : ( - /* File upload */ -
- - {t('admin.settings.premium.file.label', 'License Certificate File')} - - - {t('admin.settings.premium.file.description', 'Upload your .lic or .cert license file')} - - - {(props) => ( - - )} - - {licenseFile && ( - - {t('admin.settings.premium.file.selected', 'Selected: {{filename}} ({{size}})', { - filename: licenseFile.name, - size: (licenseFile.size / 1024).toFixed(2) + ' KB' - })} - - )} -
- )} - - - - -
-
-
-
-
+
); }; diff --git a/frontend/src/proprietary/components/shared/config/configSections/plan/AvailablePlansSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/plan/AvailablePlansSection.tsx index a3b8800d1..9aed2ff7d 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/plan/AvailablePlansSection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/plan/AvailablePlansSection.tsx @@ -5,6 +5,7 @@ import licenseService, { PlanTier, PlanTierGroup, LicenseInfo, mapLicenseToTier import PlanCard from '@app/components/shared/config/configSections/plan/PlanCard'; import FeatureComparisonTable from '@app/components/shared/config/configSections/plan/FeatureComparisonTable'; import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; +import { isCurrentTier as checkIsCurrentTier, isDowngrade as checkIsDowngrade } from '@app/utils/planTierUtils'; interface AvailablePlansSectionProps { plans: PlanTier[]; @@ -43,28 +44,12 @@ const AvailablePlansSection: React.FC = ({ // Determine if the current tier matches (checks both Stripe subscription and license) const isCurrentTier = (tierGroup: PlanTierGroup): boolean => { - // Check license tier match - if (currentTier && tierGroup.tier === currentTier) { - return true; - } - return false; + return checkIsCurrentTier(currentTier, tierGroup.tier); }; // Determine if selecting this plan would be a downgrade const isDowngrade = (tierGroup: PlanTierGroup): boolean => { - if (!currentTier) return false; - - // Define tier hierarchy: enterprise > server > free - const tierHierarchy: Record = { - 'enterprise': 3, - 'server': 2, - 'free': 1 - }; - - const currentLevel = tierHierarchy[currentTier] || 0; - const targetLevel = tierHierarchy[tierGroup.tier] || 0; - - return currentLevel > targetLevel; + return checkIsDowngrade(currentTier, tierGroup.tier); }; return ( @@ -103,7 +88,7 @@ const AvailablePlansSection: React.FC = ({ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', - marginBottom: '0.5rem', + marginBottom: '0.1rem', }} > {groupedPlans.map((group) => ( diff --git a/frontend/src/proprietary/components/shared/config/configSections/plan/LicenseKeySection.tsx b/frontend/src/proprietary/components/shared/config/configSections/plan/LicenseKeySection.tsx new file mode 100644 index 000000000..e5e90d048 --- /dev/null +++ b/frontend/src/proprietary/components/shared/config/configSections/plan/LicenseKeySection.tsx @@ -0,0 +1,273 @@ +import React, { useState } from 'react'; +import { Button, Collapse, Alert, TextInput, Paper, Stack, Group, Text, SegmentedControl, FileButton } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { alert } from '@app/components/toast'; +import { LicenseInfo } from '@app/services/licenseService'; +import licenseService from '@app/services/licenseService'; +import { useLicense } from '@app/contexts/LicenseContext'; +import { useLoginRequired } from '@app/hooks/useLoginRequired'; + +interface LicenseKeySectionProps { + currentLicenseInfo?: LicenseInfo; +} + +const LicenseKeySection: React.FC = ({ currentLicenseInfo }) => { + const { t } = useTranslation(); + const { refetchLicense } = useLicense(); + const { loginEnabled, validateLoginEnabled } = useLoginRequired(); + const [showLicenseKey, setShowLicenseKey] = useState(false); + const [licenseKeyInput, setLicenseKeyInput] = useState(''); + const [savingLicense, setSavingLicense] = useState(false); + const [inputMethod, setInputMethod] = useState<'text' | 'file'>('text'); + const [licenseFile, setLicenseFile] = useState(null); + + const handleSaveLicense = async () => { + // Block save if login is disabled + if (!validateLoginEnabled()) { + return; + } + + try { + setSavingLicense(true); + + let response; + + if (inputMethod === 'file' && licenseFile) { + // Upload file + response = await licenseService.saveLicenseFile(licenseFile); + } else if (inputMethod === 'text' && licenseKeyInput.trim()) { + // Save key string + response = await licenseService.saveLicenseKey(licenseKeyInput.trim()); + } else { + alert({ + alertType: 'error', + title: t('admin.error', 'Error'), + body: t('admin.settings.premium.noInput', 'Please provide a license key or file'), + }); + return; + } + + if (response.success) { + // Refresh license context to update all components + await refetchLicense(); + + const successMessage = + inputMethod === 'file' + ? t('admin.settings.premium.file.successMessage', 'License file uploaded and activated successfully') + : t('admin.settings.premium.key.successMessage', 'License key activated successfully'); + + alert({ + alertType: 'success', + title: t('success', 'Success'), + body: successMessage, + }); + + // Clear inputs + setLicenseKeyInput(''); + setLicenseFile(null); + setInputMethod('text'); // Reset to default + } else { + alert({ + alertType: 'error', + title: t('admin.error', 'Error'), + body: response.error || t('admin.settings.saveError', 'Failed to save license'), + }); + } + } catch (error) { + console.error('Failed to save license:', error); + alert({ + alertType: 'error', + title: t('admin.error', 'Error'), + body: t('admin.settings.saveError', 'Failed to save license'), + }); + } finally { + setSavingLicense(false); + } + }; + + return ( +
+ + + + + }> + + {t( + 'admin.settings.premium.licenseKey.info', + 'If you have a license key or certificate file from a direct purchase, you can enter it here to activate premium or enterprise features.' + )} + + + + {/* Severe warning if license already exists */} + {currentLicenseInfo?.licenseKey && ( + } + title={t('admin.settings.premium.key.overwriteWarning.title', '⚠️ Warning: Existing License Detected')} + > + + + {t( + 'admin.settings.premium.key.overwriteWarning.line1', + 'Overwriting your current license key cannot be undone.' + )} + + + {t( + 'admin.settings.premium.key.overwriteWarning.line2', + 'Your previous license will be permanently lost unless you have backed it up elsewhere.' + )} + + + {t( + 'admin.settings.premium.key.overwriteWarning.line3', + 'Important: Keep license keys private and secure. Never share them publicly.' + )} + + + + )} + + {/* Show current license source */} + {currentLicenseInfo?.licenseKey && ( + } + > + + + {t('admin.settings.premium.currentLicense.title', 'Active License')} + + + {currentLicenseInfo.licenseKey.startsWith('file:') + ? t('admin.settings.premium.currentLicense.file', 'Source: License file ({{path}})', { + path: currentLicenseInfo.licenseKey.substring(5), + }) + : t('admin.settings.premium.currentLicense.key', 'Source: License key')} + + + {t('admin.settings.premium.currentLicense.type', 'Type: {{type}}', { + type: currentLicenseInfo.licenseType, + })} + + + + )} + + {/* Input method selector */} + { + setInputMethod(value as 'text' | 'file'); + // Clear opposite input when switching + if (value === 'text') setLicenseFile(null); + if (value === 'file') setLicenseKeyInput(''); + }} + data={[ + { + label: t('admin.settings.premium.inputMethod.text', 'License Key'), + value: 'text', + }, + { + label: t('admin.settings.premium.inputMethod.file', 'Certificate File'), + value: 'file', + }, + ]} + disabled={!loginEnabled || savingLicense} + /> + + {/* Input area */} + + + {inputMethod === 'text' ? ( + /* Text input */ + setLicenseKeyInput(e.target.value)} + placeholder={currentLicenseInfo?.licenseKey || '00000000-0000-0000-0000-000000000000'} + type="password" + disabled={!loginEnabled || savingLicense} + /> + ) : ( + /* File upload */ +
+ + {t('admin.settings.premium.file.label', 'License Certificate File')} + + + {t('admin.settings.premium.file.description', 'Upload your .lic or .cert license file')} + + + {(props) => ( + + )} + + {licenseFile && ( + + {t('admin.settings.premium.file.selected', 'Selected: {{filename}} ({{size}})', { + filename: licenseFile.name, + size: (licenseFile.size / 1024).toFixed(2) + ' KB', + })} + + )} +
+ )} + + + + +
+
+
+
+
+ ); +}; + +export default LicenseKeySection; diff --git a/frontend/src/proprietary/components/shared/config/configSections/plan/PlanCard.tsx b/frontend/src/proprietary/components/shared/config/configSections/plan/PlanCard.tsx index ab56fdad3..b2dce9c65 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/plan/PlanCard.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/plan/PlanCard.tsx @@ -6,6 +6,7 @@ import { PricingBadge } from '@app/components/shared/stripeCheckout/components/P import { PriceDisplay } from '@app/components/shared/stripeCheckout/components/PriceDisplay'; import { calculateDisplayPricing } from '@app/components/shared/stripeCheckout/utils/pricingUtils'; import { getBaseCardStyle } from '@app/components/shared/stripeCheckout/utils/cardStyles'; +import { isEnterpriseBlockedForFree as checkIsEnterpriseBlockedForFree } from '@app/utils/planTierUtils'; interface PlanCardProps { planGroup: PlanTierGroup; @@ -83,7 +84,7 @@ const PlanCard: React.FC = ({ planGroup, isCurrentTier, isDowngra const isEnterprise = planGroup.tier === 'enterprise'; // Block enterprise for free tier users (must have server first) - const isEnterpriseBlockedForFree = isEnterprise && currentTier === 'free'; + const isEnterpriseBlockedForFree = checkIsEnterpriseBlockedForFree(currentTier, planGroup.tier); // Calculate "From" pricing - show yearly price divided by 12 for lowest monthly equivalent const { displayPrice, displaySeatPrice, displayCurrency } = calculateDisplayPricing( @@ -174,7 +175,7 @@ const PlanCard: React.FC = ({ planGroup, isCurrentTier, isDowngra withArrow > + + + + )} + + {licenseActivated && ( + + + + )} + + ); + + default: + return null; + } + }; + + const canGoBack = stageHistory.length > 0 && stage !== 'license-activation'; + + return ( + + {canGoBack && ( + + + + )} + + {getModalTitle()} + + + } + size={isMobile ? '100%' : 600} + centered + radius="lg" + withCloseButton={true} + closeOnEscape={true} + closeOnClickOutside={false} + fullScreen={isMobile} + zIndex={Z_INDEX_OVER_CONFIG_MODAL} + > + {renderContent()} + + ); +}; + +export default StaticCheckoutModal; diff --git a/frontend/src/proprietary/components/shared/config/configSections/plan/StaticPlanSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/plan/StaticPlanSection.tsx index ba937263a..2847ef94e 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/plan/StaticPlanSection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/plan/StaticPlanSection.tsx @@ -1,20 +1,16 @@ -import React, { useState, useEffect } from 'react'; -import { Card, Text, Group, Stack, Badge, Button, Collapse, Alert, TextInput, Paper, Loader, Divider } from '@mantine/core'; +import React, { useState } from 'react'; +import { Card, Text, Stack, Button, Collapse, Divider, Tooltip } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import LocalIcon from '@app/components/shared/LocalIcon'; -import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; -import { useRestartServer } from '@app/components/shared/config/useRestartServer'; -import { useAdminSettings } from '@app/hooks/useAdminSettings'; -import PendingBadge from '@app/components/shared/config/PendingBadge'; import { alert } from '@app/components/toast'; import { LicenseInfo, mapLicenseToTier } from '@app/services/licenseService'; import { PLAN_FEATURES, PLAN_HIGHLIGHTS } from '@app/constants/planConstants'; import FeatureComparisonTable from '@app/components/shared/config/configSections/plan/FeatureComparisonTable'; - -interface PremiumSettingsData { - key?: string; - enabled?: boolean; -} +import StaticCheckoutModal from '@app/components/shared/config/configSections/plan/StaticCheckoutModal'; +import LicenseKeySection from '@app/components/shared/config/configSections/plan/LicenseKeySection'; +import { STATIC_STRIPE_LINKS } from '@app/constants/staticStripeLinks'; +import { PricingBadge } from '@app/components/shared/stripeCheckout/components/PricingBadge'; +import { getBaseCardStyle } from '@app/components/shared/stripeCheckout/utils/cardStyles'; +import { isCurrentTier as checkIsCurrentTier, isDowngrade as checkIsDowngrade, isEnterpriseBlockedForFree } from '@app/utils/planTierUtils'; interface StaticPlanSectionProps { currentLicenseInfo?: LicenseInfo; @@ -22,38 +18,45 @@ interface StaticPlanSectionProps { const StaticPlanSection: React.FC = ({ currentLicenseInfo }) => { const { t } = useTranslation(); - const [showLicenseKey, setShowLicenseKey] = useState(false); const [showComparison, setShowComparison] = useState(false); - // Premium/License key management - const { restartModalOpened, showRestartModal, closeRestartModal, restartServer } = useRestartServer(); - const { - settings: premiumSettings, - setSettings: setPremiumSettings, - loading: premiumLoading, - saving: premiumSaving, - fetchSettings: fetchPremiumSettings, - saveSettings: savePremiumSettings, - isFieldPending, - } = useAdminSettings({ - sectionName: 'premium', - }); + // Static checkout modal state + const [checkoutModalOpened, setCheckoutModalOpened] = useState(false); + const [selectedPlan, setSelectedPlan] = useState<'server' | 'enterprise'>('server'); + const [isUpgrade, setIsUpgrade] = useState(false); - useEffect(() => { - fetchPremiumSettings(); - }, []); - - const handleSaveLicense = async () => { - try { - await savePremiumSettings(); - showRestartModal(); - } catch (_error) { + const handleOpenCheckout = (plan: 'server' | 'enterprise', upgrade: boolean) => { + // Prevent Free → Enterprise (must have Server first) + const currentTier = mapLicenseToTier(currentLicenseInfo || null); + if (currentTier === 'free' && plan === 'enterprise') { alert({ - alertType: 'error', - title: t('admin.error', 'Error'), - body: t('admin.settings.saveError', 'Failed to save settings'), + alertType: 'warning', + title: t('plan.enterprise.requiresServer', 'Server Plan Required'), + body: t( + 'plan.enterprise.requiresServerMessage', + 'Please upgrade to the Server plan first before upgrading to Enterprise.' + ), }); + return; } + + setSelectedPlan(plan); + setIsUpgrade(upgrade); + setCheckoutModalOpened(true); + }; + + const handleManageBilling = () => { + // Show warning about email verification + alert({ + alertType: 'warning', + title: t('plan.static.billingPortal.title', 'Email Verification Required'), + body: t( + 'plan.static.billingPortal.message', + 'You will need to verify your email address in the Stripe billing portal. Check your email for a login link.' + ), + }); + + window.open(STATIC_STRIPE_LINKS.billingPortal, '_blank'); }; const staticPlans = [ @@ -122,7 +125,7 @@ const StaticPlanSection: React.FC = ({ currentLicenseInf display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', - paddingBottom: '1rem', + paddingBottom: '0.1rem', }} > {staticPlans.map((plan) => ( @@ -131,53 +134,27 @@ const StaticPlanSection: React.FC = ({ currentLicenseInf padding="lg" radius="md" withBorder - style={{ - position: 'relative', - display: 'flex', - flexDirection: 'column', - borderColor: plan.id === currentPlan.id ? 'var(--mantine-color-green-6)' : undefined, - borderWidth: plan.id === currentPlan.id ? '2px' : undefined, - }} + style={getBaseCardStyle(plan.id === currentPlan.id)} + className="plan-card" > {plan.id === currentPlan.id && ( - - {t('plan.current', 'Current Plan')} - + )} {plan.popular && plan.id !== currentPlan.id && ( - - {t('plan.popular', 'Popular')} - + )}
- + {plan.name} - - - {plan.price === 0 && plan.id !== 'free' - ? t('plan.customPricing', 'Custom') - : plan.price === 0 - ? t('plan.free.name', 'Free') - : `${plan.currency}${plan.price}`} - - {plan.period && ( - - {plan.period} - - )} - {typeof plan.maxUsers === 'string' ? plan.maxUsers @@ -195,18 +172,123 @@ const StaticPlanSection: React.FC = ({ currentLicenseInf
- + ); } - > - {plan.id === currentPlan.id - ? t('plan.current', 'Current Plan') - : t('plan.contact', 'Contact Us')} - + + // Server Plan + if (plan.id === 'server') { + if (currentTier === 'free') { + return ( + + ); + } + if (isCurrent) { + return ( + + ); + } + if (isDowngradePlan) { + return ( + + ); + } + } + + // Enterprise Plan + if (plan.id === 'enterprise') { + if (isEnterpriseBlockedForFree(currentTier, plan.id)) { + return ( + + + + ); + } + if (currentTier === 'server') { + // TODO: Re-enable checkout flow when account syncing is ready + // return ( + // + // ); + return ( + + ); + } + if (isCurrent) { + return ( + + ); + } + } + + return null; + })()} ))} @@ -230,66 +312,14 @@ const StaticPlanSection: React.FC = ({ currentLicenseInf {/* License Key Section */} -
- + - - - } - > - - {t('admin.settings.premium.licenseKey.info', 'If you have a license key or certificate file from a direct purchase, you can enter it here to activate premium or enterprise features.')} - - - - {premiumLoading ? ( - - - - ) : ( - - -
- - {t('admin.settings.premium.key.label', 'License Key')} - - - } - description={t('admin.settings.premium.key.description', 'Enter your premium or enterprise license key. Premium features will be automatically enabled when a key is provided.')} - value={premiumSettings.key || ''} - onChange={(e) => setPremiumSettings({ ...premiumSettings, key: e.target.value })} - placeholder="00000000-0000-0000-0000-000000000000" - /> -
- - - - -
-
- )} -
-
-
- - {/* Restart Confirmation Modal */} - setCheckoutModalOpened(false)} + planName={selectedPlan} + isUpgrade={isUpgrade} />
); diff --git a/frontend/src/proprietary/constants/staticStripeLinks.ts b/frontend/src/proprietary/constants/staticStripeLinks.ts new file mode 100644 index 000000000..3fb45b28c --- /dev/null +++ b/frontend/src/proprietary/constants/staticStripeLinks.ts @@ -0,0 +1,56 @@ +/** + * Static Stripe payment links for offline/self-hosted environments + * + * These links are used when Supabase is not configured, allowing users to + * purchase licenses directly through Stripe hosted checkout pages. + * + * NOTE: These are test environment URLs. Replace with production URLs before release. + */ + +export interface StaticStripeLinks { + server: { + monthly: string; + yearly: string; + }; + enterprise: { + monthly: string; + yearly: string; + }; + billingPortal: string; +} +// PRODCUTION LINKS FOR LIVE SERVER +export const STATIC_STRIPE_LINKS: StaticStripeLinks = { + server: { + monthly: 'https://buy.stripe.com/fZu4gB8Nv6ysfAj0ts8Zq03', + yearly: 'https://buy.stripe.com/9B68wR6Fn0a40Fpcca8Zq02', + }, + enterprise: { + monthly: '', + yearly: '', + }, + billingPortal: 'https://billing.stripe.com/p/login/test_aFa5kv1Mz2s10Fr3Cp83C00', +}; + +// LINKS FOR TEST SERVER: +// export const STATIC_STRIPE_LINKS: StaticStripeLinks = { +// server: { +// monthly: 'https://buy.stripe.com/test_8x27sD4YL9Ut0Fr3Cp83C02', +// yearly: 'https://buy.stripe.com/test_4gMdR11Mz4A9ag17SF83C03', +// }, +// enterprise: { +// monthly: 'https://buy.stripe.com/test_8x2cMX9f18Qp9bX0qd83C04', +// yearly: 'https://buy.stripe.com/test_6oU00b2QD2s173P6OB83C05', +// }, +// billingPortal: 'https://billing.stripe.com/p/login/test_aFa5kv1Mz2s10Fr3Cp83C00', +// }; + +/** + * Builds a Stripe URL with a prefilled email parameter + * @param baseUrl - The base Stripe checkout URL + * @param email - The email address to prefill + * @returns The complete URL with encoded email parameter + */ +export function buildStripeUrlWithEmail(baseUrl: string, email: string): string { + const encodedEmail = encodeURIComponent(email); + return `${baseUrl}?locked_prefilled_email=${encodedEmail}`; +} diff --git a/frontend/src/proprietary/utils/planTierUtils.ts b/frontend/src/proprietary/utils/planTierUtils.ts new file mode 100644 index 000000000..e4fa12f62 --- /dev/null +++ b/frontend/src/proprietary/utils/planTierUtils.ts @@ -0,0 +1,40 @@ +/** + * Shared utilities for plan tier comparisons and button logic + */ + +export type PlanTier = 'free' | 'server' | 'enterprise'; + +const TIER_HIERARCHY: Record = { + 'free': 1, + 'server': 2, + 'enterprise': 3, +}; + +/** + * Get numeric level for a tier + */ +export function getTierLevel(tier: PlanTier | string | null | undefined): number { + if (!tier) return 1; + return TIER_HIERARCHY[tier as PlanTier] || 1; +} + +/** + * Check if target tier is the current tier + */ +export function isCurrentTier(currentTier: PlanTier | string | null | undefined, targetTier: PlanTier | string): boolean { + return getTierLevel(currentTier) === getTierLevel(targetTier); +} + +/** + * Check if target tier is a downgrade from current tier + */ +export function isDowngrade(currentTier: PlanTier | string | null | undefined, targetTier: PlanTier | string): boolean { + return getTierLevel(currentTier) > getTierLevel(targetTier); +} + +/** + * Check if enterprise is blocked for free tier users + */ +export function isEnterpriseBlockedForFree(currentTier: PlanTier | string | null | undefined, targetTier: PlanTier | string): boolean { + return currentTier === 'free' && targetTier === 'enterprise'; +} From e26035c3b3ea966cf1bfbe16bd8193c1c4a3e15e Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 11 Dec 2025 12:13:54 +0100 Subject: [PATCH 37/56] build(versioning): synchronize app version across Tauri and simulation configs (#5120) # Description of Changes - **What was changed** - Added `groovy.json.JsonOutput` and `groovy.json.JsonSlurper` imports to `build.gradle`. - Introduced a reusable `writeIfChanged(File targetFile, String newContent)` helper to avoid unnecessary file writes when content is unchanged. - Added `updateTauriConfigVersion(String version)` to: - Parse `frontend/src-tauri/tauri.conf.json`. - Set the `version` field from `project.version`. - Re-write the file as pretty-printed JSON (with a trailing line separator) only if content actually changed. - Added `updateSimulationVersion(File fileToUpdate, String version)` to: - Locate the `appVersion: ''` assignment via regex in simulation files. - Replace the existing version with `project.version`. - Fail the build with a clear `GradleException` if `appVersion` cannot be found. - Registered a new Gradle task `syncAppVersion` (group: `versioning`) which: - Reads `project.version` as the canonical app version. - Updates `frontend/src-tauri/tauri.conf.json`. - Updates `frontend/src/core/testing/serverExperienceSimulations.ts`. - Updates `frontend/src/proprietary/testing/serverExperienceSimulations.ts`. - Updated the main `build` task so it now depends on `syncAppVersion` in addition to `:stirling-pdf:bootJar` and `buildRestartHelper`. - **Why the change was made** - To ensure the desktop Tauri configuration and server experience simulation configs consistently use the same application version as defined in `project.version`. - To remove manual version bumps in multiple files and eliminate the risk of version mismatches between backend, desktop app, and simulation/testing tooling. - To minimize noise in commits and CI by only touching versioned files when their content actually changes (using `writeIfChanged`). --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .github/workflows/build.yml | 17 +++++++++++-- build.gradle | 49 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a049bb90..a5df3e9ec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -262,7 +262,13 @@ jobs: strategy: fail-fast: false matrix: - docker-rev: ["docker/embedded/Dockerfile", "docker/embedded/Dockerfile.ultra-lite", "docker/embedded/Dockerfile.fat"] + include: + - docker-rev: docker/embedded/Dockerfile + artifact-suffix: Dockerfile + - docker-rev: docker/embedded/Dockerfile.ultra-lite + artifact-suffix: Dockerfile.ultra-lite + - docker-rev: docker/embedded/Dockerfile.fat + artifact-suffix: Dockerfile.fat steps: - name: Harden Runner uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 @@ -272,6 +278,13 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Free disk space on runner + run: | + echo "Disk space before cleanup:" && df -h + sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android /usr/local/share/boost + docker system prune -af || true + echo "Disk space after cleanup:" && df -h + - name: Set up JDK 17 uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: @@ -313,7 +326,7 @@ jobs: if: always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: reports-docker-${{ matrix.docker-rev }} + name: reports-docker-${{ matrix.artifact-suffix }} path: | build/reports/tests/ build/test-results/ diff --git a/build.gradle b/build.gradle index 64908ee4a..2941c2eb5 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,8 @@ plugins { } import com.github.jk1.license.render.* +import groovy.json.JsonOutput +import groovy.json.JsonSlurper ext { springBootVersion = "3.5.6" @@ -65,6 +67,51 @@ allprojects { } } +def writeIfChanged(File targetFile, String newContent) { + if (targetFile.getText('UTF-8') != newContent) { + targetFile.write(newContent, 'UTF-8') + } +} + +def updateTauriConfigVersion(String version) { + File tauriConfig = file('frontend/src-tauri/tauri.conf.json') + def parsed = new JsonSlurper().parse(tauriConfig) + parsed.version = version + + def formatted = JsonOutput.prettyPrint(JsonOutput.toJson(parsed)) + System.lineSeparator() + writeIfChanged(tauriConfig, formatted) +} + +def updateSimulationVersion(File fileToUpdate, String version) { + def content = fileToUpdate.getText('UTF-8') + def matcher = content =~ /(appVersion:\s*')([^']*)(')/ + + if (!matcher.find()) { + throw new GradleException("Could not locate appVersion in ${fileToUpdate} for synchronization") + } + + def updatedContent = matcher.replaceFirst("${matcher.group(1)}${version}${matcher.group(3)}") + writeIfChanged(fileToUpdate, updatedContent) +} + +tasks.register('syncAppVersion') { + group = 'versioning' + description = 'Synchronizes app version across desktop and simulation configs.' + + doLast { + def appVersion = project.version.toString() + println "Synchronizing application version to ${appVersion}" + updateTauriConfigVersion(appVersion) + + [ + 'frontend/src/core/testing/serverExperienceSimulations.ts', + 'frontend/src/proprietary/testing/serverExperienceSimulations.ts' + ].each { path -> + updateSimulationVersion(file(path), appVersion) + } + } +} + tasks.register('writeVersion', WriteProperties) { destinationFile = layout.projectDirectory.file('app/common/src/main/resources/version.properties') println "Writing version.properties to ${destinationFile.get().asFile.path}" @@ -314,7 +361,7 @@ tasks.named('bootRun') { tasks.named('build') { group = 'build' description = 'Delegates to :stirling-pdf:bootJar' - dependsOn ':stirling-pdf:bootJar', 'buildRestartHelper' + dependsOn ':stirling-pdf:bootJar', 'buildRestartHelper', 'syncAppVersion' doFirst { println "Delegating to :stirling-pdf:bootJar" From 6565a6ce186b96fcf45245ece890e86aa5360cbd Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:19:55 +0000 Subject: [PATCH 38/56] Bug/v2/improved cache busting (#5107) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .../software/SPDF/config/WebMvcConfig.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java index 0703708f5..8eac8fa80 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java @@ -1,10 +1,14 @@ package stirling.software.SPDF.config; +import java.util.concurrent.TimeUnit; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import lombok.RequiredArgsConstructor; @@ -25,6 +29,20 @@ public class WebMvcConfig implements WebMvcConfigurer { registry.addInterceptor(endpointInterceptor); } + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // Cache hashed assets (JS/CSS with content hashes) for 1 year + // These files have names like index-ChAS4tCC.js that change when content changes + registry.addResourceHandler("/assets/**") + .addResourceLocations("classpath:/static/assets/") + .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic()); + + // Don't cache index.html - it needs to be fresh to reference latest hashed assets + registry.addResourceHandler("/index.html") + .addResourceLocations("classpath:/static/") + .setCacheControl(CacheControl.noCache().mustRevalidate()); + } + @Override public void addCorsMappings(CorsRegistry registry) { // Check if running in Tauri mode From ae723443171b2da7cccae5a37ae167f2762d56ec Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:23:20 +0000 Subject: [PATCH 39/56] Offline pdfium (#5213) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- frontend/package-lock.json | 33 +++++++++++++++++++ frontend/package.json | 1 + .../core/components/viewer/LocalEmbedPDF.tsx | 7 ++-- frontend/vite.config.ts | 10 ++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8d90d9658..f788474bb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -105,6 +105,7 @@ "typescript": "^5.9.2", "typescript-eslint": "^8.44.1", "vite": "^7.1.7", + "vite-plugin-static-copy": "^3.1.4", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" } @@ -11093,6 +11094,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pac-proxy-agent": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", @@ -14503,6 +14517,25 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-plugin-static-copy": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-3.1.4.tgz", + "integrity": "sha512-iCmr4GSw4eSnaB+G8zc2f4dxSuDjbkjwpuBLLGvQYR9IW7rnDzftnUjOH5p4RYR+d4GsiBqXRvzuFhs5bnzVyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.6.0", + "p-map": "^7.0.3", + "picocolors": "^1.1.1", + "tinyglobby": "^0.2.15" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, "node_modules/vite-tsconfig-paths": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", diff --git a/frontend/package.json b/frontend/package.json index 5489f6b46..914b7bb1f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -152,6 +152,7 @@ "typescript": "^5.9.2", "typescript-eslint": "^8.44.1", "vite": "^7.1.7", + "vite-plugin-static-copy": "^3.1.4", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" }, diff --git a/frontend/src/core/components/viewer/LocalEmbedPDF.tsx b/frontend/src/core/components/viewer/LocalEmbedPDF.tsx index 3e5fa5f1c..0b79604fd 100644 --- a/frontend/src/core/components/viewer/LocalEmbedPDF.tsx +++ b/frontend/src/core/components/viewer/LocalEmbedPDF.tsx @@ -46,6 +46,7 @@ import { PrintAPIBridge } from '@app/components/viewer/PrintAPIBridge'; import { isPdfFile } from '@app/utils/fileUtils'; import { useTranslation } from 'react-i18next'; import { LinkLayer } from '@app/components/viewer/LinkLayer'; +import { absoluteWithBasePath } from '@app/constants/app'; interface LocalEmbedPDFProps { file?: File | Blob; @@ -167,8 +168,10 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur ]; }, [pdfUrl]); - // Initialize the engine with the React hook - const { engine, isLoading, error } = usePdfiumEngine(); + // Initialize the engine with the React hook - use local WASM for offline support + const { engine, isLoading, error } = usePdfiumEngine({ + wasmUrl: absoluteWithBasePath('/pdfium/pdfium.wasm'), + }); // Early return if no file or URL provided diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 0eb35e94c..f8d52908d 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react-swc'; import tsconfigPaths from 'vite-tsconfig-paths'; +import { viteStaticCopy } from 'vite-plugin-static-copy'; export default defineConfig(({ mode }) => { // When DISABLE_ADDITIONAL_FEATURES is false (or unset), enable proprietary features @@ -20,6 +21,15 @@ export default defineConfig(({ mode }) => { tsconfigPaths({ projects: [tsconfigProject], }), + viteStaticCopy({ + targets: [ + { + //provides static pdfium so embedpdf can run without cdn + src: 'node_modules/@embedpdf/pdfium/dist/pdfium.wasm', + dest: 'pdfium' + } + ] + }) ], server: { host: true, From f29d85565a82f278d199a9beeb2ff58a024744dc Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Thu, 11 Dec 2025 12:42:16 +0000 Subject: [PATCH 40/56] Chore/v2/ctrlf (#5217) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- .../components/viewer/CustomSearchLayer.tsx | 4 +- .../core/components/viewer/EmbedPdfViewer.tsx | 16 +- .../components/viewer/SearchAPIBridge.tsx | 46 +++- .../components/viewer/SearchInterface.tsx | 254 +++++++++++------- .../viewer/useViewerRightRailButtons.tsx | 12 +- frontend/src/core/contexts/ViewerContext.tsx | 19 ++ .../src/core/contexts/viewer/viewerActions.ts | 7 + 7 files changed, 244 insertions(+), 114 deletions(-) diff --git a/frontend/src/core/components/viewer/CustomSearchLayer.tsx b/frontend/src/core/components/viewer/CustomSearchLayer.tsx index 05b50ecab..29f3b528c 100644 --- a/frontend/src/core/components/viewer/CustomSearchLayer.tsx +++ b/frontend/src/core/components/viewer/CustomSearchLayer.tsx @@ -44,8 +44,10 @@ export function CustomSearchLayer({ } const unsubscribe = searchProvides.onSearchResultStateChange?.((state: SearchResultState) => { + if (!state) return; + // Auto-scroll to active search result - if (state?.results && state.activeResultIndex !== undefined && state.activeResultIndex >= 0) { + if (state.results && state.activeResultIndex !== undefined && state.activeResultIndex >= 0) { const activeResult = state.results[state.activeResultIndex]; if (activeResult) { const pageNumber = activeResult.pageIndex + 1; // Convert to 1-based page number diff --git a/frontend/src/core/components/viewer/EmbedPdfViewer.tsx b/frontend/src/core/components/viewer/EmbedPdfViewer.tsx index 9ca8bac0a..94bff5a35 100644 --- a/frontend/src/core/components/viewer/EmbedPdfViewer.tsx +++ b/frontend/src/core/components/viewer/EmbedPdfViewer.tsx @@ -43,6 +43,8 @@ const EmbedPdfViewerContent = ({ isThumbnailSidebarVisible, toggleThumbnailSidebar, isBookmarkSidebarVisible, + isSearchInterfaceVisible, + searchInterfaceActions, zoomActions, panActions: _panActions, rotationActions: _rotationActions, @@ -184,7 +186,7 @@ const EmbedPdfViewerContent = ({ onZoomOut: zoomActions.zoomOut, }); - // Handle keyboard zoom shortcuts + // Handle keyboard shortcuts (zoom and search) useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (!isViewerHovered) return; @@ -199,6 +201,16 @@ const EmbedPdfViewerContent = ({ // Ctrl+- for zoom out event.preventDefault(); zoomActions.zoomOut(); + } else if (event.key === 'f' || event.key === 'F') { + // Ctrl+F for search + event.preventDefault(); + if (isSearchInterfaceVisible) { + // If already open, trigger refocus event + window.dispatchEvent(new CustomEvent('refocus-search-input')); + } else { + // Open search interface + searchInterfaceActions.open(); + } } } }; @@ -207,7 +219,7 @@ const EmbedPdfViewerContent = ({ return () => { document.removeEventListener('keydown', handleKeyDown); }; - }, [isViewerHovered]); + }, [isViewerHovered, isSearchInterfaceVisible, zoomActions, searchInterfaceActions]); // Register checker for unsaved changes (annotations only for now) useEffect(() => { diff --git a/frontend/src/core/components/viewer/SearchAPIBridge.tsx b/frontend/src/core/components/viewer/SearchAPIBridge.tsx index 4b0eadd23..4003e1d0b 100644 --- a/frontend/src/core/components/viewer/SearchAPIBridge.tsx +++ b/frontend/src/core/components/viewer/SearchAPIBridge.tsx @@ -28,11 +28,13 @@ export function SearchAPIBridge() { if (!search) return; const unsubscribe = search.onSearchResultStateChange?.((state: any) => { + if (!state) return; + const newState = { - results: state?.results || null, - activeIndex: (state?.activeResultIndex || 0) + 1 // Convert to 1-based index + results: state.results || null, + activeIndex: (state.activeResultIndex || 0) + 1 // Convert to 1-based index }; - + setLocalState(prevState => { // Only update if state actually changed if (prevState.results !== newState.results || prevState.activeIndex !== newState.activeIndex) { @@ -52,16 +54,42 @@ export function SearchAPIBridge() { state: localState, api: { search: async (query: string) => { - search.startSearch(); - return search.searchAllPages(query); + if (search?.startSearch && search?.searchAllPages) { + search.startSearch(); + return search.searchAllPages(query); + } }, clear: () => { - search.stopSearch(); + try { + if (search?.stopSearch) { + search.stopSearch(); + } + } catch (error) { + console.warn('Error stopping search:', error); + } setLocalState({ results: null, activeIndex: 0 }); }, - next: () => search.nextResult(), - previous: () => search.previousResult(), - goToResult: (index: number) => search.goToResult(index), + next: () => { + try { + search?.nextResult?.(); + } catch (error) { + console.warn('Error navigating to next result:', error); + } + }, + previous: () => { + try { + search?.previousResult?.(); + } catch (error) { + console.warn('Error navigating to previous result:', error); + } + }, + goToResult: (index: number) => { + try { + search?.goToResult?.(index); + } catch (error) { + console.warn('Error going to result:', error); + } + }, } }); } diff --git a/frontend/src/core/components/viewer/SearchInterface.tsx b/frontend/src/core/components/viewer/SearchInterface.tsx index da6f6472a..eefac8154 100644 --- a/frontend/src/core/components/viewer/SearchInterface.tsx +++ b/frontend/src/core/components/viewer/SearchInterface.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { Box, TextInput, ActionIcon, Text, Group } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import { LocalIcon } from '@app/components/shared/LocalIcon'; @@ -12,7 +12,9 @@ interface SearchInterfaceProps { export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { const { t } = useTranslation(); const viewerContext = React.useContext(ViewerContext); - + const inputRef = useRef(null); + const searchTimeoutRef = useRef(null); + const searchState = viewerContext?.getSearchState(); const searchResults = searchState?.results; const searchActiveIndex = searchState?.activeIndex; @@ -26,6 +28,61 @@ export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { } | null>(null); const [isSearching, setIsSearching] = useState(false); + // Auto-focus search input when visible + useEffect(() => { + if (visible) { + inputRef.current?.focus(); + } + }, [visible]); + + // Listen for refocus event (when Ctrl+F pressed while already open) + useEffect(() => { + const handleRefocus = () => { + inputRef.current?.focus(); + inputRef.current?.select(); + }; + + window.addEventListener('refocus-search-input', handleRefocus); + return () => { + window.removeEventListener('refocus-search-input', handleRefocus); + }; + }, []); + + // Auto-search as user types (debounced) + useEffect(() => { + // Clear existing timeout + if (searchTimeoutRef.current) { + clearTimeout(searchTimeoutRef.current); + } + + // If query is empty, clear search immediately + if (!searchQuery.trim()) { + searchActions?.clear(); + setResultInfo(null); + return; + } + + // Debounce search by 300ms + searchTimeoutRef.current = setTimeout(async () => { + if (searchQuery.trim() && searchActions) { + setIsSearching(true); + try { + await searchActions.search(searchQuery.trim()); + } catch (error) { + console.error('Search failed:', error); + } finally { + setIsSearching(false); + } + } + }, 300); + + return () => { + if (searchTimeoutRef.current) { + clearTimeout(searchTimeoutRef.current); + } + }; + }, [searchQuery, searchActions]); + // Monitor search state changes useEffect(() => { if (!visible) return; @@ -59,30 +116,21 @@ export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { return () => clearInterval(interval); }, [visible, searchResults, searchActiveIndex, searchQuery]); - const handleSearch = async (query: string) => { - if (!query.trim()) { - // If query is empty, clear the search - handleClearSearch(); - return; - } - - if (query.trim() && searchActions) { - setIsSearching(true); - try { - await searchActions.search(query.trim()); - } catch (error) { - console.error('Search failed:', error); - } finally { - setIsSearching(false); - } - } - }; - const handleKeyDown = (event: React.KeyboardEvent) => { if (event.key === 'Enter') { - handleSearch(searchQuery); + // Navigate to next result on Enter + event.preventDefault(); + handleNext(); } else if (event.key === 'Escape') { onClose(); + } else if (event.key === 'ArrowDown') { + // Navigate to next result + event.preventDefault(); + handleNext(); + } else if (event.key === 'ArrowUp') { + // Navigate to previous result + event.preventDefault(); + handlePrevious(); } }; @@ -103,17 +151,17 @@ export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { // No longer need to sync with external API on mount - removed const handleJumpToResult = (index: number) => { - // Use context actions instead of window API - functionality simplified for now if (resultInfo && index >= 1 && index <= resultInfo.totalResults) { - // Note: goToResult functionality would need to be implemented in SearchAPIBridge - console.log('Jump to result:', index); + // Convert to 0-based index for the API + searchActions?.goToResult?.(index - 1); } }; const handleJumpToSubmit = () => { - const index = parseInt(jumpToValue); - if (index && resultInfo && index >= 1 && index <= resultInfo.totalResults) { + const index = parseInt(jumpToValue, 10); + if (!isNaN(index) && resultInfo && index >= 1 && index <= resultInfo.totalResults) { handleJumpToResult(index); + setJumpToValue(''); // Clear the input after jumping } }; @@ -123,7 +171,14 @@ export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { } }; - const _handleClose = () => { + const handleInputBlur = () => { + // Close popover on blur if no text is entered + if (!searchQuery.trim()) { + onClose(); + } + }; + + const handleCloseClick = () => { handleClearSearch(); onClose(); }; @@ -135,100 +190,99 @@ export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { padding: '0px' }} > - {/* Header */} - + {/* Header with close button */} + {t('search.title', 'Search PDF')} + + + {/* Search input */} { const newValue = e.currentTarget.value; setSearchQuery(newValue); - // If user clears the input, clear the search highlights - if (!newValue.trim()) { - handleClearSearch(); - } }} onKeyDown={handleKeyDown} + onBlur={handleInputBlur} style={{ flex: 1 }} rightSection={ - handleSearch(searchQuery)} - disabled={!searchQuery.trim() || isSearching} - loading={isSearching} - > - - + searchQuery.trim() && ( + + + + ) } /> - {/* Results info and navigation */} - {resultInfo && ( - - {resultInfo.totalResults === 0 ? ( - - {t('search.noResults', 'No results found')} - - ) : ( - - setJumpToValue(e.currentTarget.value)} - onKeyDown={handleJumpToKeyDown} - onBlur={handleJumpToSubmit} - placeholder={resultInfo.currentIndex.toString()} - style={{ width: '3rem' }} - type="number" - min="1" - max={resultInfo.totalResults} - /> - - of {resultInfo.totalResults} - - - )} - - {resultInfo.totalResults > 0 && ( - - - - - = resultInfo.totalResults} - aria-label="Next result" - > - - - - - - - )} + {/* Results info and navigation - always show */} + + + { + const newValue = e.currentTarget.value; + setJumpToValue(newValue); + + // Jump immediately as user types + const index = parseInt(newValue, 10); + if (resultInfo && !isNaN(index) && index >= 1 && index <= resultInfo.totalResults) { + handleJumpToResult(index); + } + }} + onKeyDown={handleJumpToKeyDown} + onBlur={() => setJumpToValue('')} // Clear on blur instead of submit + placeholder={(resultInfo?.currentIndex || 0).toString()} + style={{ width: '3rem' }} + type="number" + min="1" + max={resultInfo?.totalResults || 0} + disabled={!resultInfo || resultInfo.totalResults === 0} + /> + + of {resultInfo?.totalResults || 0} + - )} + + + + + + = resultInfo.totalResults} + aria-label="Next result" + > + + + + {/* Loading state */} {isSearching && ( diff --git a/frontend/src/core/components/viewer/useViewerRightRailButtons.tsx b/frontend/src/core/components/viewer/useViewerRightRailButtons.tsx index 995d7d095..9ef19dd71 100644 --- a/frontend/src/core/components/viewer/useViewerRightRailButtons.tsx +++ b/frontend/src/core/components/viewer/useViewerRightRailButtons.tsx @@ -36,7 +36,14 @@ export function useViewerRightRailButtons() { order: 10, render: ({ disabled }) => ( - +
@@ -52,7 +60,7 @@ export function useViewerRightRailButtons() {
- {}} /> +
diff --git a/frontend/src/core/contexts/ViewerContext.tsx b/frontend/src/core/contexts/ViewerContext.tsx index 937c6067a..9217511ef 100644 --- a/frontend/src/core/contexts/ViewerContext.tsx +++ b/frontend/src/core/contexts/ViewerContext.tsx @@ -80,6 +80,14 @@ interface ViewerContextType { isBookmarkSidebarVisible: boolean; toggleBookmarkSidebar: () => void; + // Search interface visibility + isSearchInterfaceVisible: boolean; + searchInterfaceActions: { + open: () => void; + close: () => void; + toggle: () => void; + }; + // Annotation visibility toggle isAnnotationsVisible: boolean; toggleAnnotationsVisibility: () => void; @@ -145,6 +153,7 @@ export const ViewerProvider: React.FC = ({ children }) => { // UI state - only state directly managed by this context const [isThumbnailSidebarVisible, setIsThumbnailSidebarVisible] = useState(false); const [isBookmarkSidebarVisible, setIsBookmarkSidebarVisible] = useState(false); + const [isSearchInterfaceVisible, setSearchInterfaceVisible] = useState(false); const [isAnnotationsVisible, setIsAnnotationsVisible] = useState(true); const [isAnnotationMode, setIsAnnotationModeState] = useState(false); const [activeFileIndex, setActiveFileIndex] = useState(0); @@ -207,6 +216,12 @@ export const ViewerProvider: React.FC = ({ children }) => { setIsBookmarkSidebarVisible(prev => !prev); }; + const searchInterfaceActions = { + open: () => setSearchInterfaceVisible(true), + close: () => setSearchInterfaceVisible(false), + toggle: () => setSearchInterfaceVisible(prev => !prev), + }; + const toggleAnnotationsVisibility = () => { setIsAnnotationsVisible(prev => !prev); }; @@ -294,6 +309,10 @@ export const ViewerProvider: React.FC = ({ children }) => { isBookmarkSidebarVisible, toggleBookmarkSidebar, + // Search interface + isSearchInterfaceVisible, + searchInterfaceActions, + // Annotation controls isAnnotationsVisible, toggleAnnotationsVisibility, diff --git a/frontend/src/core/contexts/viewer/viewerActions.ts b/frontend/src/core/contexts/viewer/viewerActions.ts index d32c5077c..882ba8aa8 100644 --- a/frontend/src/core/contexts/viewer/viewerActions.ts +++ b/frontend/src/core/contexts/viewer/viewerActions.ts @@ -52,6 +52,7 @@ export interface SearchActions { next: () => void; previous: () => void; clear: () => void; + goToResult: (index: number) => void; } export interface ExportActions { @@ -287,6 +288,12 @@ export function createViewerActions({ api.clear(); } }, + goToResult: (index: number) => { + const api = registry.current.search?.api; + if (api?.goToResult) { + api.goToResult(index); + } + }, }; const exportActions: ExportActions = { From eb3e57577ca51997dd801bf5018b90c6e8583ead Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:16:37 +0000 Subject: [PATCH 41/56] Bump version from 2.1.2 to 2.1.3 (#5224) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2941c2eb5..90fde88e5 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ repositories { allprojects { group = 'stirling.software' - version = '2.1.2' + version = '2.1.3' configurations.configureEach { exclude group: 'commons-logging', module: 'commons-logging' From 5f072f87bb550320c0027448ffdf5b9cb783d84d Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:56:35 +0000 Subject: [PATCH 42/56] Account change details (#5190) ## Summary Accounts setting page to change a users password or username Fix huge bug were users can see admin settings due to hard code admin=true ## Testing - not run (not requested) ------ [Codex Task](https://chatgpt.com/codex/tasks/task_b_6934b8ecdbf08328a0951b46db77dfd2) --- .../public/locales/en-GB/translation.toml | 23 ++ .../core/components/shared/AppConfigModal.tsx | 2 +- .../core/components/shared/config/types.ts | 1 + frontend/src/core/services/accountService.ts | 10 + .../shared/config/configNavSections.tsx | 36 +++ .../config/configSections/AccountSection.tsx | 260 ++++++++++++++++++ .../config/configSections/GeneralSection.tsx | 53 ---- 7 files changed, 331 insertions(+), 54 deletions(-) create mode 100644 frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx delete mode 100644 frontend/src/proprietary/components/shared/config/configSections/GeneralSection.tsx diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index 9be190247..83963987d 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -435,6 +435,24 @@ latestVersion = "Latest Version" checkForUpdates = "Check for Updates" viewDetails = "View Details" +[settings.security] +title = "Security" +description = "Update your password to keep your account secure." + +[settings.security.password] +subtitle = "Change your password. You will be logged out after updating." +required = "All fields are required." +mismatch = "New passwords do not match." +error = "Unable to update password. Please verify your current password and try again." +success = "Password updated successfully. Please sign in again." +current = "Current password" +currentPlaceholder = "Enter your current password" +new = "New password" +newPlaceholder = "Enter a new password" +confirm = "Confirm new password" +confirmPlaceholder = "Re-enter your new password" +update = "Update password" + [settings.hotkeys] title = "Keyboard Shortcuts" description = "Customize keyboard shortcuts for quick tool access. Click \"Change shortcut\" and press a new key combination. Press Esc to cancel." @@ -493,6 +511,10 @@ oldPassword = "Current Password" newPassword = "New Password" confirmNewPassword = "Confirm New Password" submit = "Submit Changes" +credsUpdated = "Account updated" +description = "Changes saved. Please log in again." +error = "Unable to update username. Please verify your password and try again." +changeUsername = "Update your username. You will be logged out after updating." [account] title = "Account Settings" @@ -5070,6 +5092,7 @@ loading = "Loading..." back = "Back" continue = "Continue" error = "Error" +save = "Save" [config.overview] title = "Application Configuration" diff --git a/frontend/src/core/components/shared/AppConfigModal.tsx b/frontend/src/core/components/shared/AppConfigModal.tsx index 6dd7491d4..42e6099e3 100644 --- a/frontend/src/core/components/shared/AppConfigModal.tsx +++ b/frontend/src/core/components/shared/AppConfigModal.tsx @@ -69,7 +69,7 @@ const AppConfigModalInner: React.FC = ({ opened, onClose }) }), []); // Get isAdmin and runningEE from app config - const isAdmin = true // config?.isAdmin ?? false; + const isAdmin = config?.isAdmin ?? false; const runningEE = config?.runningEE ?? false; const loginEnabled = config?.enableLogin ?? false; diff --git a/frontend/src/core/components/shared/config/types.ts b/frontend/src/core/components/shared/config/types.ts index d4bd9a83c..740e6130e 100644 --- a/frontend/src/core/components/shared/config/types.ts +++ b/frontend/src/core/components/shared/config/types.ts @@ -3,6 +3,7 @@ export const VALID_NAV_KEYS = [ 'preferences', 'notifications', 'connections', + 'account', 'general', 'people', 'teams', diff --git a/frontend/src/core/services/accountService.ts b/frontend/src/core/services/accountService.ts index 72d9f1873..cc8c2527f 100644 --- a/frontend/src/core/services/accountService.ts +++ b/frontend/src/core/services/accountService.ts @@ -56,4 +56,14 @@ export const accountService = { formData.append('newPassword', newPassword); await apiClient.post('/api/v1/user/change-password-on-login', formData); }, + + /** + * Change username + */ + async changeUsername(newUsername: string, currentPassword: string): Promise { + const formData = new FormData(); + formData.append('currentPasswordChangeUsername', currentPassword); + formData.append('newUsername', newUsername); + await apiClient.post('/api/v1/user/change-username', formData); + }, }; diff --git a/frontend/src/proprietary/components/shared/config/configNavSections.tsx b/frontend/src/proprietary/components/shared/config/configNavSections.tsx index 6a64e5fbc..0073696f9 100644 --- a/frontend/src/proprietary/components/shared/config/configNavSections.tsx +++ b/frontend/src/proprietary/components/shared/config/configNavSections.tsx @@ -16,6 +16,8 @@ import AdminEndpointsSection from '@app/components/shared/config/configSections/ import AdminAuditSection from '@app/components/shared/config/configSections/AdminAuditSection'; import AdminUsageSection from '@app/components/shared/config/configSections/AdminUsageSection'; import ApiKeys from '@app/components/shared/config/configSections/ApiKeys'; +import AccountSection from '@app/components/shared/config/configSections/AccountSection'; +import GeneralSection from '@app/components/shared/config/configSections/GeneralSection'; /** * Hook version of proprietary config nav sections with proper i18n support @@ -30,6 +32,23 @@ export const useConfigNavSections = ( // Get the core sections (just Preferences) const sections = useCoreConfigNavSections(isAdmin, runningEE, loginEnabled); + // Add account management under Preferences + const preferencesSection = sections.find((section) => section.items.some((item) => item.key === 'general')); + if (preferencesSection) { + preferencesSection.items = preferencesSection.items.map((item) => + item.key === 'general' ? { ...item, component: } : item + ); + + if (loginEnabled) { + preferencesSection.items.push({ + key: 'account', + label: t('account.accountSettings', 'Account'), + icon: 'person-rounded', + component: + }); + } + } + // Add Admin sections if user is admin OR if login is disabled (but mark as disabled) if (isAdmin || !loginEnabled) { const requiresLogin = !loginEnabled; @@ -220,6 +239,23 @@ export const createConfigNavSections = ( // Get the core sections (just Preferences) const sections = createCoreConfigNavSections(isAdmin, runningEE, loginEnabled); + // Add account management under Preferences + const preferencesSection = sections.find((section) => section.items.some((item) => item.key === 'general')); + if (preferencesSection) { + preferencesSection.items = preferencesSection.items.map((item) => + item.key === 'general' ? { ...item, component: } : item + ); + + if (loginEnabled) { + preferencesSection.items.push({ + key: 'account', + label: 'Account', + icon: 'person-rounded', + component: + }); + } + } + // Add Admin sections if user is admin OR if login is disabled (but mark as disabled) if (isAdmin || !loginEnabled) { const requiresLogin = !loginEnabled; diff --git a/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx new file mode 100644 index 000000000..f627302b4 --- /dev/null +++ b/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx @@ -0,0 +1,260 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { Alert, Button, Group, Modal, Paper, PasswordInput, Stack, Text, TextInput } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { alert as showToast } from '@app/components/toast'; +import { useAuth } from '@app/auth/UseSession'; +import { accountService } from '@app/services/accountService'; +import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; + +const AccountSection: React.FC = () => { + const { t } = useTranslation(); + const { user, signOut } = useAuth(); + const [passwordModalOpen, setPasswordModalOpen] = useState(false); + const [usernameModalOpen, setUsernameModalOpen] = useState(false); + + const [currentPassword, setCurrentPassword] = useState(''); + const [newPassword, setNewPassword] = useState(''); + const [confirmPassword, setConfirmPassword] = useState(''); + const [passwordError, setPasswordError] = useState(''); + const [passwordSubmitting, setPasswordSubmitting] = useState(false); + + const [currentPasswordForUsername, setCurrentPasswordForUsername] = useState(''); + const [newUsername, setNewUsername] = useState(''); + const [usernameError, setUsernameError] = useState(''); + const [usernameSubmitting, setUsernameSubmitting] = useState(false); + + const userIdentifier = useMemo(() => user?.email || user?.username || '', [user?.email, user?.username]); + + const redirectToLogin = useCallback(() => { + window.location.assign('/login'); + }, []); + + const handleLogout = useCallback(async () => { + try { + await signOut(); + } finally { + redirectToLogin(); + } + }, [redirectToLogin, signOut]); + + const handlePasswordSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (!currentPassword || !newPassword || !confirmPassword) { + setPasswordError(t('settings.security.password.required', 'All fields are required.')); + return; + } + + if (newPassword !== confirmPassword) { + setPasswordError(t('settings.security.password.mismatch', 'New passwords do not match.')); + return; + } + + try { + setPasswordSubmitting(true); + setPasswordError(''); + + await accountService.changePassword(currentPassword, newPassword); + + showToast({ + alertType: 'success', + title: t('settings.security.password.success', 'Password updated successfully. Please sign in again.'), + }); + + setCurrentPassword(''); + setNewPassword(''); + setConfirmPassword(''); + setPasswordModalOpen(false); + await handleLogout(); + } catch (err) { + const axiosError = err as { response?: { data?: { message?: string } } }; + setPasswordError( + axiosError.response?.data?.message || + t('settings.security.password.error', 'Unable to update password. Please verify your current password and try again.') + ); + } finally { + setPasswordSubmitting(false); + } + }; + + const handleUsernameSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (!currentPasswordForUsername || !newUsername) { + setUsernameError(t('settings.security.password.required', 'All fields are required.')); + return; + } + + try { + setUsernameSubmitting(true); + setUsernameError(''); + + await accountService.changeUsername(newUsername, currentPasswordForUsername); + + showToast({ + alertType: 'success', + title: t('changeCreds.credsUpdated', 'Account updated'), + body: t('changeCreds.description', 'Changes saved. Please log in again.'), + }); + + setNewUsername(''); + setCurrentPasswordForUsername(''); + setUsernameModalOpen(false); + await handleLogout(); + } catch (err) { + const axiosError = err as { response?: { data?: { message?: string } } }; + setUsernameError( + axiosError.response?.data?.message || + t('changeCreds.error', 'Unable to update username. Please verify your password and try again.') + ); + } finally { + setUsernameSubmitting(false); + } + }; + + return ( + +
+ + {t('account.accountSettings', 'Account')} + + + {t('changeCreds.header', 'Update Your Account Details')} + +
+ + + + + {userIdentifier + ? t('settings.general.user', 'User') + ': ' + userIdentifier + : t('account.accountSettings', 'Account Settings')} + + + + + + + + + + + + + setPasswordModalOpen(false)} + title={t('settings.security.title', 'Change password')} + withinPortal + zIndex={Z_INDEX_OVER_CONFIG_MODAL} + > +
+ + + {t('settings.security.password.subtitle', 'Change your password. You will be logged out after updating.')} + + + {passwordError && ( + } color="red" variant="light"> + {passwordError} + + )} + + setCurrentPassword(event.currentTarget.value)} + required + /> + + setNewPassword(event.currentTarget.value)} + required + /> + + setConfirmPassword(event.currentTarget.value)} + required + /> + + + + + + +
+
+ + setUsernameModalOpen(false)} + title={t('account.changeUsername', 'Change username')} + withinPortal + zIndex={Z_INDEX_OVER_CONFIG_MODAL} + > +
+ + + {t('changeCreds.changeUsername', 'Update your username. You will be logged out after updating.')} + + + {usernameError && ( + } color="red" variant="light"> + {usernameError} + + )} + + setNewUsername(event.currentTarget.value)} + required + /> + + setCurrentPasswordForUsername(event.currentTarget.value)} + required + /> + + + + + + +
+
+
+ ); +}; + +export default AccountSection; diff --git a/frontend/src/proprietary/components/shared/config/configSections/GeneralSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/GeneralSection.tsx deleted file mode 100644 index 7894319cb..000000000 --- a/frontend/src/proprietary/components/shared/config/configSections/GeneralSection.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import { Stack, Text, Button } from '@mantine/core'; -import { useTranslation } from 'react-i18next'; -import { useAuth } from '@app/auth/UseSession'; -import { useNavigate } from 'react-router-dom'; -import CoreGeneralSection from '@core/components/shared/config/configSections/GeneralSection'; - -/** - * Proprietary extension of GeneralSection that adds account management - */ -const GeneralSection: React.FC = () => { - const { t } = useTranslation(); - const { signOut, user } = useAuth(); - const navigate = useNavigate(); - - const handleLogout = async () => { - try { - await signOut(); - navigate('/login'); - } catch (error) { - console.error('Logout error:', error); - } - }; - - return ( - -
-
- {t('settings.general.title', 'General')} - - {t('settings.general.description', 'Configure general application preferences.')} - -
- - {user && ( - - - {t('settings.general.user', 'User')}: {user.email || user.username} - - - - )} -
- - {/* Render core general section preferences (without title since we show it above) */} - -
- ); -}; - -export default GeneralSection; From c86e2d68407acaea362a2872a2e405d5682cfbb6 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 11 Dec 2025 16:38:32 +0000 Subject: [PATCH 43/56] Delete .github/README.md --- .github/README.md | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .github/README.md diff --git a/.github/README.md b/.github/README.md deleted file mode 100644 index 97cb44086..000000000 --- a/.github/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# CI Configuration - -## CI Lite Mode - -Skip non-essential CI workflows by setting a repository variable: - -**Settings → Secrets and variables → Actions → Variables → New repository variable** - -- Name: `CI_PROFILE` -- Value: `lite` - -Skips resource-intensive builds, releases, and OSS-specific workflows. Useful for deployment-only forks or faster CI runs. From f4cc87144d7bf0d7bcb26fa7021e9aa63d09729a Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Fri, 12 Dec 2025 17:44:15 +0000 Subject: [PATCH 44/56] Fix language codes in picker (#5233) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. --- frontend/src/core/components/shared/LanguageSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/core/components/shared/LanguageSelector.tsx b/frontend/src/core/components/shared/LanguageSelector.tsx index 7eb35d1f7..4129e3209 100644 --- a/frontend/src/core/components/shared/LanguageSelector.tsx +++ b/frontend/src/core/components/shared/LanguageSelector.tsx @@ -173,7 +173,7 @@ const LanguageSelector: React.FC = ({ .sort(([, nameA], [, nameB]) => nameA.localeCompare(nameB)) .map(([code, name]) => ({ value: code, - label: `${name} (${code})`, + label: name, })); // Hide the language selector if there's only one language option From 69ffd29bb5a9b07d72521e50f39bc920019dc4e2 Mon Sep 17 00:00:00 2001 From: James Brunton Date: Fri, 12 Dec 2025 18:00:40 +0000 Subject: [PATCH 45/56] Fix German text for sign tool text entry (#5232) # Description of Changes Fix #5206 Required splitting out the logic for the text with font entry so that the labels are configurable from the call-site instead of all using the same ones for Sign. --- .../public/locales/de-DE/translation.toml | 4 +- .../annotation/shared/TextInputWithFont.tsx | 26 +++++---- .../components/annotation/tools/TextTool.tsx | 57 ------------------- .../components/tools/sign/SignSettings.tsx | 6 ++ 4 files changed, 24 insertions(+), 69 deletions(-) delete mode 100644 frontend/src/core/components/annotation/tools/TextTool.tsx diff --git a/frontend/public/locales/de-DE/translation.toml b/frontend/public/locales/de-DE/translation.toml index 274de764e..d48c424f4 100644 --- a/frontend/public/locales/de-DE/translation.toml +++ b/frontend/public/locales/de-DE/translation.toml @@ -6131,8 +6131,8 @@ tags = "text,anmerkung,beschriftung" applySignatures = "Text anwenden" [addText.text] -name = "Textinhalt" -placeholder = "Geben Sie den hinzuzufügenden Text ein" +name = "Text" +placeholder = "Text eingeben" fontLabel = "Schriftart" fontSizeLabel = "Schriftgröße" fontSizePlaceholder = "Schriftgröße eingeben oder wählen (8-200)" diff --git a/frontend/src/core/components/annotation/shared/TextInputWithFont.tsx b/frontend/src/core/components/annotation/shared/TextInputWithFont.tsx index c93a89be0..f3fecba7e 100644 --- a/frontend/src/core/components/annotation/shared/TextInputWithFont.tsx +++ b/frontend/src/core/components/annotation/shared/TextInputWithFont.tsx @@ -1,6 +1,5 @@ import React, { useState, useEffect } from 'react'; import { Stack, TextInput, Select, Combobox, useCombobox, Group, Box } from '@mantine/core'; -import { useTranslation } from 'react-i18next'; import { ColorPicker } from '@app/components/annotation/shared/ColorPicker'; interface TextInputWithFontProps { @@ -13,8 +12,12 @@ interface TextInputWithFontProps { textColor?: string; onTextColorChange?: (color: string) => void; disabled?: boolean; - label?: string; - placeholder?: string; + label: string; + placeholder: string; + fontLabel: string; + fontSizeLabel: string; + fontSizePlaceholder: string; + colorLabel?: string; onAnyChange?: () => void; } @@ -30,9 +33,12 @@ export const TextInputWithFont: React.FC = ({ disabled = false, label, placeholder, + fontLabel, + fontSizeLabel, + fontSizePlaceholder, + colorLabel, onAnyChange }) => { - const { t } = useTranslation(); const [fontSizeInput, setFontSizeInput] = useState(fontSize.toString()); const fontSizeCombobox = useCombobox(); const [isColorPickerOpen, setIsColorPickerOpen] = useState(false); @@ -66,8 +72,8 @@ export const TextInputWithFont: React.FC = ({ return ( { onTextChange(e.target.value); @@ -79,7 +85,7 @@ export const TextInputWithFont: React.FC = ({ {/* Font Selection */}