diff --git a/frontend/src/components/gallery/GalleryView.tsx b/frontend/src/components/gallery/GalleryView.tsx
index 56b0c6a8..b5273206 100644
--- a/frontend/src/components/gallery/GalleryView.tsx
+++ b/frontend/src/components/gallery/GalleryView.tsx
@@ -1311,9 +1311,7 @@ export const GalleryView: React.FC
= ({ slug, event, requiresP
onOpen={openFolderBySlug}
compact={compact}
slug={slug}
- protectionLevel={protectionLevel}
useEnhancedProtection={protectionLevel !== 'basic'}
- useCanvasRendering={useCanvasRendering}
allowDownloads={allowDownloads}
/>
);
diff --git a/frontend/src/components/gallery/HeroHeader.tsx b/frontend/src/components/gallery/HeroHeader.tsx
index 6f183799..ec187f81 100644
--- a/frontend/src/components/gallery/HeroHeader.tsx
+++ b/frontend/src/components/gallery/HeroHeader.tsx
@@ -23,9 +23,7 @@ interface HeroHeaderProps {
heroLogoPosition?: 'top' | 'center' | 'bottom';
dividerStyle?: HeroDividerStyle;
allowDownloads?: boolean;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
onScrollToContent?: () => void;
// Hero image anchor position (#162) – keyword or "X% Y%" focal point
heroImageAnchor?: string;
@@ -43,8 +41,6 @@ export const HeroHeader: React.FC = ({
heroLogoSize = 'medium',
heroLogoPosition = 'top',
dividerStyle = 'wave',
- protectionLevel = 'standard',
- useCanvasRendering = false,
onScrollToContent,
heroImageAnchor = 'center'
}) => {
@@ -142,7 +138,6 @@ export const HeroHeader: React.FC = ({
style={{ objectPosition: heroImageAnchor }}
isGallery={true}
slug={slug}
- useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
/>
{/* Overlay */}
diff --git a/frontend/src/components/gallery/PhotoGrid.tsx b/frontend/src/components/gallery/PhotoGrid.tsx
index 154e8858..e41021db 100644
--- a/frontend/src/components/gallery/PhotoGrid.tsx
+++ b/frontend/src/components/gallery/PhotoGrid.tsx
@@ -196,7 +196,6 @@ export const PhotoGrid: React.FC = ({
allowDownloads={allowDownloads}
protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
slug={slug}
feedbackEnabled={feedbackEnabled}
/>
@@ -214,6 +213,7 @@ export const PhotoGrid: React.FC = ({
allowDownloads={allowDownloads}
protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
+ useCanvasRendering={useCanvasRendering}
disableRightClick={disableRightClick}
enableDevtoolsProtection={enableDevtoolsProtection}
/>
@@ -231,7 +231,6 @@ interface PhotoThumbnailProps {
allowDownloads?: boolean;
protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
slug: string; // Add slug as required prop
feedbackEnabled?: boolean;
}
@@ -244,7 +243,6 @@ const PhotoThumbnail: React.FC = ({
onDownload,
allowDownloads = true,
protectionLevel = 'standard',
- useCanvasRendering = false,
slug,
feedbackEnabled = false
}) => {
@@ -268,7 +266,6 @@ const PhotoThumbnail: React.FC = ({
loading="lazy"
isGallery={true}
slug={slug}
- useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
onProtectionViolation={(violationType) => {
// Track analytics
if (typeof window !== 'undefined' && (window as any).umami) {
diff --git a/frontend/src/components/gallery/PhotoGridWithLayouts.tsx b/frontend/src/components/gallery/PhotoGridWithLayouts.tsx
index 62a95481..b0ea6459 100644
--- a/frontend/src/components/gallery/PhotoGridWithLayouts.tsx
+++ b/frontend/src/components/gallery/PhotoGridWithLayouts.tsx
@@ -361,9 +361,7 @@ export const PhotoGridWithLayouts: React.FC = ({
heroLogoPosition={heroLogoPosition}
dividerStyle={heroDividerStyle}
allowDownloads={allowDownloads}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
heroImageAnchor={heroImageAnchor}
/>
)}
diff --git a/frontend/src/components/gallery/__tests__/canvasLightboxOnly.test.ts b/frontend/src/components/gallery/__tests__/canvasLightboxOnly.test.ts
new file mode 100644
index 00000000..d8a8c45e
--- /dev/null
+++ b/frontend/src/components/gallery/__tests__/canvasLightboxOnly.test.ts
@@ -0,0 +1,56 @@
+/**
+ * Canvas rendering is a lightbox concern, not a tile concern.
+ *
+ * A canvas pins a backing store of naturalWidth × naturalHeight × 4 bytes
+ * that the browser is not allowed to evict, and iOS Safari has a hard
+ * budget for canvas memory that fails silently when exceeded — blank
+ * tiles, no error. A gallery is hundreds of tiles and one lightbox image,
+ * so the tiles render
whatever the protection level says, and the
+ * lightbox keeps the per-event toggle and the `maximum` implication.
+ *
+ * Source-level pin: nothing under components/gallery except PhotoLightbox
+ * may hand `useCanvasRendering` to AuthenticatedImage.
+ */
+import fs from 'fs';
+import path from 'path';
+import { describe, it, expect } from 'vitest';
+
+const root = path.resolve(__dirname, '..');
+function walk(dir: string): string[] {
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
+ const file = path.join(dir, entry.name);
+ if (entry.isDirectory()) return entry.name === '__tests__' ? [] : walk(file);
+ return file.endsWith('.tsx') ? [file] : [];
+ });
+}
+
+describe('canvas rendering stays in the lightbox', () => {
+ const files = walk(root);
+ const lightbox = path.join(root, 'PhotoLightbox.tsx');
+
+ /** The JSX props of every in a file, plus every
+ * `imageProps={{ ... }}` object a layout hands to PhotoCard to spread in. */
+ const imageProps = (source: string) => [
+ ...source.split(' chunk.split('/>')[0]),
+ ...source.split('imageProps={{').slice(1).map((chunk) => chunk.split('}}')[0]),
+ ];
+
+ it('only PhotoLightbox passes useCanvasRendering to AuthenticatedImage', () => {
+ const offenders = files.filter((file) => file !== lightbox
+ && imageProps(fs.readFileSync(file, 'utf8')).some((props) => props.includes('useCanvasRendering')));
+ expect(offenders.map((f) => path.relative(root, f))).toEqual([]);
+ // The pin has teeth: the lightbox itself is caught by the same probe.
+ expect(imageProps(fs.readFileSync(lightbox, 'utf8')).some((props) => props.includes('useCanvasRendering'))).toBe(true);
+ });
+
+ it('only PhotoLightbox turns canvas on for protection level maximum', () => {
+ const offenders = files.filter((file) => file !== lightbox
+ && /useCanvasRendering[^\n]*protectionLevel === 'maximum'/.test(fs.readFileSync(file, 'utf8')));
+ expect(offenders.map((f) => path.relative(root, f))).toEqual([]);
+ });
+
+ it('the lightbox still does both', () => {
+ const source = fs.readFileSync(lightbox, 'utf8');
+ expect(source).toMatch(/useCanvasRendering=\{useCanvasRendering \|\| protectionLevel === 'maximum'\}/);
+ });
+});
diff --git a/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx b/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx
index e818d7b8..926ce009 100644
--- a/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx
+++ b/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx
@@ -47,6 +47,7 @@ export interface BaseGalleryLayoutProps {
onPickResolution?: (photoIds: number[]) => void;
protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
+ /** Canvas rendering applies to the lightbox only; tiles always render
. */
useCanvasRendering?: boolean;
feedbackEnabled?: boolean;
feedbackOptions?: {
diff --git a/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx b/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx
index e6c99b34..0a2dd95a 100644
--- a/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx
+++ b/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx
@@ -46,9 +46,7 @@ interface PhotoCardProps {
isLiked: boolean;
slug: string;
allowDownloads?: boolean;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
feedbackEnabled?: boolean;
// #506: track the per-event "allow likes" toggle so the per-photo
// Like button respects it. `feedbackEnabled` alone isn't enough —
@@ -68,8 +66,6 @@ const PhotoCard: React.FC = ({
isSelectionMode,
isLiked,
slug,
- protectionLevel = 'standard',
- useCanvasRendering = false,
feedbackEnabled = false,
allowLikes = false,
index
@@ -122,7 +118,6 @@ const PhotoCard: React.FC = ({
loading="lazy"
isGallery={true}
slug={slug}
- useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
/>
{/* Colour label (#1044) — same badge every layout uses. */}
@@ -208,9 +203,7 @@ export const GalleryPremiumLayout: React.FC = ({
allowDownloads = true,
downloadChoices,
onPickResolution,
- protectionLevel = 'standard',
useEnhancedProtection = false,
- useCanvasRendering = false,
feedbackEnabled = false,
feedbackOptions,
heroPhotoOverride,
@@ -629,9 +622,7 @@ export const GalleryPremiumLayout: React.FC = ({
isLiked={likedPhotoIds.has(originalPhoto.id)}
slug={slug}
allowDownloads={allowDownloads}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
feedbackEnabled={feedbackEnabled}
allowLikes={!!feedbackOptions?.allowLikes}
index={photoIndex}
diff --git a/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx b/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx
index 6f91e82e..bc5f6511 100644
--- a/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx
+++ b/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx
@@ -255,9 +255,7 @@ export const GalleryStoryLayout: React.FC = ({
photo={heroPhoto}
slug={slug}
allowDownloads={allowDownloads}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
/>
{/* Main Content - Scenes */}
@@ -281,9 +279,7 @@ export const GalleryStoryLayout: React.FC = ({
onPhotoClick={handleOpenLightbox}
slug={slug}
allowDownloads={allowDownloads}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
/>
) : (
@@ -298,9 +294,7 @@ export const GalleryStoryLayout: React.FC
= ({
slug={slug}
galleryId={`gallery-${scene.id}`}
allowDownloads={allowDownloads}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
// Mark first photo in each grid as featured
featured={index === 0 && scene.photos.length > 4}
/>
diff --git a/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx b/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx
index e10f5c6e..61f1d5d6 100644
--- a/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx
+++ b/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx
@@ -18,9 +18,7 @@ interface GridPhotoProps {
animationType?: string;
allowDownloads?: boolean;
slug?: string;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
feedbackEnabled?: boolean;
feedbackOptions?: {
allowLikes?: boolean;
@@ -47,8 +45,6 @@ const GridPhoto: React.FC = ({
animationType = 'fade',
allowDownloads = true,
slug,
- protectionLevel = 'standard',
- useCanvasRendering = false,
feedbackEnabled = false,
feedbackOptions,
savedIdentity,
@@ -130,7 +126,6 @@ const GridPhoto: React.FC = ({
loading: 'lazy',
isGallery: true,
slug,
- useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum',
onProtectionViolation: (violationType: string) => {
console.warn(`Protection violation on grid photo ${photo.id}: ${violationType}`);
},
@@ -200,9 +195,7 @@ export const GridGalleryLayout: React.FC = ({
isSelectionMode = false,
onPhotoSelect,
allowDownloads = true,
- protectionLevel = 'standard',
useEnhancedProtection = false,
- useCanvasRendering = false,
feedbackEnabled = false,
feedbackOptions,
isClient = false,
@@ -255,9 +248,7 @@ export const GridGalleryLayout: React.FC = ({
animationType={animation}
allowDownloads={allowDownloads}
slug={slug}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
feedbackEnabled={feedbackEnabled}
feedbackOptions={feedbackOptions}
savedIdentity={savedIdentity}
diff --git a/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx b/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx
index 8e0d5113..b4f3295d 100644
--- a/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx
+++ b/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx
@@ -40,9 +40,7 @@ interface JustifiedPhotoProps {
animationType?: string;
allowDownloads?: boolean;
slug?: string;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
feedbackEnabled?: boolean;
feedbackOptions?: {
allowLikes?: boolean;
@@ -69,8 +67,6 @@ const JustifiedPhoto: React.FC = ({
animationType = 'fade',
allowDownloads = true,
slug,
- protectionLevel = 'standard',
- useCanvasRendering = false,
feedbackEnabled = false,
feedbackOptions,
savedIdentity,
@@ -133,7 +129,6 @@ const JustifiedPhoto: React.FC = ({
loading: 'lazy',
isGallery: true,
slug,
- useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum',
onProtectionViolation: (violationType: string) => {
console.warn(`Protection violation on justified photo ${photo.id}: ${violationType}`);
},
@@ -214,9 +209,7 @@ export const JustifiedGalleryLayout: React.FC = ({
isSelectionMode = false,
onPhotoSelect,
allowDownloads = true,
- protectionLevel = 'standard',
useEnhancedProtection = false,
- useCanvasRendering = false,
feedbackEnabled = false,
feedbackOptions,
// Hero props
@@ -399,7 +392,6 @@ export const JustifiedGalleryLayout: React.FC = ({
className="w-full h-full object-cover"
isGallery={true}
slug={slug}
- useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
/>
{/* Overlay */}
@@ -523,9 +515,7 @@ export const JustifiedGalleryLayout: React.FC = ({
animationType={animation}
allowDownloads={allowDownloads}
slug={slug}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
feedbackEnabled={feedbackEnabled}
feedbackOptions={feedbackOptions}
savedIdentity={savedIdentity}
diff --git a/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx b/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx
index d88212f8..c001e771 100644
--- a/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx
+++ b/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx
@@ -14,9 +14,7 @@ interface StoryCarouselProps {
slug: string;
id: string;
allowDownloads?: boolean;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
}
export const StoryCarousel: React.FC = ({
@@ -27,9 +25,7 @@ export const StoryCarousel: React.FC = ({
slug,
id,
allowDownloads = true,
- protectionLevel = 'standard',
useEnhancedProtection = false,
- useCanvasRendering = false
}) => {
return (
@@ -53,9 +49,7 @@ export const StoryCarousel: React.FC = ({
slug={slug}
galleryId={id}
allowDownloads={allowDownloads}
- protectionLevel={protectionLevel}
useEnhancedProtection={useEnhancedProtection}
- useCanvasRendering={useCanvasRendering}
/>
diff --git a/frontend/src/components/gallery/layouts/story/StoryHero.tsx b/frontend/src/components/gallery/layouts/story/StoryHero.tsx
index 66293623..6c56b841 100644
--- a/frontend/src/components/gallery/layouts/story/StoryHero.tsx
+++ b/frontend/src/components/gallery/layouts/story/StoryHero.tsx
@@ -11,9 +11,7 @@ interface StoryHeroProps {
photo?: Photo | null;
slug: string;
allowDownloads?: boolean;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
}
export const StoryHero: React.FC = ({
@@ -22,8 +20,6 @@ export const StoryHero: React.FC = ({
stats,
photo,
slug,
- protectionLevel = 'standard',
- useCanvasRendering = false
}) => {
const formattedDate = date
? new Date(date).toLocaleDateString('en-US', {
@@ -49,7 +45,6 @@ export const StoryHero: React.FC = ({
className="w-full h-full object-cover"
isGallery={true}
slug={slug}
- useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
/>
) : (
diff --git a/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx b/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx
index a5eb5643..2cfeee02 100644
--- a/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx
+++ b/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx
@@ -14,9 +14,7 @@ interface StoryPhotoCardProps {
onClick?: () => void;
slug: string;
allowDownloads?: boolean;
- protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
useEnhancedProtection?: boolean;
- useCanvasRendering?: boolean;
featured?: boolean;
galleryId: string;
}
@@ -28,8 +26,6 @@ export const StoryPhotoCard: React.FC = ({
onToggleFavorite,
onClick,
slug,
- protectionLevel = 'standard',
- useCanvasRendering = false,
featured = false,
galleryId: _galleryId
}) => {
@@ -103,7 +99,6 @@ export const StoryPhotoCard: React.FC = ({
}`}
isGallery={true}
slug={slug}
- useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
/>
)}
diff --git a/frontend/src/features/settings/tabs/ImageSecurityTab.tsx b/frontend/src/features/settings/tabs/ImageSecurityTab.tsx
index 7c2a3354..86ccd266 100644
--- a/frontend/src/features/settings/tabs/ImageSecurityTab.tsx
+++ b/frontend/src/features/settings/tabs/ImageSecurityTab.tsx
@@ -184,7 +184,7 @@ export const ImageSecurityTab: React.FC = () => {
/>
- {t('settings.imageSecurity.enableCanvas', 'Enable canvas rendering by default (advanced protection)')}
+ {t('settings.imageSecurity.enableCanvas', 'Enable canvas rendering in the lightbox by default (advanced protection)')}
diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json
index 0f3567c4..3eef43b2 100644
--- a/frontend/src/i18n/locales/de.json
+++ b/frontend/src/i18n/locales/de.json
@@ -1934,7 +1934,7 @@
"disableRightClick": "Rechtsklick-Menü blockieren",
"watermarkDownloads": "Wasserzeichen bei Downloads hinzufügen",
"enableDevtoolsProtection": "Entwicklertools erkennen",
- "useCanvasRendering": "Canvas-Rendering (erweiterter Schutz)",
+ "useCanvasRendering": "Canvas-Rendering in der Lightbox (erweiterter Schutz)",
"protectionInfo": "Schutzfunktionen helfen, unerlaubte Downloads zu verhindern, können jedoch nicht alle Methoden blockieren.",
"protectionLevelBasic": "Einfach - Nur Rechtsklick-Sperre",
"protectionLevelStandard": "Standard - Tastenkombinationen blockiert",
@@ -2374,7 +2374,7 @@
"protectionLevel": "Standard-Schutzstufe",
"imageQuality": "Standard-Bildqualität",
"enableDevtools": "DevTools-Erkennung standardmäßig aktivieren",
- "enableCanvas": "Canvas-Rendering standardmäßig aktivieren (erweiterter Schutz)",
+ "enableCanvas": "Canvas-Rendering in der Lightbox standardmäßig aktivieren (erweiterter Schutz)",
"rateLimiting": "Ratenbegrenzung",
"rateLimitingHelp": "Begrenzen Sie, wie viele Bilder angefordert werden können, um Scraping zu verhindern.",
"requestsPerMinute": "Anfragen pro Minute",
diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json
index 4b300b5c..61df73c0 100644
--- a/frontend/src/i18n/locales/en.json
+++ b/frontend/src/i18n/locales/en.json
@@ -1430,7 +1430,7 @@
"disableRightClick": "Block right-click menu",
"watermarkDownloads": "Add watermark to downloads",
"enableDevtoolsProtection": "Detect developer tools",
- "useCanvasRendering": "Canvas rendering (advanced protection)",
+ "useCanvasRendering": "Canvas rendering in the lightbox (advanced protection)",
"protectionInfo": "Protection features help prevent unauthorized downloads but cannot block all methods.",
"protectionLevelBasic": "Basic - Right-click blocking only",
"protectionLevelStandard": "Standard - Keyboard shortcuts blocked",
@@ -1937,7 +1937,7 @@
"protectionLevel": "Default Protection Level",
"imageQuality": "Default Image Quality",
"enableDevtools": "Enable DevTools detection by default",
- "enableCanvas": "Enable canvas rendering by default (advanced protection)",
+ "enableCanvas": "Enable canvas rendering in the lightbox by default (advanced protection)",
"rateLimiting": "Rate Limiting",
"rateLimitingHelp": "Limit how many images can be requested to prevent scraping.",
"requestsPerMinute": "Requests per minute",
diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json
index f18625db..03c7b368 100644
--- a/frontend/src/i18n/locales/fr.json
+++ b/frontend/src/i18n/locales/fr.json
@@ -498,7 +498,7 @@
"disableRightClick": "Bloquer le clic droit",
"watermarkDownloads": "Ajouter un filigrane aux téléchargements",
"enableDevtoolsProtection": "Détecter les outils de développement",
- "useCanvasRendering": "Rendu canvas (protection avancée)",
+ "useCanvasRendering": "Rendu canvas dans la visionneuse (protection avancée)",
"protectionInfo": "Les fonctionnalités de protection aident à prévenir les téléchargements non autorisés mais ne peuvent pas bloquer toutes les méthodes.",
"protectionLevelBasic": "Basique - Blocage du clic droit uniquement",
"protectionLevelStandard": "Standard - Blocage des raccourcis clavier",
@@ -912,7 +912,7 @@
"protectionLevel": "Niveau de protection par défaut",
"imageQuality": "Qualité d'image par défaut",
"enableDevtools": "Activer la détection des outils DevTools par défaut",
- "enableCanvas": "Activer le rendu canvas par défaut (protection avancée)",
+ "enableCanvas": "Activer le rendu canvas dans la visionneuse par défaut (protection avancée)",
"rateLimiting": "Limitation de débit",
"rateLimitingHelp": "Limitez le nombre d'images qui peuvent être demandées pour éviter le scraping.",
"requestsPerMinute": "Requêtes par minute",
diff --git a/frontend/src/i18n/locales/sl.json b/frontend/src/i18n/locales/sl.json
index a02444bc..c13ca419 100644
--- a/frontend/src/i18n/locales/sl.json
+++ b/frontend/src/i18n/locales/sl.json
@@ -498,7 +498,7 @@
"disableRightClick": "Blokiraj meni desnega klika",
"watermarkDownloads": "Dodaj vodni žig prenosom",
"enableDevtoolsProtection": "Zaznaj orodja za razvijalce",
- "useCanvasRendering": "Izris prek canvas (napredna zaščita)",
+ "useCanvasRendering": "Izris prek canvas v pregledovalniku (napredna zaščita)",
"protectionInfo": "Zaščitne funkcije pomagajo preprečiti nepooblaščene prenose, vendar ne morejo blokirati vseh metod.",
"protectionLevelBasic": "Osnovno - samo blokada desnega klika",
"protectionLevelStandard": "Standardno - blokirane bližnjice na tipkovnici",
@@ -912,7 +912,7 @@
"protectionLevel": "Privzeta raven zaščite",
"imageQuality": "Privzeta kakovost slike",
"enableDevtools": "Privzeto omogoči zaznavanje DevTools",
- "enableCanvas": "Privzeto omogoči izris prek canvas (napredna zaščita)",
+ "enableCanvas": "Privzeto omogoči izris prek canvas v pregledovalniku (napredna zaščita)",
"rateLimiting": "Omejevanje hitrosti",
"rateLimitingHelp": "Omejite, koliko slik je mogoče zahtevati, da preprečite množično pobiranje.",
"requestsPerMinute": "Zahtev na minuto",
diff --git a/frontend/src/pages/admin/event-details/EventInformationCard.tsx b/frontend/src/pages/admin/event-details/EventInformationCard.tsx
index 38aa686e..6311b2be 100644
--- a/frontend/src/pages/admin/event-details/EventInformationCard.tsx
+++ b/frontend/src/pages/admin/event-details/EventInformationCard.tsx
@@ -669,7 +669,7 @@ export const EventInformationCard: React.FC = ({
className="w-4 h-4 text-accent border-neutral-300 dark:border-neutral-600 rounded focus:ring-primary-500"
/>
- {t('events.useCanvasRendering', 'Canvas rendering (advanced protection)')}
+ {t('events.useCanvasRendering', 'Canvas rendering in the lightbox (advanced protection)')}