release: v0.19.0
Release v0.19.0. See the `## [0.19.0] — 2026-09-29` section of [CHANGELOG.md](https://github.com/ralksta/immich-folio/blob/dev/CHANGELOG.md) for the full list. Highlights: client proofing links (#683), custom content pages (#738), asset picker search (#740), concurrent-edit detection (#742), env-locked settings (#739), an accessibility baseline (#741), three security fixes with advisories (#737, #755, #759), and a pre-release quality pass (#780–#797). --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ralksta <ralksta@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Ralf <rohlenbo79@gmail.com> Co-authored-by: Paul Thies <110185070+ImScheinox@users.noreply.github.com> Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com> Co-authored-by: Lance Martin <lancetaylor95@gmail.com>
This commit is contained in:
@@ -19,6 +19,8 @@ export const de: Dictionary = {
|
||||
map: 'Karte',
|
||||
journal: 'Journal',
|
||||
skipToContent: 'Zum Inhalt springen',
|
||||
mainNavAria: 'Hauptnavigation',
|
||||
heroNavAria: 'Bereiche',
|
||||
openMenu: 'Menü öffnen',
|
||||
closeMenu: 'Menü schließen',
|
||||
},
|
||||
@@ -44,12 +46,15 @@ export const de: Dictionary = {
|
||||
nextEntryAria: (title: string) => `Nächster Beitrag: ${title}`,
|
||||
entryNavAria: 'Journal-Navigation',
|
||||
loadingGallery: 'Galerie wird geladen',
|
||||
gallery: 'Galerie',
|
||||
loadingPhotos: 'Fotos werden geladen',
|
||||
downloadAlbum: 'Album herunterladen',
|
||||
},
|
||||
|
||||
home: {
|
||||
enter: 'Eintreten',
|
||||
pauseSlideshow: 'Diashow anhalten',
|
||||
playSlideshow: 'Diashow abspielen',
|
||||
},
|
||||
|
||||
error: {
|
||||
@@ -58,8 +63,6 @@ export const de: Dictionary = {
|
||||
errorTitle: 'Etwas ist schiefgelaufen',
|
||||
errorText:
|
||||
'Diese Seite konnte gerade nicht geladen werden. Das ist meist vorübergehend — bitte gleich noch einmal versuchen.',
|
||||
siteErrorText:
|
||||
'Diese Website konnte gerade nicht geladen werden. Das ist meist vorübergehend — bitte gleich noch einmal versuchen.',
|
||||
tryAgain: 'Erneut versuchen',
|
||||
reference: (digest: string) => `Referenz: ${digest}`,
|
||||
},
|
||||
@@ -71,6 +74,7 @@ export const de: Dictionary = {
|
||||
immichUnavailable:
|
||||
'Die Fotobibliothek ist gerade nicht erreichbar. Bitte gleich noch einmal versuchen.',
|
||||
back: 'Zurück zur Galerie',
|
||||
limitReached: 'Das Download-Limit für diesen Link ist erreicht.',
|
||||
},
|
||||
|
||||
theme: {
|
||||
@@ -82,11 +86,18 @@ export const de: Dictionary = {
|
||||
password: {
|
||||
subtitle: 'Diese Galerie ist passwortgeschützt.',
|
||||
siteSubtitle: 'Diese Website ist passwortgeschützt.',
|
||||
pageSubtitle: 'Diese Seite ist passwortgeschützt.',
|
||||
journalSubtitle: 'Dieser Journal-Eintrag ist passwortgeschützt.',
|
||||
protectedPage: 'Geschützte Seite',
|
||||
placeholder: 'Passwort eingeben',
|
||||
submit: 'Öffnen',
|
||||
verifying: 'Wird geprüft…',
|
||||
incorrect: 'Falsches Passwort. Bitte erneut versuchen.',
|
||||
failed: 'Passwort konnte nicht geprüft werden. Bitte später erneut versuchen.',
|
||||
tooManyAttempts: (seconds: number | null) =>
|
||||
seconds
|
||||
? `Zu viele Versuche – bitte in ${seconds} ${seconds === 1 ? 'Sekunde' : 'Sekunden'} erneut versuchen.`
|
||||
: 'Zu viele Versuche – bitte später erneut versuchen.',
|
||||
},
|
||||
|
||||
about: {
|
||||
@@ -104,6 +115,9 @@ export const de: Dictionary = {
|
||||
loading: 'Karte wird geladen…',
|
||||
loadFailed: (status: number) => `Kartendaten konnten nicht geladen werden (${status})`,
|
||||
initFailed: 'Karte konnte nicht initialisiert werden',
|
||||
zoomIn: 'Vergrößern',
|
||||
zoomOut: 'Verkleinern',
|
||||
leafletTitle: 'Eine JavaScript-Bibliothek für interaktive Karten',
|
||||
},
|
||||
|
||||
subpage: {
|
||||
@@ -130,6 +144,7 @@ export const de: Dictionary = {
|
||||
|
||||
lightbox: {
|
||||
viewer: 'Bildansicht',
|
||||
position: (n: number, total: number) => `Foto ${n} von ${total}`,
|
||||
openPhoto: (n: number) => `Foto ${n} ansehen`,
|
||||
close: 'Schließen',
|
||||
closeTitle: 'Schließen (Esc)',
|
||||
@@ -164,10 +179,10 @@ export const de: Dictionary = {
|
||||
downloadTitle: 'Originaldatei herunterladen (d)',
|
||||
downloadShort: 'Original',
|
||||
shortcutDownload: 'Original herunterladen',
|
||||
shortcutSlideshow: 'Diaschau',
|
||||
shortcutSlideshowRunning: (seconds: number) => `Diaschau — alle ${seconds}s`,
|
||||
slideshowStopped: 'Diaschau angehalten',
|
||||
slideshowRunning: (seconds: number) => `Diaschau läuft, wechselt alle ${seconds} Sekunden`,
|
||||
shortcutSlideshow: 'Diashow',
|
||||
shortcutSlideshowRunning: (seconds: number) => `Diashow — alle ${seconds}s`,
|
||||
slideshowStopped: 'Diashow angehalten',
|
||||
slideshowRunning: (seconds: number) => `Diashow läuft, wechselt alle ${seconds} Sekunden`,
|
||||
shortcutCopyLink: 'Link zum Foto kopieren',
|
||||
shortcutList: 'Diese Liste',
|
||||
shortcutClose: 'Ansicht schließen',
|
||||
@@ -181,6 +196,7 @@ export const de: Dictionary = {
|
||||
saved: 'Gemerkt',
|
||||
favorite: 'Merken',
|
||||
showAll: 'Alle anzeigen',
|
||||
filterEmpty: 'Keine Fotos ausgewählt.',
|
||||
selected: (n: number) => `❤️ ${n} ausgewählt`,
|
||||
shareExport: 'Teilen & Export',
|
||||
modalTitle: (n: number) => `❤️ Auswahl (${n})`,
|
||||
@@ -200,11 +216,36 @@ export const de: Dictionary = {
|
||||
listEmpty: (albumName: string) => `${albumName}: Keine Fotos ausgewählt.`,
|
||||
listSummary: (albumName: string, count: number, indices: string) =>
|
||||
`${albumName} — Ausgewählte Fotos (${count}): ${indices}`,
|
||||
mailSubject: (n: number) => `Fotoauswahl (${n} Fotos)`,
|
||||
mailSubject: (n: number) => `Fotoauswahl (${plural(n, 'Foto', 'Fotos')})`,
|
||||
mailBody: (list: string, url: string) =>
|
||||
`Hallo,\n\nhier ist meine Fotoauswahl:\n\n${list}\n\nLink zur Auswahl: ${url}\n\nViele Grüße,`,
|
||||
},
|
||||
|
||||
proofSession: {
|
||||
greeting: (name: string) => `Auswahl für ${name}`,
|
||||
intro:
|
||||
'Markiere die gewünschten Fotos mit dem Herz. Deine Auswahl wird laufend gespeichert — du kannst mit diesem Link jederzeit zurückkommen.',
|
||||
saving: 'Wird gespeichert…',
|
||||
saved: 'Auswahl gespeichert',
|
||||
saveFailed:
|
||||
'Deine Auswahl konnte nicht gespeichert werden. Prüfe die Verbindung und versuche es erneut.',
|
||||
review: 'Prüfen & absenden',
|
||||
modalTitle: (n: number) => `Deine Auswahl (${n})`,
|
||||
empty: 'Noch keine Fotos ausgewählt.',
|
||||
submit: 'Auswahl absenden',
|
||||
submitting: 'Wird gesendet…',
|
||||
confirmSubmit: (n: number) =>
|
||||
`${plural(n, 'Foto', 'Fotos')} absenden? Danach lässt sich die Auswahl nicht mehr ändern.`,
|
||||
submitted: 'Danke — deine Auswahl wurde abgeschickt.',
|
||||
locked: 'Diese Auswahl wurde abgeschickt und kann nicht mehr geändert werden.',
|
||||
validUntil: (date: string) => `Dieser Link ist gültig bis ${date}.`,
|
||||
expiredTitle: 'Dieser Link ist abgelaufen',
|
||||
expiredText: 'Bitte frag deinen Fotografen nach einem neuen Link.',
|
||||
downloadSelection: 'Auswahl herunterladen (.zip)',
|
||||
downloadAll: 'Alle Fotos herunterladen (.zip)',
|
||||
downloadsLeft: (n: number) => `Noch ${plural(n, 'Download', 'Downloads')}`,
|
||||
},
|
||||
|
||||
legal: {
|
||||
navLabel: 'Impressum',
|
||||
title: 'Impressum',
|
||||
|
||||
@@ -19,6 +19,8 @@ export const en = {
|
||||
map: 'Map',
|
||||
journal: 'Journal',
|
||||
skipToContent: 'Skip to content',
|
||||
mainNavAria: 'Main',
|
||||
heroNavAria: 'Sections',
|
||||
openMenu: 'Open menu',
|
||||
closeMenu: 'Close menu',
|
||||
},
|
||||
@@ -45,12 +47,15 @@ export const en = {
|
||||
nextEntryAria: (title: string) => `Next entry: ${title}`,
|
||||
entryNavAria: 'Journal entry navigation',
|
||||
loadingGallery: 'Loading gallery',
|
||||
gallery: 'Gallery',
|
||||
loadingPhotos: 'Loading photos',
|
||||
downloadAlbum: 'Download album',
|
||||
},
|
||||
|
||||
home: {
|
||||
enter: 'Enter',
|
||||
pauseSlideshow: 'Pause slideshow',
|
||||
playSlideshow: 'Play slideshow',
|
||||
},
|
||||
|
||||
error: {
|
||||
@@ -59,8 +64,6 @@ export const en = {
|
||||
errorTitle: 'Something went wrong',
|
||||
errorText:
|
||||
'This page could not be loaded right now. It is usually temporary — try again in a moment.',
|
||||
siteErrorText:
|
||||
'This site could not be loaded right now. It is usually temporary — try again in a moment.',
|
||||
tryAgain: 'Try again',
|
||||
reference: (digest: string) => `Reference: ${digest}`,
|
||||
},
|
||||
@@ -72,6 +75,7 @@ export const en = {
|
||||
rateLimited: 'Too many download requests. Please wait a moment and try again.',
|
||||
immichUnavailable: 'The photo library is unavailable right now. Please try again shortly.',
|
||||
back: 'Back to the gallery',
|
||||
limitReached: 'The download limit for this link has been reached.',
|
||||
},
|
||||
|
||||
theme: {
|
||||
@@ -83,11 +87,18 @@ export const en = {
|
||||
password: {
|
||||
subtitle: 'This gallery is password-protected.',
|
||||
siteSubtitle: 'This site is password-protected.',
|
||||
pageSubtitle: 'This page is password-protected.',
|
||||
journalSubtitle: 'This journal entry is password-protected.',
|
||||
protectedPage: 'Protected page',
|
||||
placeholder: 'Enter password',
|
||||
submit: 'Enter',
|
||||
verifying: 'Verifying…',
|
||||
incorrect: 'Incorrect password. Please try again.',
|
||||
failed: 'Unable to verify password. Please try again later.',
|
||||
tooManyAttempts: (seconds: number | null) =>
|
||||
seconds
|
||||
? `Too many attempts. Please try again in ${seconds} ${seconds === 1 ? 'second' : 'seconds'}.`
|
||||
: 'Too many attempts. Please try again later.',
|
||||
},
|
||||
|
||||
about: {
|
||||
@@ -105,6 +116,10 @@ export const en = {
|
||||
loading: 'Loading map…',
|
||||
loadFailed: (status: number) => `Failed to load map data (${status})`,
|
||||
initFailed: 'Failed to initialize map',
|
||||
zoomIn: 'Zoom in',
|
||||
zoomOut: 'Zoom out',
|
||||
// The title on the Leaflet credit in the map's corner.
|
||||
leafletTitle: 'A JavaScript library for interactive maps',
|
||||
},
|
||||
|
||||
subpage: {
|
||||
@@ -131,6 +146,7 @@ export const en = {
|
||||
|
||||
lightbox: {
|
||||
viewer: 'Image viewer',
|
||||
position: (n: number, total: number) => `Photo ${n} of ${total}`,
|
||||
/** A grid tile, which opens the viewer on that photo. */
|
||||
openPhoto: (n: number) => `View photo ${n}`,
|
||||
close: 'Close',
|
||||
@@ -183,6 +199,8 @@ export const en = {
|
||||
saved: 'Saved',
|
||||
favorite: 'Favorite',
|
||||
showAll: 'Show All',
|
||||
/** Shown in place of the grid when the filter is on and nothing is selected. */
|
||||
filterEmpty: 'No photos selected.',
|
||||
selected: (n: number) => `❤️ ${n} Selected`,
|
||||
shareExport: 'Share & Export',
|
||||
modalTitle: (n: number) => `❤️ Selection (${n})`,
|
||||
@@ -203,11 +221,36 @@ export const en = {
|
||||
listEmpty: (albumName: string) => `${albumName}: No photos selected.`,
|
||||
listSummary: (albumName: string, count: number, indices: string) =>
|
||||
`${albumName} — Selected Photos (${count}): ${indices}`,
|
||||
mailSubject: (n: number) => `Photo Selection (${n} items)`,
|
||||
mailSubject: (n: number) => `Photo Selection (${plural(n, 'item', 'items')})`,
|
||||
mailBody: (list: string, url: string) =>
|
||||
`Hello,\n\nHere is my photo selection:\n\n${list}\n\nShare Link: ${url}\n\nBest regards,`,
|
||||
},
|
||||
|
||||
/** Client proofing links (/proof/<token>). */
|
||||
proofSession: {
|
||||
greeting: (name: string) => `Selection for ${name}`,
|
||||
intro:
|
||||
'Tap the heart on the photos you want. Your selection is saved as you go — you can come back with this link at any time.',
|
||||
saving: 'Saving…',
|
||||
saved: 'Selection saved',
|
||||
saveFailed: 'Your selection could not be saved. Check your connection and try again.',
|
||||
review: 'Review & submit',
|
||||
modalTitle: (n: number) => `Your selection (${n})`,
|
||||
empty: 'No photos selected yet.',
|
||||
submit: 'Submit selection',
|
||||
submitting: 'Submitting…',
|
||||
confirmSubmit: (n: number) =>
|
||||
`Submit ${plural(n, 'photo', 'photos')}? The selection cannot be changed afterwards.`,
|
||||
submitted: 'Thank you — your selection has been submitted.',
|
||||
locked: 'This selection has been submitted and can no longer be changed.',
|
||||
validUntil: (date: string) => `This link is valid until ${date}.`,
|
||||
expiredTitle: 'This link has expired',
|
||||
expiredText: 'Please ask your photographer for a new link.',
|
||||
downloadSelection: 'Download selection (.zip)',
|
||||
downloadAll: 'Download all photos (.zip)',
|
||||
downloadsLeft: (n: number) => `${plural(n, 'download', 'downloads')} left`,
|
||||
},
|
||||
|
||||
legal: {
|
||||
navLabel: 'Legal Notice',
|
||||
title: 'Legal Notice',
|
||||
|
||||
@@ -19,6 +19,8 @@ export const es: Dictionary = {
|
||||
map: 'Mapa',
|
||||
journal: 'Diario',
|
||||
skipToContent: 'Saltar al contenido',
|
||||
mainNavAria: 'Navegación principal',
|
||||
heroNavAria: 'Secciones',
|
||||
openMenu: 'Abrir menú',
|
||||
closeMenu: 'Cerrar menú',
|
||||
},
|
||||
@@ -44,12 +46,15 @@ export const es: Dictionary = {
|
||||
nextEntryAria: (title: string) => `Entrada siguiente: ${title}`,
|
||||
entryNavAria: 'Navegación entre entradas del diario',
|
||||
loadingGallery: 'Cargando la galería',
|
||||
gallery: 'Galería',
|
||||
loadingPhotos: 'Cargando fotos',
|
||||
downloadAlbum: 'Descargar álbum',
|
||||
},
|
||||
|
||||
home: {
|
||||
enter: 'Entrar',
|
||||
pauseSlideshow: 'Pausar la presentación',
|
||||
playSlideshow: 'Reproducir la presentación',
|
||||
},
|
||||
|
||||
error: {
|
||||
@@ -58,8 +63,6 @@ export const es: Dictionary = {
|
||||
errorTitle: 'Algo ha salido mal',
|
||||
errorText:
|
||||
'No se ha podido cargar esta página. Suele ser algo temporal: inténtalo de nuevo en un momento.',
|
||||
siteErrorText:
|
||||
'No se ha podido cargar este sitio. Suele ser algo temporal: inténtalo de nuevo en un momento.',
|
||||
tryAgain: 'Reintentar',
|
||||
reference: (digest: string) => `Referencia: ${digest}`,
|
||||
},
|
||||
@@ -71,6 +74,7 @@ export const es: Dictionary = {
|
||||
immichUnavailable:
|
||||
'La fototeca no está disponible en este momento. Vuelve a intentarlo en breve.',
|
||||
back: 'Volver a la galería',
|
||||
limitReached: 'Se ha alcanzado el límite de descargas de este enlace.',
|
||||
},
|
||||
|
||||
theme: {
|
||||
@@ -82,11 +86,18 @@ export const es: Dictionary = {
|
||||
password: {
|
||||
subtitle: 'Esta galería está protegida con contraseña.',
|
||||
siteSubtitle: 'Este sitio está protegido con contraseña.',
|
||||
pageSubtitle: 'Esta página está protegida con contraseña.',
|
||||
journalSubtitle: 'Esta entrada del diario está protegida con contraseña.',
|
||||
protectedPage: 'Página protegida',
|
||||
placeholder: 'Introduce la contraseña',
|
||||
submit: 'Entrar',
|
||||
verifying: 'Verificando…',
|
||||
incorrect: 'Contraseña incorrecta. Inténtalo de nuevo.',
|
||||
failed: 'No se ha podido verificar la contraseña. Inténtalo más tarde.',
|
||||
tooManyAttempts: (seconds: number | null) =>
|
||||
seconds
|
||||
? `Demasiados intentos. Inténtalo de nuevo en ${seconds} ${seconds === 1 ? 'segundo' : 'segundos'}.`
|
||||
: 'Demasiados intentos. Inténtalo más tarde.',
|
||||
},
|
||||
|
||||
about: {
|
||||
@@ -104,6 +115,9 @@ export const es: Dictionary = {
|
||||
loading: 'Cargando el mapa…',
|
||||
loadFailed: (status: number) => `No se pudieron cargar los datos del mapa (${status})`,
|
||||
initFailed: 'No se pudo inicializar el mapa',
|
||||
zoomIn: 'Acercar',
|
||||
zoomOut: 'Alejar',
|
||||
leafletTitle: 'Una biblioteca de JavaScript para mapas interactivos',
|
||||
},
|
||||
|
||||
subpage: {
|
||||
@@ -130,6 +144,7 @@ export const es: Dictionary = {
|
||||
|
||||
lightbox: {
|
||||
viewer: 'Visor de imágenes',
|
||||
position: (n: number, total: number) => `Foto ${n} de ${total}`,
|
||||
openPhoto: (n: number) => `Ver foto ${n}`,
|
||||
close: 'Cerrar',
|
||||
closeTitle: 'Cerrar (Esc)',
|
||||
@@ -181,6 +196,7 @@ export const es: Dictionary = {
|
||||
saved: 'Guardado',
|
||||
favorite: 'Favorito',
|
||||
showAll: 'Mostrar todo',
|
||||
filterEmpty: 'No hay fotos seleccionadas.',
|
||||
selected: (n: number) => `❤️ ${n} ${n === 1 ? 'seleccionada' : 'seleccionadas'}`,
|
||||
shareExport: 'Compartir y exportar',
|
||||
modalTitle: (n: number) => `❤️ Selección (${n})`,
|
||||
@@ -205,6 +221,30 @@ export const es: Dictionary = {
|
||||
`Hola:\n\nEsta es mi selección de fotos:\n\n${list}\n\nEnlace: ${url}\n\nUn saludo,`,
|
||||
},
|
||||
|
||||
proofSession: {
|
||||
greeting: (name: string) => `Selección para ${name}`,
|
||||
intro:
|
||||
'Toca el corazón en las fotos que quieras. Tu selección se guarda sobre la marcha: puedes volver con este enlace cuando quieras.',
|
||||
saving: 'Guardando…',
|
||||
saved: 'Selección guardada',
|
||||
saveFailed: 'No se ha podido guardar tu selección. Revisa la conexión e inténtalo de nuevo.',
|
||||
review: 'Revisar y enviar',
|
||||
modalTitle: (n: number) => `Tu selección (${n})`,
|
||||
empty: 'Todavía no has seleccionado ninguna foto.',
|
||||
submit: 'Enviar selección',
|
||||
submitting: 'Enviando…',
|
||||
confirmSubmit: (n: number) =>
|
||||
`¿Enviar ${plural(n, 'foto', 'fotos')}? Después no podrás cambiar la selección.`,
|
||||
submitted: 'Gracias: tu selección se ha enviado.',
|
||||
locked: 'Esta selección ya se ha enviado y no se puede modificar.',
|
||||
validUntil: (date: string) => `Este enlace es válido hasta el ${date}.`,
|
||||
expiredTitle: 'Este enlace ha caducado',
|
||||
expiredText: 'Pide un enlace nuevo a tu fotógrafo.',
|
||||
downloadSelection: 'Descargar selección (.zip)',
|
||||
downloadAll: 'Descargar todas las fotos (.zip)',
|
||||
downloadsLeft: (n: number) => `${plural(n, 'descarga restante', 'descargas restantes')}`,
|
||||
},
|
||||
|
||||
legal: {
|
||||
navLabel: 'Aviso legal',
|
||||
title: 'Aviso legal',
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
import type { Dictionary } from '../index';
|
||||
|
||||
const plural = (n: number, one: string, other: string) => `${n} ${n === 1 ? one : other}`;
|
||||
// CLDR: French puts 0 in the singular ("0 photo", "0 jour"), unlike English.
|
||||
const isOne = (n: number) => n === 0 || n === 1;
|
||||
const plural = (n: number, one: string, other: string) => `${n} ${isOne(n) ? one : other}`;
|
||||
|
||||
export const fr: Dictionary = {
|
||||
dateLocale: 'fr-FR',
|
||||
@@ -19,6 +21,8 @@ export const fr: Dictionary = {
|
||||
map: 'Carte',
|
||||
journal: 'Journal',
|
||||
skipToContent: 'Aller au contenu',
|
||||
mainNavAria: 'Navigation principale',
|
||||
heroNavAria: 'Rubriques',
|
||||
openMenu: 'Ouvrir le menu',
|
||||
closeMenu: 'Fermer le menu',
|
||||
},
|
||||
@@ -44,12 +48,15 @@ export const fr: Dictionary = {
|
||||
nextEntryAria: (title: string) => `Article suivant : ${title}`,
|
||||
entryNavAria: 'Navigation entre les articles du journal',
|
||||
loadingGallery: 'Chargement de la galerie',
|
||||
gallery: 'Galerie',
|
||||
loadingPhotos: 'Chargement des photos',
|
||||
downloadAlbum: 'Télécharger l’album',
|
||||
},
|
||||
|
||||
home: {
|
||||
enter: 'Entrer',
|
||||
pauseSlideshow: 'Mettre le diaporama en pause',
|
||||
playSlideshow: 'Lancer le diaporama',
|
||||
},
|
||||
|
||||
error: {
|
||||
@@ -58,8 +65,6 @@ export const fr: Dictionary = {
|
||||
errorTitle: 'Une erreur est survenue',
|
||||
errorText:
|
||||
'Cette page n’a pas pu être chargée. C’est généralement temporaire — réessayez dans un instant.',
|
||||
siteErrorText:
|
||||
'Ce site n’a pas pu être chargé. C’est généralement temporaire — réessayez dans un instant.',
|
||||
tryAgain: 'Réessayer',
|
||||
reference: (digest: string) => `Référence : ${digest}`,
|
||||
},
|
||||
@@ -71,6 +76,7 @@ export const fr: Dictionary = {
|
||||
immichUnavailable:
|
||||
'La photothèque est momentanément indisponible. Veuillez réessayer dans un instant.',
|
||||
back: 'Retour à la galerie',
|
||||
limitReached: 'La limite de téléchargements de ce lien est atteinte.',
|
||||
},
|
||||
|
||||
theme: {
|
||||
@@ -82,11 +88,18 @@ export const fr: Dictionary = {
|
||||
password: {
|
||||
subtitle: 'Cette galerie est protégée par un mot de passe.',
|
||||
siteSubtitle: 'Ce site est protégé par un mot de passe.',
|
||||
pageSubtitle: 'Cette page est protégée par un mot de passe.',
|
||||
journalSubtitle: 'Cet article du journal est protégé par un mot de passe.',
|
||||
protectedPage: 'Page protégée',
|
||||
placeholder: 'Saisissez le mot de passe',
|
||||
submit: 'Entrer',
|
||||
verifying: 'Vérification…',
|
||||
incorrect: 'Mot de passe incorrect. Veuillez réessayer.',
|
||||
failed: 'Impossible de vérifier le mot de passe. Veuillez réessayer plus tard.',
|
||||
tooManyAttempts: (seconds: number | null) =>
|
||||
seconds
|
||||
? `Trop de tentatives. Veuillez réessayer dans ${seconds} ${seconds === 1 ? 'seconde' : 'secondes'}.`
|
||||
: 'Trop de tentatives. Veuillez réessayer plus tard.',
|
||||
},
|
||||
|
||||
about: {
|
||||
@@ -104,6 +117,9 @@ export const fr: Dictionary = {
|
||||
loading: 'Chargement de la carte…',
|
||||
loadFailed: (status: number) => `Échec du chargement des données de la carte (${status})`,
|
||||
initFailed: 'Impossible d’initialiser la carte',
|
||||
zoomIn: 'Zoom avant',
|
||||
zoomOut: 'Zoom arrière',
|
||||
leafletTitle: 'Une bibliothèque JavaScript pour cartes interactives',
|
||||
},
|
||||
|
||||
subpage: {
|
||||
@@ -130,6 +146,7 @@ export const fr: Dictionary = {
|
||||
|
||||
lightbox: {
|
||||
viewer: 'Visionneuse d’images',
|
||||
position: (n: number, total: number) => `Photo ${n} sur ${total}`,
|
||||
openPhoto: (n: number) => `Afficher la photo ${n}`,
|
||||
close: 'Fermer',
|
||||
closeTitle: 'Fermer (Échap)',
|
||||
@@ -182,7 +199,8 @@ export const fr: Dictionary = {
|
||||
saved: 'Enregistré',
|
||||
favorite: 'Favori',
|
||||
showAll: 'Tout afficher',
|
||||
selected: (n: number) => `❤️ ${n} ${n === 1 ? 'sélectionnée' : 'sélectionnées'}`,
|
||||
filterEmpty: 'Aucune photo sélectionnée.',
|
||||
selected: (n: number) => `❤️ ${n} ${isOne(n) ? 'sélectionnée' : 'sélectionnées'}`,
|
||||
shareExport: 'Partager & exporter',
|
||||
modalTitle: (n: number) => `❤️ Sélection (${n})`,
|
||||
closeModal: 'Fermer la fenêtre',
|
||||
@@ -206,6 +224,32 @@ export const fr: Dictionary = {
|
||||
`Bonjour,\n\nVoici ma sélection de photos :\n\n${list}\n\nLien de partage : ${url}\n\nCordialement,`,
|
||||
},
|
||||
|
||||
proofSession: {
|
||||
greeting: (name: string) => `Sélection pour ${name}`,
|
||||
intro:
|
||||
'Touchez le cœur sur les photos que vous souhaitez. Votre sélection est enregistrée au fur et à mesure — vous pouvez revenir avec ce lien à tout moment.',
|
||||
saving: 'Enregistrement…',
|
||||
saved: 'Sélection enregistrée',
|
||||
saveFailed:
|
||||
'Votre sélection n’a pas pu être enregistrée. Vérifiez votre connexion et réessayez.',
|
||||
review: 'Vérifier & envoyer',
|
||||
modalTitle: (n: number) => `Votre sélection (${n})`,
|
||||
empty: 'Aucune photo sélectionnée pour le moment.',
|
||||
submit: 'Envoyer la sélection',
|
||||
submitting: 'Envoi…',
|
||||
confirmSubmit: (n: number) =>
|
||||
`Envoyer ${plural(n, 'photo', 'photos')} ? La sélection ne pourra plus être modifiée ensuite.`,
|
||||
submitted: 'Merci — votre sélection a été envoyée.',
|
||||
locked: 'Cette sélection a été envoyée et ne peut plus être modifiée.',
|
||||
validUntil: (date: string) => `Ce lien est valable jusqu’au ${date}.`,
|
||||
expiredTitle: 'Ce lien a expiré',
|
||||
expiredText: 'Demandez un nouveau lien à votre photographe.',
|
||||
downloadSelection: 'Télécharger la sélection (.zip)',
|
||||
downloadAll: 'Télécharger toutes les photos (.zip)',
|
||||
downloadsLeft: (n: number) =>
|
||||
`${plural(n, 'téléchargement restant', 'téléchargements restants')}`,
|
||||
},
|
||||
|
||||
legal: {
|
||||
navLabel: 'Mentions légales',
|
||||
title: 'Mentions légales',
|
||||
@@ -236,7 +280,7 @@ export const fr: Dictionary = {
|
||||
tooMany: 'Trop de messages en peu de temps. Réessayez dans une minute.',
|
||||
failed: 'Le message n’a pas pu être envoyé. Réessayez plus tard.',
|
||||
privacy: (days: number) =>
|
||||
`Votre message est conservé sur le serveur de ce site, sert uniquement à vous répondre et est supprimé après ${days} ${days === 1 ? 'jour' : 'jours'}.`,
|
||||
`Votre message est conservé sur le serveur de ce site, sert uniquement à vous répondre et est supprimé après ${days} ${isOne(days) ? 'jour' : 'jours'}.`,
|
||||
},
|
||||
|
||||
privacy: {
|
||||
|
||||
@@ -19,6 +19,8 @@ export const it: Dictionary = {
|
||||
map: 'Mappa',
|
||||
journal: 'Diario',
|
||||
skipToContent: 'Vai al contenuto',
|
||||
mainNavAria: 'Navigazione principale',
|
||||
heroNavAria: 'Sezioni',
|
||||
openMenu: 'Apri menu',
|
||||
closeMenu: 'Chiudi menu',
|
||||
},
|
||||
@@ -45,12 +47,15 @@ export const it: Dictionary = {
|
||||
nextEntryAria: (title: string) => `Articolo successivo: ${title}`,
|
||||
entryNavAria: 'Navigazione tra gli articoli del diario',
|
||||
loadingGallery: 'Caricamento della galleria',
|
||||
gallery: 'Galleria',
|
||||
loadingPhotos: 'Caricamento delle foto',
|
||||
downloadAlbum: 'Scarica album',
|
||||
},
|
||||
|
||||
home: {
|
||||
enter: 'Entra',
|
||||
pauseSlideshow: 'Metti in pausa la presentazione',
|
||||
playSlideshow: 'Avvia la presentazione',
|
||||
},
|
||||
|
||||
error: {
|
||||
@@ -59,8 +64,6 @@ export const it: Dictionary = {
|
||||
errorTitle: 'Qualcosa è andato storto',
|
||||
errorText:
|
||||
'Non è stato possibile caricare questa pagina. Di solito è temporaneo: riprova tra un momento.',
|
||||
siteErrorText:
|
||||
'Non è stato possibile caricare questo sito. Di solito è temporaneo: riprova tra un momento.',
|
||||
tryAgain: 'Riprova',
|
||||
reference: (digest: string) => `Riferimento: ${digest}`,
|
||||
},
|
||||
@@ -71,6 +74,7 @@ export const it: Dictionary = {
|
||||
rateLimited: 'Troppe richieste di download. Attendi un momento e riprova.',
|
||||
immichUnavailable: 'La libreria fotografica non è al momento disponibile. Riprova a breve.',
|
||||
back: 'Torna alla galleria',
|
||||
limitReached: 'È stato raggiunto il limite di download per questo link.',
|
||||
},
|
||||
|
||||
theme: {
|
||||
@@ -82,11 +86,18 @@ export const it: Dictionary = {
|
||||
password: {
|
||||
subtitle: 'Questa galleria è protetta da password.',
|
||||
siteSubtitle: 'Questo sito è protetto da password.',
|
||||
pageSubtitle: 'Questa pagina è protetta da password.',
|
||||
journalSubtitle: 'Questo articolo del diario è protetto da password.',
|
||||
protectedPage: 'Pagina protetta',
|
||||
placeholder: 'Inserisci la password',
|
||||
submit: 'Entra',
|
||||
verifying: 'Verifica in corso…',
|
||||
incorrect: 'Password errata. Riprova.',
|
||||
failed: 'Impossibile verificare la password. Riprova più tardi.',
|
||||
tooManyAttempts: (seconds: number | null) =>
|
||||
seconds
|
||||
? `Troppi tentativi. Riprova tra ${seconds} ${seconds === 1 ? 'secondo' : 'secondi'}.`
|
||||
: 'Troppi tentativi. Riprova più tardi.',
|
||||
},
|
||||
|
||||
about: {
|
||||
@@ -104,6 +115,9 @@ export const it: Dictionary = {
|
||||
loading: 'Caricamento della mappa…',
|
||||
loadFailed: (status: number) => `Impossibile caricare i dati della mappa (${status})`,
|
||||
initFailed: 'Impossibile inizializzare la mappa',
|
||||
zoomIn: 'Ingrandisci',
|
||||
zoomOut: 'Riduci',
|
||||
leafletTitle: 'Una libreria JavaScript per mappe interattive',
|
||||
},
|
||||
|
||||
subpage: {
|
||||
@@ -130,6 +144,7 @@ export const it: Dictionary = {
|
||||
|
||||
lightbox: {
|
||||
viewer: 'Visualizzatore di immagini',
|
||||
position: (n: number, total: number) => `Foto ${n} di ${total}`,
|
||||
openPhoto: (n: number) => `Apri la foto ${n}`,
|
||||
close: 'Chiudi',
|
||||
closeTitle: 'Chiudi (Esc)',
|
||||
@@ -181,6 +196,7 @@ export const it: Dictionary = {
|
||||
saved: 'Salvato',
|
||||
favorite: 'Preferito',
|
||||
showAll: 'Mostra tutto',
|
||||
filterEmpty: 'Nessuna foto selezionata.',
|
||||
selected: (n: number) => `❤️ ${n} ${n === 1 ? 'selezionata' : 'selezionate'}`,
|
||||
shareExport: 'Condividi ed esporta',
|
||||
modalTitle: (n: number) => `❤️ Selezione (${n})`,
|
||||
@@ -205,6 +221,30 @@ export const it: Dictionary = {
|
||||
`Ciao,\n\necco la mia selezione di foto:\n\n${list}\n\nLink di condivisione: ${url}\n\nCordiali saluti,`,
|
||||
},
|
||||
|
||||
proofSession: {
|
||||
greeting: (name: string) => `Selezione per ${name}`,
|
||||
intro:
|
||||
'Tocca il cuore sulle foto che desideri. La tua selezione viene salvata man mano: puoi tornare con questo link in qualsiasi momento.',
|
||||
saving: 'Salvataggio…',
|
||||
saved: 'Selezione salvata',
|
||||
saveFailed: 'Non è stato possibile salvare la selezione. Controlla la connessione e riprova.',
|
||||
review: 'Controlla e invia',
|
||||
modalTitle: (n: number) => `La tua selezione (${n})`,
|
||||
empty: 'Nessuna foto selezionata.',
|
||||
submit: 'Invia selezione',
|
||||
submitting: 'Invio in corso…',
|
||||
confirmSubmit: (n: number) =>
|
||||
`Inviare ${n} foto? Dopo non sarà più possibile modificare la selezione.`,
|
||||
submitted: 'Grazie, la tua selezione è stata inviata.',
|
||||
locked: 'Questa selezione è stata inviata e non può più essere modificata.',
|
||||
validUntil: (date: string) => `Questo link è valido fino al ${date}.`,
|
||||
expiredTitle: 'Questo link è scaduto',
|
||||
expiredText: 'Chiedi un nuovo link al tuo fotografo.',
|
||||
downloadSelection: 'Scarica selezione (.zip)',
|
||||
downloadAll: 'Scarica tutte le foto (.zip)',
|
||||
downloadsLeft: (n: number) => `${plural(n, 'download rimasto', 'download rimasti')}`,
|
||||
},
|
||||
|
||||
legal: {
|
||||
navLabel: 'Note legali',
|
||||
title: 'Note legali',
|
||||
|
||||
@@ -19,6 +19,8 @@ export const nl: Dictionary = {
|
||||
map: 'Kaart',
|
||||
journal: 'Journal',
|
||||
skipToContent: 'Naar de inhoud',
|
||||
mainNavAria: 'Hoofdnavigatie',
|
||||
heroNavAria: 'Onderdelen',
|
||||
openMenu: 'Menu openen',
|
||||
closeMenu: 'Menu sluiten',
|
||||
},
|
||||
@@ -44,12 +46,15 @@ export const nl: Dictionary = {
|
||||
nextEntryAria: (title: string) => `Volgend verhaal: ${title}`,
|
||||
entryNavAria: 'Navigatie tussen journalverhalen',
|
||||
loadingGallery: 'Galerij laden',
|
||||
gallery: 'Galerie',
|
||||
loadingPhotos: 'Foto’s laden',
|
||||
downloadAlbum: 'Album downloaden',
|
||||
},
|
||||
|
||||
home: {
|
||||
enter: 'Binnenkomen',
|
||||
pauseSlideshow: 'Diavoorstelling pauzeren',
|
||||
playSlideshow: 'Diavoorstelling afspelen',
|
||||
},
|
||||
|
||||
error: {
|
||||
@@ -58,8 +63,6 @@ export const nl: Dictionary = {
|
||||
errorTitle: 'Er is iets misgegaan',
|
||||
errorText:
|
||||
'Deze pagina kon niet worden geladen. Meestal is dat tijdelijk — probeer het zo nog eens.',
|
||||
siteErrorText:
|
||||
'Deze site kon niet worden geladen. Meestal is dat tijdelijk — probeer het zo nog eens.',
|
||||
tryAgain: 'Opnieuw proberen',
|
||||
reference: (digest: string) => `Referentie: ${digest}`,
|
||||
},
|
||||
@@ -71,6 +74,7 @@ export const nl: Dictionary = {
|
||||
immichUnavailable:
|
||||
'De fotobibliotheek is op dit moment niet bereikbaar. Probeer het zo opnieuw.',
|
||||
back: 'Terug naar de galerij',
|
||||
limitReached: 'Het downloadlimiet voor deze link is bereikt.',
|
||||
},
|
||||
|
||||
theme: {
|
||||
@@ -82,11 +86,18 @@ export const nl: Dictionary = {
|
||||
password: {
|
||||
subtitle: 'Deze galerij is met een wachtwoord beveiligd.',
|
||||
siteSubtitle: 'Deze site is met een wachtwoord beveiligd.',
|
||||
pageSubtitle: 'Deze pagina is met een wachtwoord beveiligd.',
|
||||
journalSubtitle: 'Dit journalverhaal is met een wachtwoord beveiligd.',
|
||||
protectedPage: 'Beveiligde pagina',
|
||||
placeholder: 'Voer het wachtwoord in',
|
||||
submit: 'Binnenkomen',
|
||||
verifying: 'Controleren…',
|
||||
incorrect: 'Onjuist wachtwoord. Probeer het opnieuw.',
|
||||
failed: 'Het wachtwoord kon niet worden gecontroleerd. Probeer het later opnieuw.',
|
||||
tooManyAttempts: (seconds: number | null) =>
|
||||
seconds
|
||||
? `Te veel pogingen. Probeer het over ${seconds} ${seconds === 1 ? 'seconde' : 'seconden'} opnieuw.`
|
||||
: 'Te veel pogingen. Probeer het later opnieuw.',
|
||||
},
|
||||
|
||||
about: {
|
||||
@@ -104,6 +115,9 @@ export const nl: Dictionary = {
|
||||
loading: 'Kaart laden…',
|
||||
loadFailed: (status: number) => `Kaartgegevens konden niet worden geladen (${status})`,
|
||||
initFailed: 'De kaart kon niet worden gestart',
|
||||
zoomIn: 'Inzoomen',
|
||||
zoomOut: 'Uitzoomen',
|
||||
leafletTitle: 'Een JavaScript-bibliotheek voor interactieve kaarten',
|
||||
},
|
||||
|
||||
subpage: {
|
||||
@@ -130,6 +144,7 @@ export const nl: Dictionary = {
|
||||
|
||||
lightbox: {
|
||||
viewer: 'Fotoviewer',
|
||||
position: (n: number, total: number) => `Foto ${n} van ${total}`,
|
||||
openPhoto: (n: number) => `Foto ${n} bekijken`,
|
||||
close: 'Sluiten',
|
||||
closeTitle: 'Sluiten (Esc)',
|
||||
@@ -182,6 +197,7 @@ export const nl: Dictionary = {
|
||||
saved: 'Opgeslagen',
|
||||
favorite: 'Favoriet',
|
||||
showAll: 'Alles tonen',
|
||||
filterEmpty: "Geen foto's geselecteerd.",
|
||||
selected: (n: number) => `❤️ ${n} geselecteerd`,
|
||||
shareExport: 'Delen & exporteren',
|
||||
modalTitle: (n: number) => `❤️ Selectie (${n})`,
|
||||
@@ -206,6 +222,31 @@ export const nl: Dictionary = {
|
||||
`Hallo,\n\nHier is mijn fotoselectie:\n\n${list}\n\nDeellink: ${url}\n\nMet vriendelijke groet,`,
|
||||
},
|
||||
|
||||
proofSession: {
|
||||
greeting: (name: string) => `Selectie voor ${name}`,
|
||||
intro:
|
||||
'Tik op het hartje bij de foto’s die je wilt. Je selectie wordt meteen opgeslagen — je kunt met deze link altijd terugkomen.',
|
||||
saving: 'Opslaan…',
|
||||
saved: 'Selectie opgeslagen',
|
||||
saveFailed:
|
||||
'Je selectie kon niet worden opgeslagen. Controleer je verbinding en probeer het opnieuw.',
|
||||
review: 'Bekijken & versturen',
|
||||
modalTitle: (n: number) => `Jouw selectie (${n})`,
|
||||
empty: 'Nog geen foto’s geselecteerd.',
|
||||
submit: 'Selectie versturen',
|
||||
submitting: 'Versturen…',
|
||||
confirmSubmit: (n: number) =>
|
||||
`${plural(n, 'foto', 'foto’s')} versturen? Daarna kun je de selectie niet meer wijzigen.`,
|
||||
submitted: 'Bedankt — je selectie is verstuurd.',
|
||||
locked: 'Deze selectie is verstuurd en kan niet meer worden gewijzigd.',
|
||||
validUntil: (date: string) => `Deze link is geldig tot ${date}.`,
|
||||
expiredTitle: 'Deze link is verlopen',
|
||||
expiredText: 'Vraag je fotograaf om een nieuwe link.',
|
||||
downloadSelection: 'Selectie downloaden (.zip)',
|
||||
downloadAll: 'Alle foto’s downloaden (.zip)',
|
||||
downloadsLeft: (n: number) => `Nog ${plural(n, 'download', 'downloads')}`,
|
||||
},
|
||||
|
||||
legal: {
|
||||
navLabel: 'Colofon',
|
||||
title: 'Colofon',
|
||||
|
||||
Reference in New Issue
Block a user