mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 00:34:13 +01:00
Binary file not shown.
@@ -78,7 +78,7 @@ msgstr "Aktionen"
|
||||
msgid "Add Album"
|
||||
msgstr "Neues Album erstellen"
|
||||
|
||||
#: src/pages/settings/general.vue:269
|
||||
#: src/pages/settings/general.vue:377
|
||||
msgid "Add files to your library via Web Upload."
|
||||
msgstr "Dateien über den Browser hochladen und indizieren."
|
||||
|
||||
@@ -230,7 +230,7 @@ msgstr "Höhe (m)"
|
||||
msgid "An error occurred - are you offline?"
|
||||
msgstr "Server nicht erreichbar - offline?"
|
||||
|
||||
#: src/pages/settings/general.vue:590
|
||||
#: src/pages/settings/general.vue:698
|
||||
msgid "Animation"
|
||||
msgstr "Animation"
|
||||
|
||||
@@ -254,7 +254,7 @@ msgid "Approve"
|
||||
msgstr "Übernehmen"
|
||||
|
||||
#: src/component/navigation.vue:114 src/component/photo/cards.vue:20
|
||||
#: src/component/photo/clipboard.vue:211 src/pages/settings/general.vue:334
|
||||
#: src/component/photo/clipboard.vue:211 src/pages/settings/general.vue:442
|
||||
#: src/routes.js:185
|
||||
msgid "Archive"
|
||||
msgstr "Archiv"
|
||||
@@ -295,13 +295,13 @@ msgstr "Seitenverhältnis"
|
||||
msgid "At least 6 characters."
|
||||
msgstr "Mindestens 6 Zeichen."
|
||||
|
||||
#: src/pages/settings/general.vue:121
|
||||
#: src/pages/settings/general.vue:123
|
||||
msgid ""
|
||||
"Automatically create JPEGs for other file types so that they can be "
|
||||
"displayed in a browser."
|
||||
msgstr ""
|
||||
"RAW-Bilder und Videos müssen zu JPEGs konvertiert werden, damit sie in der "
|
||||
"Suche angezeigt werden können."
|
||||
"Videos und andere Bild-Formate nach JPEG konvertieren, damit sie indexiert "
|
||||
"und angezeigt werden können."
|
||||
|
||||
#: src/pages/settings.vue:8
|
||||
msgid "Backup"
|
||||
@@ -319,11 +319,11 @@ msgstr "Blau"
|
||||
msgid "Brown"
|
||||
msgstr "Braun"
|
||||
|
||||
#: src/pages/settings/general.vue:423
|
||||
#: src/pages/settings/general.vue:531
|
||||
msgid "Browse and edit image classification labels."
|
||||
msgstr "Automatische Bild-Kategorisierung sehen und bearbeiten."
|
||||
|
||||
#: src/pages/settings/general.vue:379
|
||||
#: src/pages/settings/general.vue:487
|
||||
msgid "Browse indexed files and folders in Library."
|
||||
msgstr "Durchsuche indizierte Dateien und Verzeichnisse."
|
||||
|
||||
@@ -384,7 +384,7 @@ msgstr "Kategorie"
|
||||
msgid "Change"
|
||||
msgstr "Ändern"
|
||||
|
||||
#: src/pages/settings/general.vue:357
|
||||
#: src/pages/settings/general.vue:465
|
||||
msgid "Change photo titles, locations and other metadata."
|
||||
msgstr "Titel, Datum, Ort und andere Metadaten können geändert werden."
|
||||
|
||||
@@ -453,7 +453,7 @@ msgstr "Enthält einen Eintrag."
|
||||
msgid "Contributors"
|
||||
msgstr "Contributors"
|
||||
|
||||
#: src/pages/settings/general.vue:120
|
||||
#: src/pages/settings/general.vue:122
|
||||
msgid "Convert to JPEG"
|
||||
msgstr "Automatisch konvertieren"
|
||||
|
||||
@@ -587,7 +587,7 @@ msgstr "Fertig."
|
||||
#: src/component/album/clipboard.vue:111 src/component/album/toolbar.vue:106
|
||||
#: src/component/file/clipboard.vue:64 src/component/photo/clipboard.vue:165
|
||||
#: src/component/photo/viewer.vue:72 src/dialog/photo/files.vue:33
|
||||
#: src/pages/settings/general.vue:290 src/share/album/clipboard.vue:60
|
||||
#: src/pages/settings/general.vue:398 src/share/album/clipboard.vue:60
|
||||
#: src/share/photo/clipboard.vue:62 src/share/photos.vue:75
|
||||
msgid "Download"
|
||||
msgstr "Download"
|
||||
@@ -596,7 +596,7 @@ msgstr "Download"
|
||||
msgid "Download remote files"
|
||||
msgstr "Dateien herunterladen"
|
||||
|
||||
#: src/pages/settings/general.vue:291
|
||||
#: src/pages/settings/general.vue:399
|
||||
msgid "Download single files and zip archives."
|
||||
msgstr ""
|
||||
"Einzelne Fotos, Videos sowie Zip-Archive können heruntergeladen werden."
|
||||
@@ -623,7 +623,7 @@ msgstr "E-Mail"
|
||||
|
||||
#: src/component/album/clipboard.vue:89 src/component/album/toolbar.vue:69
|
||||
#: src/component/photo/clipboard.vue:119 src/component/photo/viewer.vue:89
|
||||
#: src/pages/settings/general.vue:356
|
||||
#: src/pages/settings/general.vue:464
|
||||
msgid "Edit"
|
||||
msgstr "Bearbeiten"
|
||||
|
||||
@@ -663,7 +663,7 @@ msgstr "Fehler"
|
||||
msgid "Every two days"
|
||||
msgstr "Jeden zweiten Tag"
|
||||
|
||||
#: src/pages/settings/general.vue:77
|
||||
#: src/pages/settings/general.vue:79
|
||||
msgid ""
|
||||
"Exclude content marked as private from search results, shared albums, labels "
|
||||
"and places."
|
||||
@@ -731,17 +731,21 @@ msgstr "Datei"
|
||||
msgid "File Browser"
|
||||
msgstr "Datei Browser"
|
||||
|
||||
#: src/pages/settings/general.vue:248
|
||||
msgid "File Name Prefix"
|
||||
msgstr "Fortlaufender Name"
|
||||
|
||||
#: src/dialog/photo/edit.vue:31
|
||||
msgid "Files"
|
||||
msgstr "Dateien"
|
||||
|
||||
#: src/pages/settings/general.vue:143
|
||||
#: src/pages/settings/general.vue:249
|
||||
msgid ""
|
||||
"Files with sequential names like 'IMG_1234 (2)' or 'IMG_1234 copy 2' belong "
|
||||
"to the same photo."
|
||||
"Files with sequential names like 'IMG_1234 (2)' and 'IMG_1234 (3)' belong to "
|
||||
"the same picture."
|
||||
msgstr ""
|
||||
"Dateien mit Namen wie ‘IMG_1234 (2)’ oder ‘IMG_1234 copy 2’ werden als "
|
||||
"Stapel zusammengefasst."
|
||||
"Dateien mit fortlaufenden Namen wie ‘IMG_1234 (2)’ und ‘IMG_1234 (3)’ "
|
||||
"gehören zum gleichen Bild."
|
||||
|
||||
#: src/dialog/photo/details.vue:476
|
||||
msgid "Focal Length"
|
||||
@@ -814,11 +818,11 @@ msgstr "Unsichtbar"
|
||||
msgid "Hidden Files"
|
||||
msgstr "Unsichtbare Dateien"
|
||||
|
||||
#: src/pages/settings/general.vue:335
|
||||
#: src/pages/settings/general.vue:443
|
||||
msgid "Hide photos that have been moved to archive."
|
||||
msgstr "Archivierte Inhalte werden nicht in den Suchergebnissen angezeigt."
|
||||
|
||||
#: src/pages/settings/general.vue:76
|
||||
#: src/pages/settings/general.vue:78
|
||||
msgid "Hide Private"
|
||||
msgstr "Privates ausblenden"
|
||||
|
||||
@@ -852,7 +856,7 @@ msgstr "Bild"
|
||||
msgid "Image"
|
||||
msgstr "Bild"
|
||||
|
||||
#: src/pages/library/import.vue:43 src/pages/settings/general.vue:466
|
||||
#: src/pages/library/import.vue:43 src/pages/settings/general.vue:574
|
||||
msgid "Import"
|
||||
msgstr "Import"
|
||||
|
||||
@@ -868,7 +872,7 @@ msgstr ""
|
||||
"Import kopiert neue Dateien und sortiert sie nach Datum, um Duplikate zu "
|
||||
"vermeiden."
|
||||
|
||||
#: src/pages/settings/general.vue:467
|
||||
#: src/pages/settings/general.vue:575
|
||||
msgid "Imported files will be sorted by date and given a unique name."
|
||||
msgstr ""
|
||||
"Import kopiert neue Dateien und sortiert sie nach Datum, um Duplikate zu "
|
||||
@@ -935,7 +939,7 @@ msgid "Label Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: src/component/navigation.vue:263 src/dialog/photo/edit.vue:27
|
||||
#: src/pages/settings/general.vue:422 src/routes.js:236
|
||||
#: src/pages/settings/general.vue:530 src/routes.js:236
|
||||
msgid "Labels"
|
||||
msgstr "Kategorien"
|
||||
|
||||
@@ -943,7 +947,7 @@ msgstr "Kategorien"
|
||||
msgid "Labels deleted"
|
||||
msgstr "Kategorien gelöscht"
|
||||
|
||||
#: src/pages/settings/general.vue:220
|
||||
#: src/pages/settings/general.vue:328
|
||||
msgid "Language"
|
||||
msgstr "Sprache"
|
||||
|
||||
@@ -963,14 +967,14 @@ msgstr "Lavendel"
|
||||
msgid "Lens"
|
||||
msgstr "Objektiv"
|
||||
|
||||
#: src/pages/settings/general.vue:401
|
||||
#: src/pages/settings/general.vue:509
|
||||
msgid "Let PhotoPrism create albums from past events."
|
||||
msgstr ""
|
||||
"PhotoPrism erstellt automatisch Alben mit besonderen Momenten, Reisen und "
|
||||
"Orten."
|
||||
|
||||
#: src/component/navigation.vue:276 src/component/navigation.vue:285
|
||||
#: src/pages/settings/general.vue:6 src/pages/settings/general.vue:444
|
||||
#: src/pages/settings/general.vue:6 src/pages/settings/general.vue:552
|
||||
#: src/routes.js:255 src/routes.js:262 src/routes.js:269
|
||||
msgid "Library"
|
||||
msgstr "Dateien"
|
||||
@@ -1033,7 +1037,7 @@ msgstr "Anmelden"
|
||||
msgid "Logout"
|
||||
msgstr "Abmelden"
|
||||
|
||||
#: src/pages/library.vue:17 src/pages/settings/general.vue:488
|
||||
#: src/pages/library.vue:17 src/pages/settings/general.vue:596
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
|
||||
@@ -1069,7 +1073,7 @@ msgstr "Nachricht versendet"
|
||||
msgid "Missing"
|
||||
msgstr "Fehlend"
|
||||
|
||||
#: src/component/navigation.vue:218 src/pages/settings/general.vue:400
|
||||
#: src/component/navigation.vue:218 src/pages/settings/general.vue:508
|
||||
#: src/routes.js:98 src/routes.js:105
|
||||
msgid "Moments"
|
||||
msgstr "Erlebnisse"
|
||||
@@ -1196,7 +1200,7 @@ msgstr ""
|
||||
#: src/component/photo/list.vue:15 src/component/photo/list.vue:1
|
||||
#: src/component/photo/list.vue:19 src/component/photo/mosaic.vue:15
|
||||
#: src/component/photo/mosaic.vue:1 src/dialog/upload.vue:50
|
||||
#: src/pages/settings/general.vue:99
|
||||
#: src/pages/settings/general.vue:101
|
||||
msgid ""
|
||||
"Non-photographic and low-quality images require a review before they appear "
|
||||
"in search results."
|
||||
@@ -1305,7 +1309,7 @@ msgid "Original Name"
|
||||
msgstr "Originalname"
|
||||
|
||||
#: src/component/navigation.vue:293 src/pages/library/files.vue:6
|
||||
#: src/pages/settings/general.vue:378
|
||||
#: src/pages/settings/general.vue:486
|
||||
msgid "Originals"
|
||||
msgstr "Originale"
|
||||
|
||||
@@ -1374,8 +1378,12 @@ msgstr "Pink"
|
||||
msgid "Place"
|
||||
msgstr "Ort"
|
||||
|
||||
#: src/pages/settings/general.vue:204
|
||||
msgid "Place & Time"
|
||||
msgstr "Gleicher Ort & Zeit"
|
||||
|
||||
#: src/component/navigation.vue:231 src/component/navigation.vue:240
|
||||
#: src/pages/settings/general.vue:124 src/pages/settings/general.vue:510
|
||||
#: src/pages/settings/general.vue:152 src/pages/settings/general.vue:618
|
||||
#: src/routes.js:192 src/routes.js:198 src/routes.js:204 src/routes.js:211
|
||||
msgid "Places"
|
||||
msgstr "Karten"
|
||||
@@ -1442,7 +1450,7 @@ msgstr "Projektion"
|
||||
msgid "Purple"
|
||||
msgstr "Purpur"
|
||||
|
||||
#: src/pages/settings/general.vue:98
|
||||
#: src/pages/settings/general.vue:100
|
||||
msgid "Quality Filter"
|
||||
msgstr "Qualitätsfilter"
|
||||
|
||||
@@ -1562,7 +1570,7 @@ msgstr "Scans"
|
||||
msgid "Search"
|
||||
msgstr "Suche"
|
||||
|
||||
#: src/pages/settings/general.vue:511
|
||||
#: src/pages/settings/general.vue:619
|
||||
msgid "Search and display photos on a map."
|
||||
msgstr "Fotos und Videos auf verschiedenen Weltkarten anzeigen und filtern."
|
||||
|
||||
@@ -1629,7 +1637,7 @@ msgid "Setup"
|
||||
msgstr "Einrichtung"
|
||||
|
||||
#: src/component/album/clipboard.vue:68 src/component/album/toolbar.vue:87
|
||||
#: src/component/photo/clipboard.vue:73 src/pages/settings/general.vue:312
|
||||
#: src/component/photo/clipboard.vue:73 src/pages/settings/general.vue:420
|
||||
msgid "Share"
|
||||
msgstr "Teilen"
|
||||
|
||||
@@ -1645,7 +1653,7 @@ msgstr "Mit dir geteilt."
|
||||
msgid "Show less"
|
||||
msgstr "Weniger zeigen"
|
||||
|
||||
#: src/pages/settings/general.vue:445
|
||||
#: src/pages/settings/general.vue:553
|
||||
msgid "Show Library in navigation menu."
|
||||
msgstr "Datei-Verwaltung in der Navigation anzeigen."
|
||||
|
||||
@@ -1653,7 +1661,7 @@ msgstr "Datei-Verwaltung in der Navigation anzeigen."
|
||||
msgid "Show more"
|
||||
msgstr "Mehr zeigen"
|
||||
|
||||
#: src/pages/settings/general.vue:489
|
||||
#: src/pages/settings/general.vue:597
|
||||
msgid "Show server logs in Library."
|
||||
msgstr "Server-Ereignisprotokoll anzeigen, um Fehler zu finden."
|
||||
|
||||
@@ -1699,14 +1707,32 @@ msgstr "Quelle"
|
||||
msgid "Spanish"
|
||||
msgstr "Spanisch"
|
||||
|
||||
#: src/pages/settings/general.vue:142
|
||||
msgid "Stack Sequences"
|
||||
msgstr "Sequenzen gruppieren"
|
||||
#: src/pages/settings/general.vue:227
|
||||
msgid "Stack files sharing the same unique image or instance identifier."
|
||||
msgstr "Bilder mit identischer ID als Stapel indexieren und anzeigen."
|
||||
|
||||
#: src/component/navigation.vue:89
|
||||
#: src/pages/settings/general.vue:38
|
||||
msgid "Stack files with matching..."
|
||||
msgstr "Als Stapel zusammenfassen..."
|
||||
|
||||
#: src/pages/settings/general.vue:205
|
||||
msgid ""
|
||||
"Stack pictures taken at the exact same time and location based on their "
|
||||
"metadata."
|
||||
msgstr "Aufnahmen mit übereinstimmenden Metadaten gruppieren."
|
||||
|
||||
#: src/component/navigation.vue:89 src/pages/settings/general.vue:144
|
||||
msgid "Stacks"
|
||||
msgstr "Bildstapel"
|
||||
|
||||
#: src/pages/settings/general.vue:145
|
||||
msgid ""
|
||||
"Stacks group files with a similar frame of reference, but differences of "
|
||||
"quality, format, size or color."
|
||||
msgstr ""
|
||||
"Bildstapel enthalten zusammengehörige Aufnahmen, die jedoch Unterschiede in "
|
||||
"Qualität, Format, Größe oder Farben aufweisen können."
|
||||
|
||||
#: src/pages/library/index.vue:30
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
@@ -1731,7 +1757,7 @@ msgstr "Ablageverzeichnis"
|
||||
msgid "Streets"
|
||||
msgstr "Straßen"
|
||||
|
||||
#: src/pages/settings/general.vue:568
|
||||
#: src/pages/settings/general.vue:676
|
||||
msgid "Style"
|
||||
msgstr "Style"
|
||||
|
||||
@@ -1777,7 +1803,7 @@ msgstr ""
|
||||
"Ihr Format wird möglicherweise nicht unterstützt, es handelt sich um "
|
||||
"Duplikate oder sie wurden noch nicht nach JPEG konvertiert."
|
||||
|
||||
#: src/pages/settings/general.vue:198
|
||||
#: src/pages/settings/general.vue:306
|
||||
msgid "Theme"
|
||||
msgstr "Theme"
|
||||
|
||||
@@ -1844,6 +1870,10 @@ msgstr "Versuche es mit anderen Filtern oder Suchbegriffen."
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: src/pages/settings/general.vue:226
|
||||
msgid "Unique ID"
|
||||
msgstr "Eindeutige Bild-ID"
|
||||
|
||||
#: src/dialog/photo/details.vue:16 src/dialog/photo/info.vue:21
|
||||
#: src/model/album.js:122 src/model/photo.js:401 src/model/photo.js:415
|
||||
#: src/model/photo.js:438 src/model/photo.js:452 src/model/photo.js:529
|
||||
@@ -1869,7 +1899,7 @@ msgstr "Geändert"
|
||||
#: src/component/album/toolbar.vue:175 src/component/navigation.vue:130
|
||||
#: src/component/photo/toolbar.vue:123 src/dialog/share/upload.vue:35
|
||||
#: src/dialog/upload.vue:8 src/dialog/upload.vue:54 src/pages/albums.vue:134
|
||||
#: src/pages/library/import.vue:38 src/pages/settings/general.vue:268
|
||||
#: src/pages/library/import.vue:38 src/pages/settings/general.vue:376
|
||||
#: src/pages/settings/sync.vue:24
|
||||
msgid "Upload"
|
||||
msgstr "Upload"
|
||||
@@ -1890,7 +1920,7 @@ msgstr "Upload fehlgeschlagen"
|
||||
msgid "Upload local files"
|
||||
msgstr "Dateien hochladen"
|
||||
|
||||
#: src/pages/settings/general.vue:313
|
||||
#: src/pages/settings/general.vue:421
|
||||
msgid "Upload to WebDAV and share links with friends."
|
||||
msgstr "Teile Fotos, Videos und Alben mit Freunden."
|
||||
|
||||
@@ -1914,7 +1944,7 @@ msgstr "URL"
|
||||
msgid "User"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: src/pages/settings/general.vue:38
|
||||
#: src/pages/settings/general.vue:66
|
||||
msgid "User Interface"
|
||||
msgstr "Benutzeroberfläche"
|
||||
|
||||
@@ -2003,6 +2033,9 @@ msgstr "Ihre Nachricht wurde gesendet"
|
||||
msgid "Zoom in/out"
|
||||
msgstr "Zoom in/out"
|
||||
|
||||
#~ msgid "Stack Sequences"
|
||||
#~ msgstr "Sequenzen gruppieren"
|
||||
|
||||
#~ msgid "Brazilian Portuguese"
|
||||
#~ msgstr "Brasilianisches Portugiesisch"
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -78,7 +78,7 @@ msgstr ""
|
||||
msgid "Add Album"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:269
|
||||
#: src/pages/settings/general.vue:377
|
||||
msgid "Add files to your library via Web Upload."
|
||||
msgstr ""
|
||||
|
||||
@@ -234,7 +234,7 @@ msgstr ""
|
||||
msgid "An error occurred - are you offline?"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:590
|
||||
#: src/pages/settings/general.vue:698
|
||||
msgid "Animation"
|
||||
msgstr ""
|
||||
|
||||
@@ -259,7 +259,7 @@ msgstr ""
|
||||
#: src/component/navigation.vue:114
|
||||
#: src/component/photo/cards.vue:20
|
||||
#: src/component/photo/clipboard.vue:211
|
||||
#: src/pages/settings/general.vue:334
|
||||
#: src/pages/settings/general.vue:442
|
||||
#: src/routes.js:185
|
||||
msgid "Archive"
|
||||
msgstr ""
|
||||
@@ -300,7 +300,7 @@ msgstr ""
|
||||
msgid "At least 6 characters."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:121
|
||||
#: src/pages/settings/general.vue:123
|
||||
msgid "Automatically create JPEGs for other file types so that they can be displayed in a browser."
|
||||
msgstr ""
|
||||
|
||||
@@ -320,11 +320,11 @@ msgstr ""
|
||||
msgid "Brown"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:423
|
||||
#: src/pages/settings/general.vue:531
|
||||
msgid "Browse and edit image classification labels."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:379
|
||||
#: src/pages/settings/general.vue:487
|
||||
msgid "Browse indexed files and folders in Library."
|
||||
msgstr ""
|
||||
|
||||
@@ -404,7 +404,7 @@ msgstr ""
|
||||
msgid "Change"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:357
|
||||
#: src/pages/settings/general.vue:465
|
||||
msgid "Change photo titles, locations and other metadata."
|
||||
msgstr ""
|
||||
|
||||
@@ -476,7 +476,7 @@ msgstr ""
|
||||
msgid "Contributors"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:120
|
||||
#: src/pages/settings/general.vue:122
|
||||
msgid "Convert to JPEG"
|
||||
msgstr ""
|
||||
|
||||
@@ -636,7 +636,7 @@ msgstr ""
|
||||
#: src/component/photo/clipboard.vue:165
|
||||
#: src/component/photo/viewer.vue:72
|
||||
#: src/dialog/photo/files.vue:33
|
||||
#: src/pages/settings/general.vue:290
|
||||
#: src/pages/settings/general.vue:398
|
||||
#: src/share/album/clipboard.vue:60
|
||||
#: src/share/photo/clipboard.vue:62
|
||||
#: src/share/photos.vue:75
|
||||
@@ -647,7 +647,7 @@ msgstr ""
|
||||
msgid "Download remote files"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:291
|
||||
#: src/pages/settings/general.vue:399
|
||||
msgid "Download single files and zip archives."
|
||||
msgstr ""
|
||||
|
||||
@@ -679,7 +679,7 @@ msgstr ""
|
||||
#: src/component/album/toolbar.vue:69
|
||||
#: src/component/photo/clipboard.vue:119
|
||||
#: src/component/photo/viewer.vue:89
|
||||
#: src/pages/settings/general.vue:356
|
||||
#: src/pages/settings/general.vue:464
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
@@ -720,7 +720,7 @@ msgstr ""
|
||||
msgid "Every two days"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:77
|
||||
#: src/pages/settings/general.vue:79
|
||||
msgid "Exclude content marked as private from search results, shared albums, labels and places."
|
||||
msgstr ""
|
||||
|
||||
@@ -788,12 +788,16 @@ msgstr ""
|
||||
msgid "File Browser"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:248
|
||||
msgid "File Name Prefix"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/edit.vue:31
|
||||
msgid "Files"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:143
|
||||
msgid "Files with sequential names like 'IMG_1234 (2)' or 'IMG_1234 copy 2' belong to the same photo."
|
||||
#: src/pages/settings/general.vue:249
|
||||
msgid "Files with sequential names like 'IMG_1234 (2)' and 'IMG_1234 (3)' belong to the same picture."
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/details.vue:476
|
||||
@@ -873,11 +877,11 @@ msgstr ""
|
||||
msgid "Hidden Files"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:335
|
||||
#: src/pages/settings/general.vue:443
|
||||
msgid "Hide photos that have been moved to archive."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:76
|
||||
#: src/pages/settings/general.vue:78
|
||||
msgid "Hide Private"
|
||||
msgstr ""
|
||||
|
||||
@@ -909,7 +913,7 @@ msgid "Image"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/library/import.vue:43
|
||||
#: src/pages/settings/general.vue:466
|
||||
#: src/pages/settings/general.vue:574
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
@@ -921,7 +925,7 @@ msgstr ""
|
||||
msgid "Imported files will be sorted by date and given a unique name to avoid duplicates."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:467
|
||||
#: src/pages/settings/general.vue:575
|
||||
msgid "Imported files will be sorted by date and given a unique name."
|
||||
msgstr ""
|
||||
|
||||
@@ -990,7 +994,7 @@ msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:263
|
||||
#: src/dialog/photo/edit.vue:27
|
||||
#: src/pages/settings/general.vue:422
|
||||
#: src/pages/settings/general.vue:530
|
||||
#: src/routes.js:236
|
||||
msgid "Labels"
|
||||
msgstr ""
|
||||
@@ -999,7 +1003,7 @@ msgstr ""
|
||||
msgid "Labels deleted"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:220
|
||||
#: src/pages/settings/general.vue:328
|
||||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
@@ -1020,14 +1024,14 @@ msgstr ""
|
||||
msgid "Lens"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:401
|
||||
#: src/pages/settings/general.vue:509
|
||||
msgid "Let PhotoPrism create albums from past events."
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:276
|
||||
#: src/component/navigation.vue:285
|
||||
#: src/pages/settings/general.vue:6
|
||||
#: src/pages/settings/general.vue:444
|
||||
#: src/pages/settings/general.vue:552
|
||||
#: src/routes.js:255
|
||||
#: src/routes.js:262
|
||||
#: src/routes.js:269
|
||||
@@ -1093,7 +1097,7 @@ msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/library.vue:17
|
||||
#: src/pages/settings/general.vue:488
|
||||
#: src/pages/settings/general.vue:596
|
||||
msgid "Logs"
|
||||
msgstr ""
|
||||
|
||||
@@ -1131,7 +1135,7 @@ msgid "Missing"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:218
|
||||
#: src/pages/settings/general.vue:400
|
||||
#: src/pages/settings/general.vue:508
|
||||
#: src/routes.js:98
|
||||
#: src/routes.js:105
|
||||
msgid "Moments"
|
||||
@@ -1280,7 +1284,7 @@ msgstr ""
|
||||
#: src/component/photo/mosaic.vue:15
|
||||
#: src/component/photo/mosaic.vue:1
|
||||
#: src/dialog/upload.vue:50
|
||||
#: src/pages/settings/general.vue:99
|
||||
#: src/pages/settings/general.vue:101
|
||||
msgid "Non-photographic and low-quality images require a review before they appear in search results."
|
||||
msgstr ""
|
||||
|
||||
@@ -1380,7 +1384,7 @@ msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:293
|
||||
#: src/pages/library/files.vue:6
|
||||
#: src/pages/settings/general.vue:378
|
||||
#: src/pages/settings/general.vue:486
|
||||
msgid "Originals"
|
||||
msgstr ""
|
||||
|
||||
@@ -1448,10 +1452,14 @@ msgstr ""
|
||||
msgid "Place"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:204
|
||||
msgid "Place & Time"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:231
|
||||
#: src/component/navigation.vue:240
|
||||
#: src/pages/settings/general.vue:124
|
||||
#: src/pages/settings/general.vue:510
|
||||
#: src/pages/settings/general.vue:152
|
||||
#: src/pages/settings/general.vue:618
|
||||
#: src/routes.js:192
|
||||
#: src/routes.js:198
|
||||
#: src/routes.js:204
|
||||
@@ -1524,7 +1532,7 @@ msgstr ""
|
||||
msgid "Purple"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:98
|
||||
#: src/pages/settings/general.vue:100
|
||||
msgid "Quality Filter"
|
||||
msgstr ""
|
||||
|
||||
@@ -1653,7 +1661,7 @@ msgstr ""
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:511
|
||||
#: src/pages/settings/general.vue:619
|
||||
msgid "Search and display photos on a map."
|
||||
msgstr ""
|
||||
|
||||
@@ -1732,7 +1740,7 @@ msgstr ""
|
||||
#: src/component/album/clipboard.vue:68
|
||||
#: src/component/album/toolbar.vue:87
|
||||
#: src/component/photo/clipboard.vue:73
|
||||
#: src/pages/settings/general.vue:312
|
||||
#: src/pages/settings/general.vue:420
|
||||
msgid "Share"
|
||||
msgstr ""
|
||||
|
||||
@@ -1748,7 +1756,7 @@ msgstr ""
|
||||
msgid "Show less"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:445
|
||||
#: src/pages/settings/general.vue:553
|
||||
msgid "Show Library in navigation menu."
|
||||
msgstr ""
|
||||
|
||||
@@ -1756,7 +1764,7 @@ msgstr ""
|
||||
msgid "Show more"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:489
|
||||
#: src/pages/settings/general.vue:597
|
||||
msgid "Show server logs in Library."
|
||||
msgstr ""
|
||||
|
||||
@@ -1805,14 +1813,27 @@ msgstr ""
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:142
|
||||
msgid "Stack Sequences"
|
||||
#: src/pages/settings/general.vue:227
|
||||
msgid "Stack files sharing the same unique image or instance identifier."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:38
|
||||
msgid "Stack files with matching..."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:205
|
||||
msgid "Stack pictures taken at the exact same time and location based on their metadata."
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:89
|
||||
#: src/pages/settings/general.vue:144
|
||||
msgid "Stacks"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:145
|
||||
msgid "Stacks group files with a similar frame of reference, but differences of quality, format, size or color."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/library/index.vue:30
|
||||
msgid "Start"
|
||||
msgstr ""
|
||||
@@ -1837,7 +1858,7 @@ msgstr ""
|
||||
msgid "Streets"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:568
|
||||
#: src/pages/settings/general.vue:676
|
||||
msgid "Style"
|
||||
msgstr ""
|
||||
|
||||
@@ -1879,7 +1900,7 @@ msgstr ""
|
||||
msgid "Their format may not be supported, they haven't been converted to JPEG yet or there are duplicates."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:198
|
||||
#: src/pages/settings/general.vue:306
|
||||
msgid "Theme"
|
||||
msgstr ""
|
||||
|
||||
@@ -1956,6 +1977,10 @@ msgstr ""
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:226
|
||||
msgid "Unique ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/details.vue:16
|
||||
#: src/dialog/photo/info.vue:21
|
||||
#: src/model/album.js:122
|
||||
@@ -1998,7 +2023,7 @@ msgstr ""
|
||||
#: src/dialog/upload.vue:54
|
||||
#: src/pages/albums.vue:134
|
||||
#: src/pages/library/import.vue:38
|
||||
#: src/pages/settings/general.vue:268
|
||||
#: src/pages/settings/general.vue:376
|
||||
#: src/pages/settings/sync.vue:24
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
@@ -2019,7 +2044,7 @@ msgstr ""
|
||||
msgid "Upload local files"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:313
|
||||
#: src/pages/settings/general.vue:421
|
||||
msgid "Upload to WebDAV and share links with friends."
|
||||
msgstr ""
|
||||
|
||||
@@ -2045,7 +2070,7 @@ msgstr ""
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/settings/general.vue:38
|
||||
#: src/pages/settings/general.vue:66
|
||||
msgid "User Interface"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -59,15 +59,73 @@
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="onChange"
|
||||
:disabled="busy"
|
||||
class="ma-0 pa-0 input-sequences"
|
||||
v-model="settings.index.sequences"
|
||||
color="secondary-dark"
|
||||
:label="$gettext('Stack Sequences')"
|
||||
:hint="$gettext('Files with sequential names like \'IMG_1234 (2)\' or \'IMG_1234 copy 2\' belong to the same photo.')"
|
||||
prepend-icon="photo_library"
|
||||
persistent-hint
|
||||
@change="onChange"
|
||||
:disabled="busy"
|
||||
class="ma-0 pa-0 input-stacks"
|
||||
v-model="settings.index.stacks"
|
||||
color="secondary-dark"
|
||||
:label="$gettext('Stacks')"
|
||||
:hint="$gettext('Stacks group files with a similar frame of reference, but differences of quality, format, size or color.')"
|
||||
prepend-icon="burst_mode"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
<v-card flat tile class="mt-0 px-1 application" v-show="settings.index.stacks">
|
||||
<v-card-title primary-title class="pb-0">
|
||||
<h3 class="body-2 mb-0">
|
||||
<translate>Stack files with matching...</translate>
|
||||
</h3>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-actions>
|
||||
<v-layout wrap align-top>
|
||||
<v-flex xs12 sm6 lg4 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="onChange"
|
||||
:disabled="busy"
|
||||
class="ma-0 pa-0 input-stack-meta"
|
||||
v-model="settings.stack.meta"
|
||||
color="secondary-dark"
|
||||
:label="$gettext('Place & Time')"
|
||||
:hint="$gettext('Stack pictures taken at the exact same time and location based on their metadata.')"
|
||||
prepend-icon="schedule"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg4 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="onChange"
|
||||
:disabled="busy"
|
||||
class="ma-0 pa-0 input-stack-uuid"
|
||||
v-model="settings.stack.uuid"
|
||||
color="secondary-dark"
|
||||
:label="$gettext('Unique ID')"
|
||||
:hint="$gettext('Stack files sharing the same unique image or instance identifier.')"
|
||||
prepend-icon="fingerprint"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
|
||||
<v-flex xs12 sm6 lg4 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="onChange"
|
||||
:disabled="busy"
|
||||
class="ma-0 pa-0 input-stack-sequences"
|
||||
v-model="settings.stack.sequences"
|
||||
color="secondary-dark"
|
||||
:label="$gettext('File Name Prefix')"
|
||||
:hint="$gettext('Files with sequential names like \'IMG_1234 (2)\' and \'IMG_1234 (3)\' belong to the same picture.')"
|
||||
prepend-icon="spellcheck"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
@@ -49,7 +49,7 @@ func StartIndexing(router *gin.RouterGroup) {
|
||||
indOpt := photoprism.IndexOptions{
|
||||
Rescan: f.Rescan,
|
||||
Convert: conf.Settings().Index.Convert && conf.SidecarWritable(),
|
||||
Stack: conf.Settings().Index.Stack,
|
||||
Stack: conf.Settings().Index.Stacks,
|
||||
Path: filepath.Clean(f.Path),
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ func indexAction(ctx *cli.Context) error {
|
||||
Path: subPath,
|
||||
Rescan: ctx.Bool("all"),
|
||||
Convert: conf.Settings().Index.Convert && conf.SidecarWritable(),
|
||||
Stack: conf.Settings().Index.Stack,
|
||||
Stack: conf.Settings().Index.Stacks,
|
||||
}
|
||||
|
||||
indexed := ind.Start(indOpt)
|
||||
|
||||
@@ -27,21 +27,6 @@ type MapsSettings struct {
|
||||
Style string `json:"style" yaml:"style"`
|
||||
}
|
||||
|
||||
// IndexSettings represents indexing settings.
|
||||
type IndexSettings struct {
|
||||
Path string `json:"path" yaml:"path"`
|
||||
Convert bool `json:"convert" yaml:"convert"`
|
||||
Rescan bool `json:"rescan" yaml:"rescan"`
|
||||
Sequences bool `json:"sequences" yaml:"sequences"`
|
||||
Stack bool `json:"stack" yaml:"stack"`
|
||||
}
|
||||
|
||||
// ImportSettings represents import settings.
|
||||
type ImportSettings struct {
|
||||
Path string `json:"path" yaml:"path"`
|
||||
Move bool `json:"move" yaml:"move"`
|
||||
}
|
||||
|
||||
// FeatureSettings represents feature flags, mainly for the Web UI.
|
||||
type FeatureSettings struct {
|
||||
Upload bool `json:"upload" yaml:"upload"`
|
||||
@@ -60,6 +45,27 @@ type FeatureSettings struct {
|
||||
Logs bool `json:"logs" yaml:"logs"`
|
||||
}
|
||||
|
||||
// ImportSettings represents import settings.
|
||||
type ImportSettings struct {
|
||||
Path string `json:"path" yaml:"path"`
|
||||
Move bool `json:"move" yaml:"move"`
|
||||
}
|
||||
|
||||
// IndexSettings represents indexing settings.
|
||||
type IndexSettings struct {
|
||||
Path string `json:"path" yaml:"path"`
|
||||
Convert bool `json:"convert" yaml:"convert"`
|
||||
Rescan bool `json:"rescan" yaml:"rescan"`
|
||||
Stacks bool `json:"stacks" yaml:"stacks"`
|
||||
}
|
||||
|
||||
// StackSettings represents file stack settings.
|
||||
type StackSettings struct {
|
||||
UUID bool `json:"uuid" yaml:"uuid"`
|
||||
Meta bool `json:"meta" yaml:"meta"`
|
||||
Sequences bool `json:"sequences" yaml:"sequences"`
|
||||
}
|
||||
|
||||
// Settings represents user settings for Web UI, indexing, and import.
|
||||
type Settings struct {
|
||||
Theme string `json:"theme" yaml:"theme"`
|
||||
@@ -69,6 +75,7 @@ type Settings struct {
|
||||
Features FeatureSettings `json:"features" yaml:"features"`
|
||||
Import ImportSettings `json:"import" yaml:"import"`
|
||||
Index IndexSettings `json:"index" yaml:"index"`
|
||||
Stack StackSettings `json:"stack" yaml:"stack"`
|
||||
}
|
||||
|
||||
// NewSettings creates a new Settings instance.
|
||||
@@ -104,11 +111,15 @@ func NewSettings() *Settings {
|
||||
Move: false,
|
||||
},
|
||||
Index: IndexSettings{
|
||||
Path: "/",
|
||||
Rescan: false,
|
||||
Convert: true,
|
||||
Sequences: true,
|
||||
Stack: true,
|
||||
Path: "/",
|
||||
Rescan: false,
|
||||
Convert: true,
|
||||
Stacks: true,
|
||||
},
|
||||
Stack: StackSettings{
|
||||
UUID: true,
|
||||
Meta: true,
|
||||
Sequences: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
7
internal/config/testdata/configEmpty.yml
vendored
7
internal/config/testdata/configEmpty.yml
vendored
@@ -27,5 +27,8 @@ index:
|
||||
path: /
|
||||
convert: true
|
||||
rescan: false
|
||||
sequences: true
|
||||
stack: true
|
||||
stacks: true
|
||||
stack:
|
||||
uuid: true
|
||||
meta: true
|
||||
sequences: false
|
||||
|
||||
@@ -1012,13 +1012,27 @@ func (m *Photo) MapKey() string {
|
||||
}
|
||||
|
||||
// Stack merges the photo with identical ones.
|
||||
func (m *Photo) Stack() (identical Photos, err error) {
|
||||
if err := Db().
|
||||
func (m *Photo) Stack(meta, uuid bool) (identical Photos, err error) {
|
||||
if !meta && !uuid {
|
||||
return identical, nil
|
||||
}
|
||||
|
||||
stmt := Db().
|
||||
Where("id <> ?", m.ID).
|
||||
Where("photo_single = 0").
|
||||
Where("(taken_at = ? AND cell_id = ? AND camera_serial = ? AND camera_id = ?) OR (uuid <> '' AND uuid = ?)",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.UUID).
|
||||
Find(&identical).Error; err != nil {
|
||||
Where("photo_single = 0")
|
||||
|
||||
switch {
|
||||
case meta && uuid:
|
||||
stmt.Where("(taken_at = ? AND taken_src = 'meta' AND cell_id = ? AND camera_serial = ? AND camera_id = ?) OR (uuid <> '' AND uuid = ?)",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.UUID)
|
||||
case meta:
|
||||
stmt.Where("taken_at = ? AND taken_src = 'meta' AND cell_id = ? AND camera_serial = ? AND camera_id = ?",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID)
|
||||
case uuid:
|
||||
stmt.Where("uuid <> '' AND uuid = ?", m.UUID)
|
||||
}
|
||||
|
||||
if err := stmt.Find(&identical).Error; err != nil {
|
||||
return identical, err
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ func (c *Convert) Start(path string) error {
|
||||
|
||||
// ToJson uses exiftool to export metadata to a json file.
|
||||
func (c *Convert) ToJson(mf *MediaFile) (*MediaFile, error) {
|
||||
jsonName := fs.TypeJson.FindFirst(mf.FileName(), []string{c.conf.SidecarPath(), fs.HiddenPath}, c.conf.OriginalsPath(), c.conf.Settings().Index.Sequences)
|
||||
jsonName := fs.TypeJson.FindFirst(mf.FileName(), []string{c.conf.SidecarPath(), fs.HiddenPath}, c.conf.OriginalsPath(), c.conf.Settings().Stack.Sequences)
|
||||
|
||||
result, err := NewMediaFile(jsonName)
|
||||
|
||||
@@ -127,7 +127,7 @@ func (c *Convert) ToJson(mf *MediaFile) (*MediaFile, error) {
|
||||
return nil, fmt.Errorf("convert: can't create json sidecar file for %s in read only mode", txt.Quote(mf.BaseName()))
|
||||
}
|
||||
|
||||
jsonName = fs.FileName(mf.FileName(), c.conf.SidecarPath(), c.conf.OriginalsPath(), ".json", c.conf.Settings().Index.Sequences)
|
||||
jsonName = fs.FileName(mf.FileName(), c.conf.SidecarPath(), c.conf.OriginalsPath(), ".json", c.conf.Settings().Stack.Sequences)
|
||||
|
||||
fileName := mf.RelName(c.conf.OriginalsPath())
|
||||
|
||||
@@ -220,7 +220,7 @@ func (c *Convert) ToJpeg(image *MediaFile) (*MediaFile, error) {
|
||||
return image, nil
|
||||
}
|
||||
|
||||
jpegName := fs.TypeJpeg.FindFirst(image.FileName(), []string{c.conf.SidecarPath(), fs.HiddenPath}, c.conf.OriginalsPath(), c.conf.Settings().Index.Sequences)
|
||||
jpegName := fs.TypeJpeg.FindFirst(image.FileName(), []string{c.conf.SidecarPath(), fs.HiddenPath}, c.conf.OriginalsPath(), c.conf.Settings().Stack.Sequences)
|
||||
|
||||
mediaFile, err := NewMediaFile(jpegName)
|
||||
|
||||
@@ -232,12 +232,12 @@ func (c *Convert) ToJpeg(image *MediaFile) (*MediaFile, error) {
|
||||
return nil, fmt.Errorf("convert: disabled in read only mode (%s)", image.RelName(c.conf.OriginalsPath()))
|
||||
}
|
||||
|
||||
jpegName = fs.FileName(image.FileName(), c.conf.SidecarPath(), c.conf.OriginalsPath(), fs.JpegExt, c.conf.Settings().Index.Sequences)
|
||||
jpegName = fs.FileName(image.FileName(), c.conf.SidecarPath(), c.conf.OriginalsPath(), fs.JpegExt, c.conf.Settings().Stack.Sequences)
|
||||
fileName := image.RelName(c.conf.OriginalsPath())
|
||||
|
||||
log.Debugf("convert: %s -> %s", fileName, filepath.Base(jpegName))
|
||||
|
||||
xmpName := fs.TypeXMP.Find(image.FileName(), c.conf.Settings().Index.Sequences)
|
||||
xmpName := fs.TypeXMP.Find(image.FileName(), c.conf.Settings().Stack.Sequences)
|
||||
|
||||
event.Publish("index.converting", event.Data{
|
||||
"fileType": image.FileType(),
|
||||
@@ -308,7 +308,7 @@ func (c *Convert) ToAvc1(video *MediaFile) (*MediaFile, error) {
|
||||
return video, nil
|
||||
}
|
||||
|
||||
avcName := fs.TypeMp4.FindFirst(video.FileName(), []string{c.conf.SidecarPath(), fs.HiddenPath}, c.conf.OriginalsPath(), c.conf.Settings().Index.Sequences)
|
||||
avcName := fs.TypeMp4.FindFirst(video.FileName(), []string{c.conf.SidecarPath(), fs.HiddenPath}, c.conf.OriginalsPath(), c.conf.Settings().Stack.Sequences)
|
||||
|
||||
mediaFile, err := NewMediaFile(avcName)
|
||||
|
||||
@@ -320,7 +320,7 @@ func (c *Convert) ToAvc1(video *MediaFile) (*MediaFile, error) {
|
||||
return nil, fmt.Errorf("convert: disabled in read only mode (%s)", video.RelName(c.conf.OriginalsPath()))
|
||||
}
|
||||
|
||||
avcName = fs.FileName(video.FileName(), c.conf.SidecarPath(), c.conf.OriginalsPath(), fs.AvcExt, c.conf.Settings().Index.Sequences)
|
||||
avcName = fs.FileName(video.FileName(), c.conf.SidecarPath(), c.conf.OriginalsPath(), fs.AvcExt, c.conf.Settings().Stack.Sequences)
|
||||
fileName := video.RelName(c.conf.OriginalsPath())
|
||||
|
||||
log.Debugf("convert: %s -> %s", fileName, filepath.Base(avcName))
|
||||
|
||||
@@ -151,7 +151,7 @@ func (imp *Import) Start(opt ImportOptions) fs.Done {
|
||||
return nil
|
||||
}
|
||||
|
||||
related, err := mf.RelatedFiles(imp.conf.Settings().Index.Sequences)
|
||||
related, err := mf.RelatedFiles(imp.conf.Settings().Stack.Sequences)
|
||||
|
||||
if err != nil {
|
||||
event.Error(fmt.Sprintf("import: %s", err.Error()))
|
||||
|
||||
@@ -113,7 +113,7 @@ func ImportWorker(jobs <-chan ImportJob) {
|
||||
}
|
||||
}
|
||||
|
||||
related, err := f.RelatedFiles(imp.conf.Settings().Index.Sequences)
|
||||
related, err := f.RelatedFiles(imp.conf.Settings().Stack.Sequences)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("import: %s in %s (find related files)", err.Error(), txt.Quote(fs.RelName(destinationMainFilename, imp.originalsPath())))
|
||||
|
||||
@@ -167,7 +167,7 @@ func (ind *Index) Start(opt IndexOptions) fs.Done {
|
||||
return nil
|
||||
}
|
||||
|
||||
related, err := mf.RelatedFiles(ind.conf.Settings().Index.Sequences)
|
||||
related, err := mf.RelatedFiles(ind.conf.Settings().Stack.Sequences)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("index: %s", err.Error())
|
||||
@@ -222,7 +222,7 @@ func (ind *Index) Start(opt IndexOptions) fs.Done {
|
||||
}
|
||||
|
||||
if opt.Stack {
|
||||
if err := ind.StackIdenticalPhotos(); err != nil {
|
||||
if err := ind.StackPhotos(); err != nil {
|
||||
log.Errorf("index: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -240,16 +240,16 @@ func (ind *Index) Start(opt IndexOptions) fs.Done {
|
||||
return done
|
||||
}
|
||||
|
||||
// StackIdenticalPhotos stacks files that belong to the same photo.
|
||||
func (ind *Index) StackIdenticalPhotos() error {
|
||||
photos, err := query.IdenticalPhotos()
|
||||
// StackPhotos stacks files that belong to the same photo.
|
||||
func (ind *Index) StackPhotos() error {
|
||||
photos, err := query.MatchingPhotos(ind.conf.Settings().Stack.Meta, ind.conf.Settings().Stack.UUID)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, photo := range photos {
|
||||
if merged, err := photo.Stack(); err != nil {
|
||||
if merged, err := photo.Stack(ind.conf.Settings().Stack.Meta, ind.conf.Settings().Stack.UUID); err != nil {
|
||||
log.Errorf("index: %s", err)
|
||||
} else {
|
||||
log.Infof("index: merged photo uid %s with %s", photo.PhotoUID, merged.UIDs())
|
||||
|
||||
@@ -114,7 +114,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
||||
|
||||
photoExists := false
|
||||
|
||||
stripSequence := Config().Settings().Index.Sequences
|
||||
stripSequence := Config().Settings().Stack.Sequences
|
||||
|
||||
event.Publish("index.indexing", event.Data{
|
||||
"fileHash": fileHash,
|
||||
@@ -156,23 +156,24 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find existing photo by file path and name.
|
||||
// Look for existing photo if file wasn't indexed yet...
|
||||
if !fileExists {
|
||||
photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ?", filePath, fileBase)
|
||||
|
||||
// Add file to existing photo (file stack)?
|
||||
if o.Stack {
|
||||
// Try to find existing photo by exact time and location.
|
||||
// Stack file based on matching location and time metadata?
|
||||
if o.Stack && Config().Settings().Stack.Meta {
|
||||
if photoQuery.Error != nil && m.MetaData().HasTimeAndPlace() {
|
||||
metaData = m.MetaData()
|
||||
photoQuery = entity.UnscopedDb().First(&photo, "photo_lat = ? AND photo_lng = ? AND taken_at = ? AND camera_serial = ?", metaData.Lat, metaData.Lng, metaData.TakenAt, metaData.CameraSerial)
|
||||
photoQuery = entity.UnscopedDb().First(&photo, "photo_lat = ? AND photo_lng = ? AND taken_at = ? AND taken_src = 'meta' AND camera_serial = ?", metaData.Lat, metaData.Lng, metaData.TakenAt, metaData.CameraSerial)
|
||||
|
||||
if photoQuery.Error == nil {
|
||||
fileStacked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find existing photo by unique image id.
|
||||
// Stack file based on the same unique ID?
|
||||
if o.Stack && Config().Settings().Stack.UUID {
|
||||
if photoQuery.Error != nil && m.MetaData().HasDocumentID() {
|
||||
photoQuery = entity.UnscopedDb().First(&photo, "uuid = ?", m.MetaData().DocumentID)
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ func (m *MediaFile) PathNameInfo() (fileRoot, fileBase, relativePath, relativeNa
|
||||
rootPath = Config().OriginalsPath()
|
||||
}
|
||||
|
||||
fileBase = m.BasePrefix(Config().Settings().Index.Sequences)
|
||||
fileBase = m.BasePrefix(Config().Settings().Stack.Sequences)
|
||||
relativePath = m.RelPath(rootPath)
|
||||
relativeName = m.RelName(rootPath)
|
||||
|
||||
|
||||
@@ -110,23 +110,46 @@ func PhotosCheck(limit int, offset int) (entities entity.Photos, err error) {
|
||||
return entities, err
|
||||
}
|
||||
|
||||
// IdenticalPhotos returns photos sharing the same exact time, location and camera serial.
|
||||
func IdenticalPhotos() (entities entity.Photos, err error) {
|
||||
err = UnscopedDb().Table("photos").
|
||||
Select("photos.*").
|
||||
Joins(`JOIN photos dup ON photos.id < dup.id
|
||||
AND photos.photo_single = 0
|
||||
AND dup.photo_single = 0
|
||||
AND photos.deleted_at IS NULL
|
||||
AND dup.deleted_at IS NULL
|
||||
AND ((photos.photo_lat = dup.photo_lat
|
||||
// MatchingPhotos returns photos sharing the same exact time and location, or unique image id.
|
||||
func MatchingPhotos(meta, uuid bool) (entities entity.Photos, err error) {
|
||||
if !meta && !uuid {
|
||||
return entities, nil
|
||||
}
|
||||
|
||||
stmt := UnscopedDb().Table("photos").
|
||||
Select("photos.*")
|
||||
|
||||
switch {
|
||||
case meta && uuid:
|
||||
stmt.Joins(`JOIN photos dup ON photos.id < dup.id
|
||||
AND photos.photo_single = 0 AND dup.photo_single = 0
|
||||
AND photos.deleted_at IS NULL AND dup.deleted_at IS NULL
|
||||
AND ((photos.taken_src = 'meta' AND dup.taken_src = 'meta'
|
||||
AND photos.photo_lat = dup.photo_lat
|
||||
AND photos.photo_lng = dup.photo_lng
|
||||
AND photos.taken_at = dup.taken_at
|
||||
AND photos.camera_id = dup.camera_id
|
||||
AND photos.camera_serial = dup.camera_serial) OR
|
||||
(photos.uuid <> '' AND photos.uuid = dup.uuid))`).
|
||||
Group("photos.id").
|
||||
Find(&entities).Error
|
||||
(photos.uuid <> '' AND photos.uuid = dup.uuid))`)
|
||||
case meta:
|
||||
stmt.Joins(`JOIN photos dup ON photos.id < dup.id
|
||||
AND photos.photo_single = 0
|
||||
AND dup.photo_single = 0
|
||||
AND photos.deleted_at IS NULL AND dup.deleted_at IS NULL
|
||||
AND ((photos.taken_src = 'meta' AND dup.taken_src = 'meta'
|
||||
AND photos.photo_lat = dup.photo_lat
|
||||
AND photos.photo_lng = dup.photo_lng
|
||||
AND photos.taken_at = dup.taken_at
|
||||
AND photos.camera_id = dup.camera_id
|
||||
AND photos.camera_serial = dup.camera_serial))`)
|
||||
case uuid:
|
||||
stmt.Joins(`JOIN photos dup ON photos.id < dup.id
|
||||
AND photos.photo_single = 0 AND dup.photo_single = 0
|
||||
AND photos.deleted_at IS NULL AND dup.deleted_at IS NULL
|
||||
AND (photos.uuid <> '' AND photos.uuid = dup.uuid)`)
|
||||
}
|
||||
|
||||
err = stmt.Group("photos.id").Find(&entities).Error
|
||||
|
||||
return entities, err
|
||||
}
|
||||
|
||||
@@ -80,12 +80,43 @@ func TestPhotosCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIdenticalPhotos(t *testing.T) {
|
||||
result, err := IdenticalPhotos()
|
||||
t.Run("all", func(t *testing.T) {
|
||||
result, err := MatchingPhotos(true, true)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.IsType(t, entity.Photos{}, result)
|
||||
// t.Logf("%+v", result)
|
||||
assert.IsType(t, entity.Photos{}, result)
|
||||
})
|
||||
|
||||
t.Run("meta", func(t *testing.T) {
|
||||
result, err := MatchingPhotos(true, false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.IsType(t, entity.Photos{}, result)
|
||||
})
|
||||
|
||||
t.Run("uuid", func(t *testing.T) {
|
||||
result, err := MatchingPhotos(false, true)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.IsType(t, entity.Photos{}, result)
|
||||
})
|
||||
|
||||
t.Run("none", func(t *testing.T) {
|
||||
result, err := MatchingPhotos(false, false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.IsType(t, entity.Photos{}, result)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (worker *Sync) relatedDownloads(a entity.Account) (result Downloads, err er
|
||||
|
||||
// Group results by directory and base name
|
||||
for i, file := range files {
|
||||
k := fs.AbsPrefix(file.RemoteName, worker.conf.Settings().Index.Sequences)
|
||||
k := fs.AbsPrefix(file.RemoteName, worker.conf.Settings().Stack.Sequences)
|
||||
|
||||
result[k] = append(result[k], file)
|
||||
|
||||
@@ -137,7 +137,7 @@ func (worker *Sync) download(a entity.Account) (complete bool, err error) {
|
||||
continue
|
||||
}
|
||||
|
||||
related, err := mf.RelatedFiles(worker.conf.Settings().Index.Sequences)
|
||||
related, err := mf.RelatedFiles(worker.conf.Settings().Stack.Sequences)
|
||||
|
||||
if err != nil {
|
||||
worker.logWarn(err)
|
||||
|
||||
Reference in New Issue
Block a user