From 0104c3ea078126444e3156bdb508bd36d65b6eb9 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 09:26:24 -0800 Subject: [PATCH 001/163] Animate GIF in viewer --- src/components/Viewer.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index a780ac2c..5a4f8639 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -569,8 +569,15 @@ export default class Viewer extends Mixins(GlobalMixin) { /** Get base data object */ private getItemData(photo: IPhoto) { + let previewUrl = getPreviewUrl(photo, false, 2048); + + // Preview aren't animated + if (photo.mimetype === "image/gif") { + previewUrl = getDownloadLink(photo); + } + return { - src: getPreviewUrl(photo, false, 2048), + src: previewUrl, width: photo.w || undefined, height: photo.h || undefined, thumbCropped: true, From 0576b28f5ce3fc9de9c21062fd1bd01520abe955 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 12:46:43 -0800 Subject: [PATCH 002/163] Print per-file in index --- lib/Command/Index.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/Command/Index.php b/lib/Command/Index.php index 55134207..cce9439a 100644 --- a/lib/Command/Index.php +++ b/lib/Command/Index.php @@ -277,14 +277,6 @@ class Index extends Command return; } - // Clear previous line and write new one - $line = 'Scanning folder '.$folderPath; - if ($this->previousLineLength) { - $this->output->write("\r".str_repeat(' ', $this->previousLineLength)."\r"); - } - $this->output->write($line."\r"); - $this->previousLineLength = \strlen($line); - $nodes = $folder->getDirectoryListing(); foreach ($nodes as &$node) { @@ -305,6 +297,15 @@ class Index extends Command private function parseFile(File &$file, bool &$refresh): void { + // Clear previous line and write new one + $line = 'Scanning file '.$file->getPath(); + if ($this->previousLineLength) { + $this->output->write("\r".str_repeat(' ', $this->previousLineLength)."\r"); + } + $this->output->write($line."\r"); + $this->previousLineLength = \strlen($line); + + // Process the file $res = $this->timelineWrite->processFile($file, $refresh); if (2 === $res) { ++$this->nProcessed; From 1d65a6dabe3840cb1da5caa307c64f4808a4de80 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 13:13:16 -0800 Subject: [PATCH 003/163] Store exif meta in db --- lib/Db/TimelineWrite.php | 29 ++++++++ .../Version400604Date20221107205439.php | 67 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 lib/Migration/Version400604Date20221107205439.php diff --git a/lib/Db/TimelineWrite.php b/lib/Db/TimelineWrite.php index 20c11b07..f9744442 100644 --- a/lib/Db/TimelineWrite.php +++ b/lib/Db/TimelineWrite.php @@ -97,6 +97,33 @@ class TimelineWrite $dateTaken = gmdate('Y-m-d H:i:s', $dateTaken); [$w, $h] = Exif::getDimensions($exif); + // Store raw metadata in the database + // We need to remove blacklisted fields to prevent leaking info + unset($exif['SourceFile']); + unset($exif['FileName']); + unset($exif['ExifToolVersion']); + unset($exif['Directory']); + unset($exif['FileSize']); + unset($exif['FileModifyDate']); + unset($exif['FileAccessDate']); + unset($exif['FileInodeChangeDate']); + unset($exif['FilePermissions']); + + // Truncate any fields >2048 chars + foreach ($exif as $key => &$value) { + if (\is_string($value) && \strlen($value) > 2048) { + $exif[$key] = \substr($value, 0, 2048); + } + } + + // Store JSON string + $exifJson = json_encode($exif); + + // Store error if data > 64kb + if (\strlen($exifJson) > 65535) { + $exifJson = json_encode(['error' => 'Exif data too large']); + } + if ($prevRow) { // Update existing row // No need to set objectid again @@ -107,6 +134,7 @@ class TimelineWrite ->set('isvideo', $query->createNamedParameter($isvideo, IQueryBuilder::PARAM_INT)) ->set('w', $query->createNamedParameter($w, IQueryBuilder::PARAM_INT)) ->set('h', $query->createNamedParameter($h, IQueryBuilder::PARAM_INT)) + ->set('exif', $query->createNamedParameter($exifJson, IQueryBuilder::PARAM_STR)) ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) ; $query->executeStatement(); @@ -123,6 +151,7 @@ class TimelineWrite 'isvideo' => $query->createNamedParameter($isvideo, IQueryBuilder::PARAM_INT), 'w' => $query->createNamedParameter($w, IQueryBuilder::PARAM_INT), 'h' => $query->createNamedParameter($h, IQueryBuilder::PARAM_INT), + 'exif' => $query->createNamedParameter($exifJson, IQueryBuilder::PARAM_STR), ]) ; $query->executeStatement(); diff --git a/lib/Migration/Version400604Date20221107205439.php b/lib/Migration/Version400604Date20221107205439.php new file mode 100644 index 00000000..5e6c0bbb --- /dev/null +++ b/lib/Migration/Version400604Date20221107205439.php @@ -0,0 +1,67 @@ + + * @author Your name + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace OCA\Memories\Migration; + +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Auto-generated migration step: Please modify to your needs! + */ +class Version400604Date20221107205439 extends SimpleMigrationStep +{ + /** + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void + { + } + + /** + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options): ?ISchemaWrapper + { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('memories'); + + $table->addColumn('exif', 'text', [ + 'notnull' => false, + 'length' => 65535, + 'default' => '', + ]); + + return $schema; + } + + /** + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void + { + } +} From 0fbe35db7d24d6fb7bf03845f9011c7f671c7c61 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 13:25:52 -0800 Subject: [PATCH 004/163] Return exif in info call --- lib/Controller/ImageController.php | 3 ++- lib/Db/TimelineQuery.php | 11 +++++++++-- lib/Db/TimelineWrite.php | 12 ++---------- .../Version400604Date20221107205439.php | 18 +++++++++--------- src/components/modal/EditDate.vue | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/Controller/ImageController.php b/lib/Controller/ImageController.php index ad9b7023..d790ee83 100644 --- a/lib/Controller/ImageController.php +++ b/lib/Controller/ImageController.php @@ -52,7 +52,8 @@ class ImageController extends ApiBase $file = $file[0]; // Get the image info - $info = $this->timelineQuery->getInfoById($file->getId()); + $basic = false !== $this->request->getParam('basic', false); + $info = $this->timelineQuery->getInfoById($file->getId(), $basic); return new JSONResponse($info, Http::STATUS_OK); } diff --git a/lib/Db/TimelineQuery.php b/lib/Db/TimelineQuery.php index 8974e541..e5d4eb2a 100644 --- a/lib/Db/TimelineQuery.php +++ b/lib/Db/TimelineQuery.php @@ -48,14 +48,18 @@ class TimelineQuery { } - public function getInfoById(int $id): array + public function getInfoById(int $id, bool $basic): array { $qb = $this->connection->getQueryBuilder(); - $qb->select('fileid', 'dayid', 'datetaken') + $qb->select('fileid', 'dayid', 'datetaken', 'w', 'h') ->from('memories') ->where($qb->expr()->eq('fileid', $qb->createNamedParameter($id, \PDO::PARAM_INT))) ; + if (!$basic) { + $qb->addSelect('exif'); + } + $result = $qb->executeQuery(); $row = $result->fetch(); $result->closeCursor(); @@ -72,6 +76,9 @@ class TimelineQuery 'fileid' => (int) $row['fileid'], 'dayid' => (int) $row['dayid'], 'datetaken' => $utcTs, + 'w' => (int) $row['w'], + 'h' => (int) $row['h'], + 'exif' => $basic ? [] : json_decode($row['exif'], true), ]; } } diff --git a/lib/Db/TimelineWrite.php b/lib/Db/TimelineWrite.php index f9744442..bcd9145c 100644 --- a/lib/Db/TimelineWrite.php +++ b/lib/Db/TimelineWrite.php @@ -99,20 +99,12 @@ class TimelineWrite // Store raw metadata in the database // We need to remove blacklisted fields to prevent leaking info - unset($exif['SourceFile']); - unset($exif['FileName']); - unset($exif['ExifToolVersion']); - unset($exif['Directory']); - unset($exif['FileSize']); - unset($exif['FileModifyDate']); - unset($exif['FileAccessDate']); - unset($exif['FileInodeChangeDate']); - unset($exif['FilePermissions']); + unset($exif['SourceFile'], $exif['FileName'], $exif['ExifToolVersion'], $exif['Directory'], $exif['FileSize'], $exif['FileModifyDate'], $exif['FileAccessDate'], $exif['FileInodeChangeDate'], $exif['FilePermissions']); // Truncate any fields >2048 chars foreach ($exif as $key => &$value) { if (\is_string($value) && \strlen($value) > 2048) { - $exif[$key] = \substr($value, 0, 2048); + $exif[$key] = substr($value, 0, 2048); } } diff --git a/lib/Migration/Version400604Date20221107205439.php b/lib/Migration/Version400604Date20221107205439.php index 5e6c0bbb..c978652f 100644 --- a/lib/Migration/Version400604Date20221107205439.php +++ b/lib/Migration/Version400604Date20221107205439.php @@ -44,18 +44,18 @@ class Version400604Date20221107205439 extends SimpleMigrationStep */ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options): ?ISchemaWrapper { - /** @var ISchemaWrapper $schema */ - $schema = $schemaClosure(); + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); - $table = $schema->getTable('memories'); + $table = $schema->getTable('memories'); - $table->addColumn('exif', 'text', [ - 'notnull' => false, - 'length' => 65535, - 'default' => '', - ]); + $table->addColumn('exif', 'text', [ + 'notnull' => false, + 'length' => 65535, + 'default' => '', + ]); - return $schema; + return $schema; } /** diff --git a/src/components/modal/EditDate.vue b/src/components/modal/EditDate.vue index da5723d8..ebf0f8c5 100644 --- a/src/components/modal/EditDate.vue +++ b/src/components/modal/EditDate.vue @@ -186,7 +186,7 @@ export default class EditDate extends Mixins(GlobalMixin) { const calls = photos.map((p) => async () => { try { const res = await axios.get( - generateUrl(INFO_API_URL, { id: p.fileid }) + generateUrl(INFO_API_URL, { id: p.fileid }) + "?basic=1" ); if (typeof res.data.datetaken !== "number") { console.error("Invalid date for", p.fileid); From 34155aae78d2ac871fae9eee6267d70b822f393c Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 13:55:11 -0800 Subject: [PATCH 005/163] metaview: dump raw exif --- src/App.vue | 35 +++++++++++++++++++++++++++++++++++ src/components/Metadata.vue | 37 +++++++++++++++++++++++++++++++++++++ src/components/Viewer.vue | 1 + src/services/dav/base.ts | 1 + src/types.ts | 2 ++ 5 files changed, 76 insertions(+) create mode 100644 src/components/Metadata.vue diff --git a/src/App.vue b/src/App.vue index c8244f68..c0afe12c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -106,6 +106,7 @@ import { getCurrentUser } from "@nextcloud/auth"; import Timeline from "./components/Timeline.vue"; import Settings from "./components/Settings.vue"; import FirstStart from "./components/FirstStart.vue"; +import Metadata from "./components/Metadata.vue"; import GlobalMixin from "./mixins/GlobalMixin"; import UserConfig from "./mixins/UserConfig"; @@ -147,6 +148,8 @@ import MapIcon from "vue-material-design-icons/Map.vue"; export default class App extends Mixins(GlobalMixin, UserConfig) { // Outer element + private metadataComponent!: Metadata; + get ncVersion() { const version = (window.OC).config.version.split("."); return Number(version[0]); @@ -185,6 +188,38 @@ export default class App extends Mixins(GlobalMixin, UserConfig) { const colorPrimary = getComputedStyle(root).getPropertyValue("--color-primary"); root.style.setProperty("--color-primary-select-light", `${colorPrimary}40`); + + // Register sidebar metadata tab + const OCA = globalThis.OCA; + if (OCA.Files && OCA.Files.Sidebar) { + OCA.Files.Sidebar.registerTab( + new OCA.Files.Sidebar.Tab({ + id: "memories-metadata", + name: this.t("memories", "Metadata"), + icon: "icon-details", + + async mount(el, fileInfo, context) { + if (this.metadataComponent) { + this.metadataComponent.$destroy(); + } + this.metadataComponent = new Metadata({ + // Better integration with vue parent component + parent: context, + }); + // Only mount after we have all the info we need + await this.metadataComponent.update(fileInfo); + this.metadataComponent.$mount(el); + }, + update(fileInfo) { + this.metadataComponent.update(fileInfo); + }, + destroy() { + this.metadataComponent.$destroy(); + this.metadataComponent = null; + }, + }) + ); + } } async beforeMount() { diff --git a/src/components/Metadata.vue b/src/components/Metadata.vue new file mode 100644 index 00000000..80de6acf --- /dev/null +++ b/src/components/Metadata.vue @@ -0,0 +1,37 @@ + + + \ No newline at end of file diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index 5a4f8639..907a90f3 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -763,6 +763,7 @@ export default class Viewer extends Mixins(GlobalMixin) { private async openSidebar(photo?: IPhoto) { const fInfo = await dav.getFiles([photo || this.currentPhoto]); globalThis.OCA?.Files?.Sidebar?.setFullScreenMode?.(true); + globalThis.OCA.Files.Sidebar.setActiveTab("memories-metadata"); globalThis.OCA.Files.Sidebar.open(fInfo[0].filename); } diff --git a/src/services/dav/base.ts b/src/services/dav/base.ts index c991421f..4365aedd 100644 --- a/src/services/dav/base.ts +++ b/src/services/dav/base.ts @@ -55,6 +55,7 @@ export async function getFiles(photos: IPhoto[]): Promise { photosWithFilename.map((photo) => { const prefixPath = `/files/${getCurrentUser()?.uid}`; return { + id: photo.fileid, fileid: photo.fileid, filename: photo.filename.replace(prefixPath, ""), originalFilename: photo.filename, diff --git a/src/types.ts b/src/types.ts index 83ec8ec7..e30eb360 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,8 @@ import { VueConstructor } from "vue"; export type IFileInfo = { + /** Same as fileid */ + id: number; /** Database file ID */ fileid: number; /** Full file name, e.g. /pi/test/Qx0dq7dvEXA.jpg */ From 0d0a6d8cf24bf77f8a8ad56688de0de5f39948a4 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 14:19:46 -0800 Subject: [PATCH 006/163] metaview: date --- src/components/Metadata.vue | 70 ++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/src/components/Metadata.vue b/src/components/Metadata.vue index 80de6acf..998dcf18 100644 --- a/src/components/Metadata.vue +++ b/src/components/Metadata.vue @@ -1,8 +1,15 @@ @@ -13,11 +20,18 @@ import GlobalMixin from "../mixins/GlobalMixin"; import { generateUrl } from "@nextcloud/router"; import axios from "@nextcloud/axios"; +import moment from "moment"; +import * as utils from "../services/Utils"; + +import CalendarIcon from "vue-material-design-icons/Calendar.vue"; import { IFileInfo } from "../types"; +import { getCanonicalLocale } from "@nextcloud/l10n"; @Component({ - components: {}, + components: { + CalendarIcon, + }, }) export default class Metadata extends Mixins(GlobalMixin) { private exif: { [prop: string]: any } = {}; @@ -26,6 +40,31 @@ export default class Metadata extends Mixins(GlobalMixin) { return Object.keys(this.exif); } + get dateOriginal() { + const dt = this.exif["DateTimeOriginal"] || this.exif["CreateDate"]; + if (!dt) return null; + + const m = moment(dt, "YYYY:MM:DD HH:mm:ss"); + if (!m.isValid()) return null; + m.locale(getCanonicalLocale()); + return m; + } + + get dateOriginalStr() { + if (!this.dateOriginal) return null; + return utils.getLongDateStr(this.dateOriginal.toDate(), true); + } + + get dateOriginalTime() { + if (!this.dateOriginal) return null; + + // Try to get timezone + let tz = this.exif["OffsetTimeOriginal"] || this.exif["OffsetTime"]; + tz = tz ? "GMT" + tz : ""; + + return this.dateOriginal.format("h:mm A") + " " + tz; + } + public async update(fileInfo: IFileInfo) { this.exif = {}; const res = await axios.get( @@ -34,4 +73,25 @@ export default class Metadata extends Mixins(GlobalMixin) { this.exif = res.data.exif || {}; } } - \ No newline at end of file + + + \ No newline at end of file From 14cdab5d7920fb0a65503a4a4c2496ef4db0ec4f Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 7 Nov 2022 14:46:09 -0800 Subject: [PATCH 007/163] metaview: add camera --- src/components/Metadata.vue | 97 +++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/src/components/Metadata.vue b/src/components/Metadata.vue index 998dcf18..5c998a60 100644 --- a/src/components/Metadata.vue +++ b/src/components/Metadata.vue @@ -1,13 +1,15 @@ @@ -79,6 +82,7 @@ Date: Mon, 14 Nov 2022 03:14:53 +0000 Subject: [PATCH 106/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/de_DE.js | 3 +++ l10n/de_DE.json | 3 +++ l10n/tr.js | 9 ++++++++- l10n/tr.json | 9 ++++++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/l10n/de_DE.js b/l10n/de_DE.js index 90ed2fd8..9bb6cb4a 100644 --- a/l10n/de_DE.js +++ b/l10n/de_DE.js @@ -26,6 +26,8 @@ OC.L10N.register( "Choose the root of your timeline" : "Start Ihrer Zeitleiste auswählen", "The selected folder does not seem to be valid. Try again." : "Der ausgewählte Ordner scheint ungültig zu sein. Versuchen Sie es nochmal.", "Found {total} photos in {path}" : "{total} Fotos gefunden in {path}", + "Failed to get Exif data. Metadata may be lost!" : "Exif-Daten konnten nicht abgerufen werden. Metadaten können verloren gehen!", + "No Exif data found! Continue?" : "Keine Exif-Daten gefunden! Fortsetzen?", "Image saved successfully" : "Bild erfolgreich gespeichert", "Error saving image" : "Fehler beim Speichern des Bildes", "Unsaved changes" : "Ungespeicherte Änderungen", @@ -218,6 +220,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Beachten Sie, dass der ausgewählte Zuschneidebereich kleiner ist als die angewendete Größenänderung, was zu Qualitätseinbußen führen kann", "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", + "Transcoding failed." : "Transkodierung fehlgeschlagen.", "Shared Folder" : "Geteilter Ordner", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", diff --git a/l10n/de_DE.json b/l10n/de_DE.json index e0b5fbc5..b4a902b8 100644 --- a/l10n/de_DE.json +++ b/l10n/de_DE.json @@ -24,6 +24,8 @@ "Choose the root of your timeline" : "Start Ihrer Zeitleiste auswählen", "The selected folder does not seem to be valid. Try again." : "Der ausgewählte Ordner scheint ungültig zu sein. Versuchen Sie es nochmal.", "Found {total} photos in {path}" : "{total} Fotos gefunden in {path}", + "Failed to get Exif data. Metadata may be lost!" : "Exif-Daten konnten nicht abgerufen werden. Metadaten können verloren gehen!", + "No Exif data found! Continue?" : "Keine Exif-Daten gefunden! Fortsetzen?", "Image saved successfully" : "Bild erfolgreich gespeichert", "Error saving image" : "Fehler beim Speichern des Bildes", "Unsaved changes" : "Ungespeicherte Änderungen", @@ -216,6 +218,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Beachten Sie, dass der ausgewählte Zuschneidebereich kleiner ist als die angewendete Größenänderung, was zu Qualitätseinbußen führen kann", "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", + "Transcoding failed." : "Transkodierung fehlgeschlagen.", "Shared Folder" : "Geteilter Ordner", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", diff --git a/l10n/tr.js b/l10n/tr.js index b14fe8cc..e89e1778 100644 --- a/l10n/tr.js +++ b/l10n/tr.js @@ -14,6 +14,7 @@ OC.L10N.register( "On this day" : "Bugün", "Tags" : "Etiketler", "Maps" : "Haritalar", + "EXIF" : "EXIF", "A better photos experience awaits you" : "Daha iyi bir fotoğraf deneyimi sizi bekliyor", "Choose the root folder of your timeline to begin" : "Zaman tünelinizin başlangıç kök klasörünü seçin", "If you just installed Memories, run:" : "Anılar uygulamasını yeni kurduysanız şunu çalıştırın:", @@ -24,6 +25,9 @@ OC.L10N.register( "Choose the root of your timeline" : "Zaman tünelinizin kök klasörünü seçin", "The selected folder does not seem to be valid. Try again." : "Seçilmiş klasör geçersiz gibi görünüyor. Yeniden deneyin.", "Found {total} photos in {path}" : "{path} yolunda {total} fotoğraf bulundu", + "Failed to get Exif data. Metadata may be lost!" : "EXIF verileri alınamadı. Üst veriler kaybolmuş olabilir!", + "No Exif data found! Continue?" : "Herhangi bir EXIF verisi bulunamadı. İlerlensin mi?", + "Image saved successfully" : "Görsel kaydedildi", "Error saving image" : "Görsel kaydedilirken sorun çıktı", "Unsaved changes" : "Kaydedilmemiş değişiklikler", "Drop changes" : "Değişiklikleri yok say", @@ -54,6 +58,8 @@ OC.L10N.register( "Failed to load some photos" : "Bazı fotoğraflar yüklenemedi", "Share" : "Paylaş", "Sidebar" : "Yan çubuk", + "Video sharing not supported yet" : "Görüntü paylaşımı henüz desteklenmiyor", + "Cannot share this type of data" : "Bu türdeki verileri paylaşamazsınız", "Processing … {n}/{m}" : "İşleniyor… {n}/{m}", "{n} photos added to album" : "{n} fotoğraf albüme eklendi", "Search for collaborators" : "Katılımcı arama", @@ -148,7 +154,7 @@ OC.L10N.register( "Resize" : "Yeniden boyutlandır", "Invalid image." : "Görsel geçersiz.", "Error while uploading the image." : "Görsel yüklenirken sorun çıktı.", - "are not images" : "görsel değil", + "are not images" : "görseller değil", "is not an image" : "bir görsel değil", "to be uploaded" : "yüklenecek", "Crop" : "Kırp", @@ -213,6 +219,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Seçilmiş kırpma alanı uygulanan yeniden boyutlandırma alanından küçük. Bu durum görsel kalitesinin düşmesine neden olabilir.", "Actual size (100%)" : "Gerçek boyut (%100)", "Fit size" : "Boyutu sığdır", + "Transcoding failed." : "Kod dönüştürülemedi.", "Shared Folder" : "Paylaşılmış klasör", "Failed to create {albumName}." : "{albumName} albümü oluşturulamadı.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} albümünün adı {newAlbumName} olarak değiştirilemedi.", diff --git a/l10n/tr.json b/l10n/tr.json index 496d462f..249f1da4 100644 --- a/l10n/tr.json +++ b/l10n/tr.json @@ -12,6 +12,7 @@ "On this day" : "Bugün", "Tags" : "Etiketler", "Maps" : "Haritalar", + "EXIF" : "EXIF", "A better photos experience awaits you" : "Daha iyi bir fotoğraf deneyimi sizi bekliyor", "Choose the root folder of your timeline to begin" : "Zaman tünelinizin başlangıç kök klasörünü seçin", "If you just installed Memories, run:" : "Anılar uygulamasını yeni kurduysanız şunu çalıştırın:", @@ -22,6 +23,9 @@ "Choose the root of your timeline" : "Zaman tünelinizin kök klasörünü seçin", "The selected folder does not seem to be valid. Try again." : "Seçilmiş klasör geçersiz gibi görünüyor. Yeniden deneyin.", "Found {total} photos in {path}" : "{path} yolunda {total} fotoğraf bulundu", + "Failed to get Exif data. Metadata may be lost!" : "EXIF verileri alınamadı. Üst veriler kaybolmuş olabilir!", + "No Exif data found! Continue?" : "Herhangi bir EXIF verisi bulunamadı. İlerlensin mi?", + "Image saved successfully" : "Görsel kaydedildi", "Error saving image" : "Görsel kaydedilirken sorun çıktı", "Unsaved changes" : "Kaydedilmemiş değişiklikler", "Drop changes" : "Değişiklikleri yok say", @@ -52,6 +56,8 @@ "Failed to load some photos" : "Bazı fotoğraflar yüklenemedi", "Share" : "Paylaş", "Sidebar" : "Yan çubuk", + "Video sharing not supported yet" : "Görüntü paylaşımı henüz desteklenmiyor", + "Cannot share this type of data" : "Bu türdeki verileri paylaşamazsınız", "Processing … {n}/{m}" : "İşleniyor… {n}/{m}", "{n} photos added to album" : "{n} fotoğraf albüme eklendi", "Search for collaborators" : "Katılımcı arama", @@ -146,7 +152,7 @@ "Resize" : "Yeniden boyutlandır", "Invalid image." : "Görsel geçersiz.", "Error while uploading the image." : "Görsel yüklenirken sorun çıktı.", - "are not images" : "görsel değil", + "are not images" : "görseller değil", "is not an image" : "bir görsel değil", "to be uploaded" : "yüklenecek", "Crop" : "Kırp", @@ -211,6 +217,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Seçilmiş kırpma alanı uygulanan yeniden boyutlandırma alanından küçük. Bu durum görsel kalitesinin düşmesine neden olabilir.", "Actual size (100%)" : "Gerçek boyut (%100)", "Fit size" : "Boyutu sığdır", + "Transcoding failed." : "Kod dönüştürülemedi.", "Shared Folder" : "Paylaşılmış klasör", "Failed to create {albumName}." : "{albumName} albümü oluşturulamadı.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} albümünün adı {newAlbumName} olarak değiştirilemedi.", From e9d3b80f0a264c1bfbfac609e301ef4b29f71277 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 21:21:46 -0800 Subject: [PATCH 107/163] Add plyr --- package-lock.json | 333 ++++++++++++-------------------------- package.json | 2 +- src/assets/plyr.svg | 1 + src/components/PsVideo.ts | 89 +++++++++- 4 files changed, 185 insertions(+), 240 deletions(-) create mode 100644 src/assets/plyr.svg diff --git a/package-lock.json b/package-lock.json index ae8cce8f..961679c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,10 +19,10 @@ "moment": "^2.29.4", "path-posix": "^1.0.0", "photoswipe": "^5.3.3", + "plyr": "^3.7.2", "reflect-metadata": "^0.1.13", "video.js": "^7.20.3", "videojs-contrib-quality-levels": "^2.2.0", - "videojs-hls-quality-selector": "^1.1.4", "vue": "^2.7.10", "vue-class-component": "^7.2.6", "vue-material-design-icons": "^5.1.2", @@ -2877,11 +2877,6 @@ "node": ">=4" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -3673,7 +3668,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", @@ -3989,6 +3985,11 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" }, + "node_modules/custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "node_modules/date-format-parse": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/date-format-parse/-/date-format-parse-0.2.7.tgz", @@ -4891,53 +4892,11 @@ "dev": true, "peer": true }, - "node_modules/fs-promise": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-0.5.0.tgz", - "integrity": "sha512-Y+4F4ujhEcayCJt6JmzcOun9MYGQwz+bVUiuBmTkJImhBHKpBvmVPZR9wtfiF7k3ffwAOAuurygQe+cPLSFQhw==", - "deprecated": "Use mz or fs-extra^3.0 with Promise Support", - "dependencies": { - "any-promise": "^1.0.0", - "fs-extra": "^0.26.5", - "mz": "^2.3.1", - "thenify-all": "^1.6.0" - } - }, - "node_modules/fs-promise/node_modules/fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/fs-promise/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/fs-promise/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/function-bind": { "version": "1.1.1", @@ -5034,6 +4993,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5073,6 +5033,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5082,6 +5043,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5109,7 +5071,8 @@ "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true }, "node_modules/hammerjs": { "version": "2.0.8", @@ -5516,6 +5479,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5524,7 +5488,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/internal-slot": { "version": "1.0.3", @@ -6189,18 +6154,6 @@ "resolved": "https://registry.npmjs.org/justified-layout/-/justified-layout-4.1.0.tgz", "integrity": "sha512-M5FimNMXgiOYerVRGsXZ2YK9YNCaTtwtYp7Hb2308U1Q9TXXHx5G0p08mcVR5O53qf8bWY4NJcPBxE6zuayXSg==" }, - "node_modules/karma-safaritechpreview-launcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/karma-safaritechpreview-launcher/-/karma-safaritechpreview-launcher-0.0.6.tgz", - "integrity": "sha512-2QMxAGXPQ37H3KoR9SCdh0OoktQZ5MyrxkvBiZ+VVOQfYVrcyOQXGrPea0/DKvf8qoQvrvP2FHcP/BxsuxuyHw==", - "dependencies": { - "fs-promise": "^0.5.0", - "marcosc-async": "^3.0.4" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/keycode": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", @@ -6216,14 +6169,6 @@ "node": ">=0.10.0" } }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, "node_modules/klona": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", @@ -6307,6 +6252,11 @@ "node": ">=8.9.0" } }, + "node_modules/loadjs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.2.0.tgz", + "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==" + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -6410,12 +6360,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/marcosc-async": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/marcosc-async/-/marcosc-async-3.0.5.tgz", - "integrity": "sha512-CCDofAatyNlbCCE1aIERplqT8r4S3LLc72pg3Bg/RilWPFqdXYO/FiDfzZ9ijf7K1P0j5mUZYCQ6eWXNuAxNBg==", - "engines": ">=4" - }, "node_modules/material-colors": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", @@ -6675,16 +6619,6 @@ "npm": ">=5" } }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -6809,6 +6743,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -6900,6 +6835,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -7050,6 +6986,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -7175,6 +7112,18 @@ "node": ">=14" } }, + "node_modules/plyr": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/plyr/-/plyr-3.7.2.tgz", + "integrity": "sha512-I0ZC/OI4oJ0iWG9s2rrnO0YFO6aLyrPiQBq9kum0FqITYljwTPBbYL3TZZu8UJQJUq7tUWN18Q7ACwNCkGKABQ==", + "dependencies": { + "core-js": "^3.22.0", + "custom-event-polyfill": "^1.0.7", + "loadjs": "^4.2.0", + "rangetouch": "^2.0.1", + "url-polyfill": "^1.1.12" + } + }, "node_modules/polished": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/polished/-/polished-3.7.2.tgz", @@ -7487,6 +7436,11 @@ "node": ">= 0.6" } }, + "node_modules/rangetouch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz", + "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==" + }, "node_modules/raw-body": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", @@ -8881,25 +8835,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -9307,6 +9242,11 @@ "requires-port": "^1.0.0" } }, + "node_modules/url-polyfill": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.12.tgz", + "integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==" + }, "node_modules/url-toolkit": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz", @@ -9457,17 +9397,6 @@ "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz", "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" }, - "node_modules/videojs-hls-quality-selector": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/videojs-hls-quality-selector/-/videojs-hls-quality-selector-1.1.4.tgz", - "integrity": "sha512-wWAjlLQui02gp//t9KHGd3XnbYO7wdOptskh3ZYCrbl/5Lbkveqb9yBVjH4e0zIQBPvGdWPMcOeDukf8iuYeBw==", - "dependencies": { - "global": "^4.3.2", - "karma-safaritechpreview-launcher": "0.0.6", - "video.js": "^7.5.5", - "videojs-contrib-quality-levels": "^2.0.9" - } - }, "node_modules/videojs-vtt.js": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz", @@ -10471,7 +10400,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { "version": "8.10.0", @@ -12650,11 +12580,6 @@ "color-convert": "^1.9.0" } }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -13291,7 +13216,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "connect-history-api-fallback": { "version": "2.0.0", @@ -13547,6 +13473,11 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" }, + "custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "date-format-parse": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/date-format-parse/-/date-format-parse-0.2.7.tgz", @@ -14265,51 +14196,11 @@ "dev": true, "peer": true }, - "fs-promise": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-0.5.0.tgz", - "integrity": "sha512-Y+4F4ujhEcayCJt6JmzcOun9MYGQwz+bVUiuBmTkJImhBHKpBvmVPZR9wtfiF7k3ffwAOAuurygQe+cPLSFQhw==", - "requires": { - "any-promise": "^1.0.0", - "fs-extra": "^0.26.5", - "mz": "^2.3.1", - "thenify-all": "^1.6.0" - }, - "dependencies": { - "fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "function-bind": { "version": "1.1.1", @@ -14379,6 +14270,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -14392,6 +14284,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -14401,6 +14294,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -14441,7 +14335,8 @@ "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true }, "hammerjs": { "version": "2.0.8", @@ -14767,6 +14662,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -14775,7 +14671,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "internal-slot": { "version": "1.0.3", @@ -15244,15 +15141,6 @@ "resolved": "https://registry.npmjs.org/justified-layout/-/justified-layout-4.1.0.tgz", "integrity": "sha512-M5FimNMXgiOYerVRGsXZ2YK9YNCaTtwtYp7Hb2308U1Q9TXXHx5G0p08mcVR5O53qf8bWY4NJcPBxE6zuayXSg==" }, - "karma-safaritechpreview-launcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/karma-safaritechpreview-launcher/-/karma-safaritechpreview-launcher-0.0.6.tgz", - "integrity": "sha512-2QMxAGXPQ37H3KoR9SCdh0OoktQZ5MyrxkvBiZ+VVOQfYVrcyOQXGrPea0/DKvf8qoQvrvP2FHcP/BxsuxuyHw==", - "requires": { - "fs-promise": "^0.5.0", - "marcosc-async": "^3.0.4" - } - }, "keycode": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", @@ -15265,14 +15153,6 @@ "dev": true, "peer": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "requires": { - "graceful-fs": "^4.1.9" - } - }, "klona": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", @@ -15328,6 +15208,11 @@ "json5": "^2.1.2" } }, + "loadjs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.2.0.tgz", + "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==" + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -15419,11 +15304,6 @@ "semver": "^6.0.0" } }, - "marcosc-async": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/marcosc-async/-/marcosc-async-3.0.5.tgz", - "integrity": "sha512-CCDofAatyNlbCCE1aIERplqT8r4S3LLc72pg3Bg/RilWPFqdXYO/FiDfzZ9ijf7K1P0j5mUZYCQ6eWXNuAxNBg==" - }, "material-colors": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", @@ -15633,16 +15513,6 @@ "global": "^4.4.0" } }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -15742,7 +15612,8 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "peer": true }, "object-inspect": { "version": "1.12.2", @@ -15807,6 +15678,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "requires": { "wrappy": "1" } @@ -15923,7 +15795,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true }, "path-key": { "version": "3.1.1", @@ -16012,6 +15885,18 @@ "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", "dev": true }, + "plyr": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/plyr/-/plyr-3.7.2.tgz", + "integrity": "sha512-I0ZC/OI4oJ0iWG9s2rrnO0YFO6aLyrPiQBq9kum0FqITYljwTPBbYL3TZZu8UJQJUq7tUWN18Q7ACwNCkGKABQ==", + "requires": { + "core-js": "^3.22.0", + "custom-event-polyfill": "^1.0.7", + "loadjs": "^4.2.0", + "rangetouch": "^2.0.1", + "url-polyfill": "^1.1.12" + } + }, "polished": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/polished/-/polished-3.7.2.tgz", @@ -16245,6 +16130,11 @@ "dev": true, "peer": true }, + "rangetouch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz", + "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==" + }, "raw-body": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", @@ -17311,22 +17201,6 @@ } } }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -17633,6 +17507,11 @@ "requires-port": "^1.0.0" } }, + "url-polyfill": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.12.tgz", + "integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==" + }, "url-toolkit": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz", @@ -17737,17 +17616,6 @@ "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz", "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" }, - "videojs-hls-quality-selector": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/videojs-hls-quality-selector/-/videojs-hls-quality-selector-1.1.4.tgz", - "integrity": "sha512-wWAjlLQui02gp//t9KHGd3XnbYO7wdOptskh3ZYCrbl/5Lbkveqb9yBVjH4e0zIQBPvGdWPMcOeDukf8iuYeBw==", - "requires": { - "global": "^4.3.2", - "karma-safaritechpreview-launcher": "0.0.6", - "video.js": "^7.5.5", - "videojs-contrib-quality-levels": "^2.0.9" - } - }, "videojs-vtt.js": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz", @@ -18562,7 +18430,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "ws": { "version": "8.10.0", diff --git a/package.json b/package.json index aae83758..aa91e4af 100644 --- a/package.json +++ b/package.json @@ -39,10 +39,10 @@ "moment": "^2.29.4", "path-posix": "^1.0.0", "photoswipe": "^5.3.3", + "plyr": "^3.7.2", "reflect-metadata": "^0.1.13", "video.js": "^7.20.3", "videojs-contrib-quality-levels": "^2.2.0", - "videojs-hls-quality-selector": "^1.1.4", "vue": "^2.7.10", "vue-class-component": "^7.2.6", "vue-material-design-icons": "^5.1.2", diff --git a/src/assets/plyr.svg b/src/assets/plyr.svg new file mode 100644 index 00000000..62ab2579 --- /dev/null +++ b/src/assets/plyr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index bd7740bf..6b421246 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -6,10 +6,13 @@ import { showError } from "@nextcloud/dialogs"; import { translate as t } from "@nextcloud/l10n"; import { getCurrentUser } from "@nextcloud/auth"; +import Plyr from "plyr"; +import "plyr/dist/plyr.css"; +import plyrsvg from "../assets/plyr.svg"; + import videojs from "video.js"; import "video.js/dist/video-js.min.css"; import "videojs-contrib-quality-levels"; -import "videojs-hls-quality-selector"; const config_noTranscode = loadState( "memories", @@ -139,8 +142,11 @@ class VideoContentSetup { ); } } + + // Add the video element to the actual container content.element.appendChild(content.videoElement); + // Get file id const fileid = content.data.photo.fileid; // Create hls sources if enabled @@ -164,7 +170,7 @@ class VideoContentSetup { content.videojs = videojs(content.videoElement, { fill: true, autoplay: true, - controls: true, + controls: false, sources: sources, preload: "metadata", playbackRates: [0.5, 1, 1.5, 2], @@ -198,11 +204,6 @@ class VideoContentSetup { } }); - content.videojs.qualityLevels(); - content.videojs.hlsQualitySelector({ - displayCurrentQuality: true, - }); - setTimeout(() => { content.videojs .contentEl() @@ -220,6 +221,9 @@ class VideoContentSetup { canPlay = true; this.updateRotation(content); }); + content.videojs.on("loadedmetadata", () => { + this.initPlyr(content); + }); // Get correct orientation axios @@ -242,6 +246,10 @@ class VideoContentSetup { content.videojs.dispose(); content.videojs = null; + content.plyr.elements.container.remove(); + content.plyr.destroy(); + content.plyr = null; + const elem: HTMLDivElement = content.element; while (elem.lastElementChild) { elem.removeChild(elem.lastElementChild); @@ -250,6 +258,73 @@ class VideoContentSetup { } } + initPlyr(content: any) { + if (content.plyr) return; + + // Retain original parent for video element + const origParent = content.videoElement.parentElement; + + // Populate quality list + const qualityList = content.videojs?.qualityLevels(); + let qualityNums: number[]; + if (qualityList && qualityList.length > 1) { + const s = new Set(); + for (let i = 0; i < qualityList?.length; i++) { + const { width, height } = qualityList[i]; + s.add(Math.min(width, height)); + } + qualityNums = Array.from(s).sort((a, b) => b - a); + qualityNums.unshift(0); + } + + // Create a second container element to append the video + // temporarily, so we can put the plyr controls there. This is + // required because controls have to fill the entire space + // const pc = document.createElement("div"); + // pc.appendChild(content.videoElement); + const plyr = new Plyr(content.videoElement, { + iconUrl: plyrsvg, + quality: !qualityNums + ? undefined + : { + default: 0, + options: qualityNums, + forced: true, + onChange: (quality: number) => { + if (!qualityList || !content.videojs) return; + for (let i = 0; i < qualityList.length; ++i) { + const { width, height } = qualityList[i]; + const pixels = Math.min(width, height); + qualityList[i].enabled = pixels === quality || !quality; + } + }, + }, + i18n: { + qualityLabel: { + 0: t("memories", "Auto"), + }, + }, + }); + plyr.elements.container.style.height = "100%"; + plyr.elements.container.style.width = "100%"; + plyr.elements.container + .querySelectorAll("button") + .forEach((el) => el.classList.add("button-vue")); + plyr.elements.container + .querySelectorAll("progress") + .forEach((el) => el.classList.add("vue")); + plyr.elements.container.style.backgroundColor = "transparent"; + plyr.elements.wrapper.style.backgroundColor = "transparent"; + + content.plyr = plyr; + globalThis.plyr = plyr; + + // Restore original parent of video element + origParent.appendChild(content.videoElement); + // Move plyr to the slide container + content.slide.holderElement.appendChild(plyr.elements.container); + } + updateRotation(content, val?: number) { if (!content.videojs || !content.videoElement) { return; From 80ac6355d634f83e9d702b0d7904dfadf972f0e2 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 21:33:11 -0800 Subject: [PATCH 108/163] Fix fullscreen --- src/components/PsVideo.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 6b421246..3016d36e 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -205,16 +205,8 @@ class VideoContentSetup { }); setTimeout(() => { - content.videojs - .contentEl() - .querySelectorAll("button") - .forEach((b: HTMLButtonElement) => { - b.classList.add("button-vue"); - }); - - // iOS needs this - content.videojs.play(); - }, 500); + content.videojs.play(); // iOS needs this + }, 200); let canPlay = false; content.videojs.on("canplay", () => { @@ -280,8 +272,6 @@ class VideoContentSetup { // Create a second container element to append the video // temporarily, so we can put the plyr controls there. This is // required because controls have to fill the entire space - // const pc = document.createElement("div"); - // pc.appendChild(content.videoElement); const plyr = new Plyr(content.videoElement, { iconUrl: plyrsvg, quality: !qualityNums @@ -304,6 +294,10 @@ class VideoContentSetup { 0: t("memories", "Auto"), }, }, + fullscreen: { + enabled: true, + container: ".pswp__item", + }, }); plyr.elements.container.style.height = "100%"; plyr.elements.container.style.width = "100%"; @@ -317,7 +311,6 @@ class VideoContentSetup { plyr.elements.wrapper.style.backgroundColor = "transparent"; content.plyr = plyr; - globalThis.plyr = plyr; // Restore original parent of video element origParent.appendChild(content.videoElement); From 0bcc0fda342e442f4a1c28fda62f2ac1a50040e1 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 21:41:04 -0800 Subject: [PATCH 109/163] plyr: more fixes --- src/components/PsVideo.ts | 42 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 3016d36e..5fd2a7db 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -269,26 +269,10 @@ class VideoContentSetup { qualityNums.unshift(0); } - // Create a second container element to append the video - // temporarily, so we can put the plyr controls there. This is - // required because controls have to fill the entire space - const plyr = new Plyr(content.videoElement, { + // Create the plyr instance + const opts: Plyr.Options = { iconUrl: plyrsvg, - quality: !qualityNums - ? undefined - : { - default: 0, - options: qualityNums, - forced: true, - onChange: (quality: number) => { - if (!qualityList || !content.videojs) return; - for (let i = 0; i < qualityList.length; ++i) { - const { width, height } = qualityList[i]; - const pixels = Math.min(width, height); - qualityList[i].enabled = pixels === quality || !quality; - } - }, - }, + blankVideo: "", i18n: { qualityLabel: { 0: t("memories", "Auto"), @@ -298,7 +282,25 @@ class VideoContentSetup { enabled: true, container: ".pswp__item", }, - }); + }; + + if (qualityNums) { + opts.quality = { + default: 0, + options: qualityNums, + forced: true, + onChange: (quality: number) => { + if (!qualityList || !content.videojs) return; + for (let i = 0; i < qualityList.length; ++i) { + const { width, height } = qualityList[i]; + const pixels = Math.min(width, height); + qualityList[i].enabled = pixels === quality || !quality; + } + }, + }; + } + + const plyr = new Plyr(content.videoElement, opts); plyr.elements.container.style.height = "100%"; plyr.elements.container.style.width = "100%"; plyr.elements.container From 478f884a213f2dcbc62c58aa5a165a04729d786a Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 21:43:43 -0800 Subject: [PATCH 110/163] Fix plyr color --- src/App.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/App.vue b/src/App.vue index da1cc027..9d1c0731 100644 --- a/src/App.vue +++ b/src/App.vue @@ -199,6 +199,7 @@ export default class App extends Mixins(GlobalMixin, UserConfig) { const colorPrimary = getComputedStyle(root).getPropertyValue("--color-primary"); root.style.setProperty("--color-primary-select-light", `${colorPrimary}40`); + root.style.setProperty("--plyr-color-main", colorPrimary); // Register sidebar metadata tab const OCA = globalThis.OCA; From 8a0da692766b6386eebe9b5a138b2802eb277dca Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 21:45:18 -0800 Subject: [PATCH 111/163] plyr: fix seeking --- src/components/PsVideo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 5fd2a7db..740828a9 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -78,7 +78,7 @@ class VideoContentSetup { origEvent.clientX, origEvent.clientY ); - if (elems.some((el) => el.classList.contains("vjs-control-bar"))) { + if (elems.some((el) => el.classList.contains("plyr__controls"))) { e.preventDefault(); return; } From ba00ddd9c2a9159e9a49582595727847ebe98f8f Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 21:54:03 -0800 Subject: [PATCH 112/163] plyr: hide volume on mobile --- src/components/Viewer.vue | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index 834dbcc4..3b268ddb 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -843,6 +843,13 @@ export default class Viewer extends Mixins(GlobalMixin) { display: none; } +:deep .plyr__volume { + // Cannot be vertical yet :( + @media (max-width: 768px) { + display: none; + } +} + :deep .pswp { .pswp__zoom-wrap { width: 100%; From 09c62f32b95f49bae84dfb3024b2daf5b9801925 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 22:58:59 -0800 Subject: [PATCH 113/163] Fix rotation and controls on ios --- src/components/PsVideo.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 740828a9..6cbddbb5 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -209,11 +209,9 @@ class VideoContentSetup { }, 200); let canPlay = false; - content.videojs.on("canplay", () => { - canPlay = true; - this.updateRotation(content); - }); content.videojs.on("loadedmetadata", () => { + canPlay = true; + this.updateRotation(content); // also gets the correct video elem as a side effect this.initPlyr(content); }); @@ -238,8 +236,8 @@ class VideoContentSetup { content.videojs.dispose(); content.videojs = null; - content.plyr.elements.container.remove(); - content.plyr.destroy(); + content.plyr?.elements?.container?.remove(); + content.plyr?.destroy(); content.plyr = null; const elem: HTMLDivElement = content.element; @@ -321,9 +319,10 @@ class VideoContentSetup { } updateRotation(content, val?: number) { - if (!content.videojs || !content.videoElement) { - return; - } + if (!content.videojs) return; + + content.videoElement = content.videojs.el()?.querySelector("video"); + if (!content.videoElement) return; const rotation = val ?? Number(content.data.exif?.Rotation); const shouldRotate = content.videojs?.src().includes("m3u8"); From 6eb4327730802b9315c487b292ab1e7ff86941dc Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 23:06:40 -0800 Subject: [PATCH 114/163] Bump up go-vod --- scripts/get-exiftool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get-exiftool.sh b/scripts/get-exiftool.sh index d3633567..af50615c 100755 --- a/scripts/get-exiftool.sh +++ b/scripts/get-exiftool.sh @@ -17,7 +17,7 @@ mv "exiftool-$exifver" exiftool rm -rf *.zip exiftool/t exiftool/html chmod 755 exiftool/exiftool -govod="0.0.8" +govod="0.0.9" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64" chmod 755 go-vod-* From 0bc61df92240958bee557a2ce25cd6e4e0742c99 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 23:07:34 -0800 Subject: [PATCH 115/163] release: v4.7.0 --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index a68ba3ae..e875b863 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -33,7 +33,7 @@ Memories is a *batteries-included* photo management solution for Nextcloud with 1. Run `php ./occ memories:index` to generate metadata indices for existing photos. 1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos. ]]> - 4.7.0-beta.5 + 4.7.0 agpl Varun Patil Memories From eb9aed441b0e32ada256baabea906f8bd18a7c4f Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 23:35:01 -0800 Subject: [PATCH 116/163] Make video fill up space --- src/components/Viewer.vue | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index 3b268ddb..df06ffd4 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -534,10 +534,21 @@ export default class Viewer extends Mixins(GlobalMixin) { previewUrl = generateUrl(getDownloadLink(photo)); } + // Get height and width + let w = photo.w; + let h = photo.h; + + if (isvideo && w && h) { + // For videos, make sure the screen is filled up, + // by scaling up the video by a maximum of 4x + w *= 4; + h *= 4; + } + return { src: previewUrl, - width: photo.w || undefined, - height: photo.h || undefined, + width: w || undefined, + height: h || undefined, thumbCropped: true, photo: photo, type: isvideo ? "video" : "image", From ed898cdd8d84e2b42353b35eedb669650a8033a5 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sun, 13 Nov 2022 23:48:44 -0800 Subject: [PATCH 117/163] Update sponsorship in readme --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c17e36fc..0ee99595 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Demo](https://img.shields.io/badge/demo-online-blue)](https://memories-demo.radialapps.com/apps/memories/) [![Gitter](https://img.shields.io/gitter/room/pulsejet/memories)](https://gitter.im/pulsejet/memories) [![GitHub issues](https://img.shields.io/github/issues/pulsejet/memories)](https://github.com/pulsejet/memories/issues) +![GitHub Sponsor](https://img.shields.io/github/sponsors/pulsejet?logo=GitHub) Memories is a _batteries-included_ photo management solution for Nextcloud with advanced features including: @@ -42,12 +43,12 @@ Memories is a _batteries-included_ photo management solution for Nextcloud with 1. ✅ Enable the app through the app management of your Nextcloud. 1. ⚒️ (Strongly recommended) use VS Code and install Vetur and Prettier. -## How to support development +## Support the project -1. **🌟 Star this repository**: This is the easiest way to support the project and costs nothing. -1. **🪲 Report bugs**: If you find a bug, please report it on the issue tracker. -1. **📝 Contribute**: If you want to contribute, please read file / comment on an issue and ask for guidance. -1. **🪙 Sponsorship**: If you want to support the project financially, you can donate to the project on [GitHub](https://github.com/sponsors/pulsejet). +1. **🌟 Star this repository**: This is the easiest way to support Memories and costs nothing. +1. **🪲 Report bugs**: Report any bugs you find on the issue tracker. +1. **📝 Contribute**: Read and file or comment on an issue and ask for guidance. +1. **🪙 Sponsorship**: You can support the project financially at [GitHub Sponsors](https://github.com/sponsors/pulsejet). ## Special Thanks From bd8a8c15797f24ed868afd0afa2d69c44b435a7b Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 00:03:46 -0800 Subject: [PATCH 118/163] readme: thank you @mpodshivalin! --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0ee99595..c7febf29 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ Memories is a _batteries-included_ photo management solution for Nextcloud with 1. **📝 Contribute**: Read and file or comment on an issue and ask for guidance. 1. **🪙 Sponsorship**: You can support the project financially at [GitHub Sponsors](https://github.com/sponsors/pulsejet). +A shout out to the current and past financial backers of Memories! See the sponsors page for a full list. + +[](https://github.com/mpodshivalin) + ## Special Thanks Nextcloud team. A lot of this work is based on [Photos](https://github.com/nextcloud/photos). From 649c0659c73cdf709bce36f2a30ec72ace970225 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 00:05:29 -0800 Subject: [PATCH 119/163] readme: make sponsors badge a link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7febf29..0cc2aa36 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Demo](https://img.shields.io/badge/demo-online-blue)](https://memories-demo.radialapps.com/apps/memories/) [![Gitter](https://img.shields.io/gitter/room/pulsejet/memories)](https://gitter.im/pulsejet/memories) [![GitHub issues](https://img.shields.io/github/issues/pulsejet/memories)](https://github.com/pulsejet/memories/issues) -![GitHub Sponsor](https://img.shields.io/github/sponsors/pulsejet?logo=GitHub) +[![GitHub Sponsor](https://img.shields.io/github/sponsors/pulsejet?logo=GitHub)](https://github.com/sponsors/pulsejet) Memories is a _batteries-included_ photo management solution for Nextcloud with advanced features including: From 39daae1cb765dc9ed26bdace3aa22351d168121a Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 00:24:23 -0800 Subject: [PATCH 120/163] Make sure transcoder is executable (fix #193) --- lib/Controller/VideoController.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Controller/VideoController.php b/lib/Controller/VideoController.php index 66f14345..bf8d531f 100644 --- a/lib/Controller/VideoController.php +++ b/lib/Controller/VideoController.php @@ -90,6 +90,11 @@ class VideoController extends ApiBase return new JSONResponse(['message' => 'Transcoder not configured'], Http::STATUS_INTERNAL_SERVER_ERROR); } + // Make transcoder executable + if (!is_executable($transcoder)) { + chmod($transcoder, 0755); + } + // Check for environment variables $vaapi = $this->config->getSystemValue('memories.qsv', false); $env = ''; From d9e3d3e0c1c117daf1dea66a285642f404b521c4 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 01:02:14 -0800 Subject: [PATCH 121/163] Update go-vod --- scripts/get-exiftool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get-exiftool.sh b/scripts/get-exiftool.sh index af50615c..980f0095 100755 --- a/scripts/get-exiftool.sh +++ b/scripts/get-exiftool.sh @@ -17,7 +17,7 @@ mv "exiftool-$exifver" exiftool rm -rf *.zip exiftool/t exiftool/html chmod 755 exiftool/exiftool -govod="0.0.9" +govod="0.0.10" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64" chmod 755 go-vod-* From 103cce1a353b3569a1b956ba77da8a11ef29c51a Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 01:10:43 -0800 Subject: [PATCH 122/163] video: fix initial quality switch --- src/components/PsVideo.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 6cbddbb5..1d35a678 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -215,6 +215,12 @@ class VideoContentSetup { this.initPlyr(content); }); + content.videojs.qualityLevels()?.on("addqualitylevel", (e) => { + window.setTimeout(() => { + this.initPlyr(content); + }, 0); + }); + // Get correct orientation axios .get( @@ -251,6 +257,9 @@ class VideoContentSetup { initPlyr(content: any) { if (content.plyr) return; + content.videoElement = content.videojs?.el()?.querySelector("video"); + if (!content.videoElement) return; + // Retain original parent for video element const origParent = content.videoElement.parentElement; From c237d27e8226248ea44ae5b5f7541a8471e1cfab Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 01:26:21 -0800 Subject: [PATCH 123/163] Bump go-vod --- scripts/get-exiftool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get-exiftool.sh b/scripts/get-exiftool.sh index 980f0095..6f78f136 100755 --- a/scripts/get-exiftool.sh +++ b/scripts/get-exiftool.sh @@ -17,7 +17,7 @@ mv "exiftool-$exifver" exiftool rm -rf *.zip exiftool/t exiftool/html chmod 755 exiftool/exiftool -govod="0.0.10" +govod="0.0.11" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64" chmod 755 go-vod-* From 36a809149b696e4362902815a1853fbb7cad82d7 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 01:27:04 -0800 Subject: [PATCH 124/163] release: v4.7.1 --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index e875b863..e5282414 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -33,7 +33,7 @@ Memories is a *batteries-included* photo management solution for Nextcloud with 1. Run `php ./occ memories:index` to generate metadata indices for existing photos. 1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos. ]]> - 4.7.0 + 4.7.1 agpl Varun Patil Memories From 63990e524043b5048abcf2ec421b97322c038491 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Mon, 14 Nov 2022 10:39:02 +0000 Subject: [PATCH 125/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/bg.js | 1 + l10n/bg.json | 1 + l10n/ca.js | 3 ++- l10n/ca.json | 3 ++- l10n/cs.js | 1 + l10n/cs.json | 1 + l10n/cy_GB.js | 3 ++- l10n/cy_GB.json | 3 ++- l10n/da.js | 1 + l10n/da.json | 1 + l10n/de.js | 1 + l10n/de.json | 1 + l10n/de_DE.js | 1 + l10n/de_DE.json | 1 + l10n/el.js | 3 ++- l10n/el.json | 3 ++- l10n/eo.js | 3 ++- l10n/eo.json | 3 ++- l10n/es.js | 1 + l10n/es.json | 1 + l10n/es_GT.js | 3 ++- l10n/es_GT.json | 3 ++- l10n/eu.js | 1 + l10n/eu.json | 1 + l10n/fa.js | 3 ++- l10n/fa.json | 3 ++- l10n/fi.js | 1 + l10n/fi.json | 1 + l10n/fr.js | 1 + l10n/fr.json | 1 + l10n/gl.js | 3 ++- l10n/gl.json | 3 ++- l10n/he.js | 3 ++- l10n/he.json | 3 ++- l10n/hr.js | 3 ++- l10n/hr.json | 3 ++- l10n/hu.js | 2 ++ l10n/hu.json | 2 ++ l10n/is.js | 3 ++- l10n/is.json | 3 ++- l10n/it.js | 3 ++- l10n/it.json | 3 ++- l10n/ja.js | 3 ++- l10n/ja.json | 3 ++- l10n/ko.js | 3 ++- l10n/ko.json | 3 ++- l10n/lt_LT.js | 1 + l10n/lt_LT.json | 1 + l10n/lv.js | 1 + l10n/lv.json | 1 + l10n/mk.js | 1 + l10n/mk.json | 1 + l10n/nb.js | 3 ++- l10n/nb.json | 3 ++- l10n/nl.js | 3 ++- l10n/nl.json | 3 ++- l10n/pl.js | 1 + l10n/pl.json | 1 + l10n/pt_BR.js | 1 + l10n/pt_BR.json | 1 + l10n/pt_PT.js | 1 + l10n/pt_PT.json | 1 + l10n/ro.js | 3 ++- l10n/ro.json | 3 ++- l10n/ru.js | 1 + l10n/ru.json | 1 + l10n/sc.js | 3 ++- l10n/sc.json | 3 ++- l10n/sk.js | 1 + l10n/sk.json | 1 + l10n/sl.js | 3 ++- l10n/sl.json | 3 ++- l10n/sr.js | 3 ++- l10n/sr.json | 3 ++- l10n/sv.js | 1 + l10n/sv.json | 1 + l10n/tr.js | 2 ++ l10n/tr.json | 2 ++ l10n/uk.js | 1 + l10n/uk.json | 1 + l10n/vi.js | 3 ++- l10n/vi.json | 3 ++- l10n/zh_CN.js | 1 + l10n/zh_CN.json | 1 + l10n/zh_HK.js | 1 + l10n/zh_HK.json | 1 + l10n/zh_TW.js | 4 ++++ l10n/zh_TW.json | 4 ++++ 88 files changed, 138 insertions(+), 40 deletions(-) diff --git a/l10n/bg.js b/l10n/bg.js index 42f08eb4..996ca056 100644 --- a/l10n/bg.js +++ b/l10n/bg.js @@ -217,6 +217,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Обърнете внимание, че избраната област за изрязване е по-ниска от приложеното преоразмеряване, което може да доведе до влошаване на качеството", "Actual size (100%)" : "Действителен размер (100%)", "Fit size" : "Подходящ размер", + "Auto" : "Автоматично", "Shared Folder" : "Споделена папка", "Failed to create {albumName}." : "Неуспешно създаване на {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Неуспешно преименуване от {currentAlbumName} на {newAlbumName}.", diff --git a/l10n/bg.json b/l10n/bg.json index 628e79d0..d97c266f 100644 --- a/l10n/bg.json +++ b/l10n/bg.json @@ -215,6 +215,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Обърнете внимание, че избраната област за изрязване е по-ниска от приложеното преоразмеряване, което може да доведе до влошаване на качеството", "Actual size (100%)" : "Действителен размер (100%)", "Fit size" : "Подходящ размер", + "Auto" : "Автоматично", "Shared Folder" : "Споделена папка", "Failed to create {albumName}." : "Неуспешно създаване на {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Неуспешно преименуване от {currentAlbumName} на {newAlbumName}.", diff --git a/l10n/ca.js b/l10n/ca.js index c2418d1a..65d42078 100644 --- a/l10n/ca.js +++ b/l10n/ca.js @@ -121,6 +121,7 @@ OC.L10N.register( "Saved image size (width x height)" : "Mida de la imatge desada (amplada x alçada)", "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Tingueu en compte que l'àrea de retall seleccionada és inferior al canvi de mida aplicat, cosa que pot provocar una disminució de la qualitat", "Actual size (100%)" : "Mida real (100%)", - "Fit size" : "Talla ajustada" + "Fit size" : "Talla ajustada", + "Auto" : "Automàtic" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/ca.json b/l10n/ca.json index dfb91d27..6aa4f2c2 100644 --- a/l10n/ca.json +++ b/l10n/ca.json @@ -119,6 +119,7 @@ "Saved image size (width x height)" : "Mida de la imatge desada (amplada x alçada)", "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Tingueu en compte que l'àrea de retall seleccionada és inferior al canvi de mida aplicat, cosa que pot provocar una disminució de la qualitat", "Actual size (100%)" : "Mida real (100%)", - "Fit size" : "Talla ajustada" + "Fit size" : "Talla ajustada", + "Auto" : "Automàtic" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/cs.js b/l10n/cs.js index e2ac7f0e..3a6c5c72 100644 --- a/l10n/cs.js +++ b/l10n/cs.js @@ -221,6 +221,7 @@ OC.L10N.register( "Actual size (100%)" : "Skutečná velikost (100%)", "Fit size" : "Přizpůsobit velikost", "Transcoding failed." : "Překódování se nezdařilo.", + "Auto" : "Automaticky", "Shared Folder" : "Sdílená složka", "Failed to create {albumName}." : "Nepodařilo se vytvořit {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Nepodařilo přejmenovat {currentAlbumName} to {newAlbumName}.", diff --git a/l10n/cs.json b/l10n/cs.json index e4f506b7..63794960 100644 --- a/l10n/cs.json +++ b/l10n/cs.json @@ -219,6 +219,7 @@ "Actual size (100%)" : "Skutečná velikost (100%)", "Fit size" : "Přizpůsobit velikost", "Transcoding failed." : "Překódování se nezdařilo.", + "Auto" : "Automaticky", "Shared Folder" : "Sdílená složka", "Failed to create {albumName}." : "Nepodařilo se vytvořit {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Nepodařilo přejmenovat {currentAlbumName} to {newAlbumName}.", diff --git a/l10n/cy_GB.js b/l10n/cy_GB.js index 92805fea..2e81565b 100644 --- a/l10n/cy_GB.js +++ b/l10n/cy_GB.js @@ -25,6 +25,7 @@ OC.L10N.register( "Refresh" : "Ail-lwytho", "Undo" : "Dadwneud", "Custom" : "Cyfaddas", - "Size" : "Maint" + "Size" : "Maint", + "Auto" : "Awto" }, "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"); diff --git a/l10n/cy_GB.json b/l10n/cy_GB.json index 715bffd2..503832cd 100644 --- a/l10n/cy_GB.json +++ b/l10n/cy_GB.json @@ -23,6 +23,7 @@ "Refresh" : "Ail-lwytho", "Undo" : "Dadwneud", "Custom" : "Cyfaddas", - "Size" : "Maint" + "Size" : "Maint", + "Auto" : "Awto" },"pluralForm" :"nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;" } \ No newline at end of file diff --git a/l10n/da.js b/l10n/da.js index af60c433..f3a40e01 100644 --- a/l10n/da.js +++ b/l10n/da.js @@ -66,6 +66,7 @@ OC.L10N.register( "Position" : "Position", "Extension" : "Filtype", "Name is required." : "Navn er påkrævet.", + "Auto" : "Auto", "Failed to delete files." : "Kunne ikke slette filer.", "Failed to delete {fileName}." : "Kunne ikke slette {fileName}.", "Failed to favorite files." : "Kunne ikke vælge favorit filer.", diff --git a/l10n/da.json b/l10n/da.json index 8ee94fcf..b63c3b91 100644 --- a/l10n/da.json +++ b/l10n/da.json @@ -64,6 +64,7 @@ "Position" : "Position", "Extension" : "Filtype", "Name is required." : "Navn er påkrævet.", + "Auto" : "Auto", "Failed to delete files." : "Kunne ikke slette filer.", "Failed to delete {fileName}." : "Kunne ikke slette {fileName}.", "Failed to favorite files." : "Kunne ikke vælge favorit filer.", diff --git a/l10n/de.js b/l10n/de.js index 5b691a8e..3369af5f 100644 --- a/l10n/de.js +++ b/l10n/de.js @@ -196,6 +196,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Beachte, dass der ausgewählte Zuschneidebereich kleiner ist als die angewendete Größenänderung, was zu Qualitätseinbußen führen kann.", "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", + "Auto" : "Automatisch", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", "General Failure" : "Allgemeiner Fehler", diff --git a/l10n/de.json b/l10n/de.json index 4b59a866..2548d1f4 100644 --- a/l10n/de.json +++ b/l10n/de.json @@ -194,6 +194,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Beachte, dass der ausgewählte Zuschneidebereich kleiner ist als die angewendete Größenänderung, was zu Qualitätseinbußen führen kann.", "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", + "Auto" : "Automatisch", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", "General Failure" : "Allgemeiner Fehler", diff --git a/l10n/de_DE.js b/l10n/de_DE.js index 9bb6cb4a..32d6ddca 100644 --- a/l10n/de_DE.js +++ b/l10n/de_DE.js @@ -221,6 +221,7 @@ OC.L10N.register( "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", "Transcoding failed." : "Transkodierung fehlgeschlagen.", + "Auto" : "Automatisch", "Shared Folder" : "Geteilter Ordner", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", diff --git a/l10n/de_DE.json b/l10n/de_DE.json index b4a902b8..e9dfac14 100644 --- a/l10n/de_DE.json +++ b/l10n/de_DE.json @@ -219,6 +219,7 @@ "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", "Transcoding failed." : "Transkodierung fehlgeschlagen.", + "Auto" : "Automatisch", "Shared Folder" : "Geteilter Ordner", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", diff --git a/l10n/el.js b/l10n/el.js index c24d6f3a..336c7cce 100644 --- a/l10n/el.js +++ b/l10n/el.js @@ -50,6 +50,7 @@ OC.L10N.register( "Position" : "Θέση", "Extension" : "Επέκταση", "Name is required." : "Απαιτείται όνομα.", - "Quality" : "Ποιότητα" + "Quality" : "Ποιότητα", + "Auto" : "Αυτόματα" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/el.json b/l10n/el.json index ae6e143f..04095a2a 100644 --- a/l10n/el.json +++ b/l10n/el.json @@ -48,6 +48,7 @@ "Position" : "Θέση", "Extension" : "Επέκταση", "Name is required." : "Απαιτείται όνομα.", - "Quality" : "Ποιότητα" + "Quality" : "Ποιότητα", + "Auto" : "Αυτόματα" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/eo.js b/l10n/eo.js index 2ce10909..d66be403 100644 --- a/l10n/eo.js +++ b/l10n/eo.js @@ -36,6 +36,7 @@ OC.L10N.register( "Text" : "Teksto", "Size" : "Grando", "Position" : "Loko", - "Extension" : "Dosiersufikso" + "Extension" : "Dosiersufikso", + "Auto" : "Aŭtomate" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/eo.json b/l10n/eo.json index 2952bd62..f7ddbb26 100644 --- a/l10n/eo.json +++ b/l10n/eo.json @@ -34,6 +34,7 @@ "Text" : "Teksto", "Size" : "Grando", "Position" : "Loko", - "Extension" : "Dosiersufikso" + "Extension" : "Dosiersufikso", + "Auto" : "Aŭtomate" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/es.js b/l10n/es.js index 690f4197..0d35a957 100644 --- a/l10n/es.js +++ b/l10n/es.js @@ -218,6 +218,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Tenga en cuenta que el área a recortar es menor al redimensionamiento aplicado lo que puede causar pérdida de calidad", "Actual size (100%)" : "Tamaño actual (100%)", "Fit size" : "Ajustar tamaño", + "Auto" : "Auto", "Shared Folder" : "Carpeta compartida", "Failed to create {albumName}." : "Fallo al crear {albumName}", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Fallo al renombrar {currentAlbumName} a {newAlbumName}.", diff --git a/l10n/es.json b/l10n/es.json index 314546c8..b85bfb00 100644 --- a/l10n/es.json +++ b/l10n/es.json @@ -216,6 +216,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Tenga en cuenta que el área a recortar es menor al redimensionamiento aplicado lo que puede causar pérdida de calidad", "Actual size (100%)" : "Tamaño actual (100%)", "Fit size" : "Ajustar tamaño", + "Auto" : "Auto", "Shared Folder" : "Carpeta compartida", "Failed to create {albumName}." : "Fallo al crear {albumName}", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Fallo al renombrar {currentAlbumName} a {newAlbumName}.", diff --git a/l10n/es_GT.js b/l10n/es_GT.js index 3a35c0f8..eb02434f 100644 --- a/l10n/es_GT.js +++ b/l10n/es_GT.js @@ -34,6 +34,7 @@ OC.L10N.register( "Value" : "Valor", "Text" : "Texto", "Size" : "Tamaño", - "Position" : "Posición" + "Position" : "Posición", + "Auto" : "Auto" }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/l10n/es_GT.json b/l10n/es_GT.json index f61b3538..b6b8b812 100644 --- a/l10n/es_GT.json +++ b/l10n/es_GT.json @@ -32,6 +32,7 @@ "Value" : "Valor", "Text" : "Texto", "Size" : "Tamaño", - "Position" : "Posición" + "Position" : "Posición", + "Auto" : "Auto" },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" } \ No newline at end of file diff --git a/l10n/eu.js b/l10n/eu.js index db4b7dca..880b196a 100644 --- a/l10n/eu.js +++ b/l10n/eu.js @@ -176,6 +176,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Kontuan izan hautatutako mozte-eremua aplikatutako tamaina baino txikiagoa dela eta horrek kalitatea gutxitzea eragin dezakeela", "Actual size (100%)" : "Benetako tamaina (% 100)", "Fit size" : "Egokitu tamaina", + "Auto" : "Auto", "Failed to create {albumName}." : "Ezin izan da {albumName} sortu.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Ezin izan da {currentAlbumName} berrizendatu {newAlbumName} gisa.", "General Failure" : "Hutsegite orokorra", diff --git a/l10n/eu.json b/l10n/eu.json index b69619e4..fb2488de 100644 --- a/l10n/eu.json +++ b/l10n/eu.json @@ -174,6 +174,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Kontuan izan hautatutako mozte-eremua aplikatutako tamaina baino txikiagoa dela eta horrek kalitatea gutxitzea eragin dezakeela", "Actual size (100%)" : "Benetako tamaina (% 100)", "Fit size" : "Egokitu tamaina", + "Auto" : "Auto", "Failed to create {albumName}." : "Ezin izan da {albumName} sortu.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Ezin izan da {currentAlbumName} berrizendatu {newAlbumName} gisa.", "General Failure" : "Hutsegite orokorra", diff --git a/l10n/fa.js b/l10n/fa.js index bb077fd4..0a25b373 100644 --- a/l10n/fa.js +++ b/l10n/fa.js @@ -37,6 +37,7 @@ OC.L10N.register( "Value" : "مقدار", "Text" : "متن", "Size" : "اندازه", - "Extension" : "گسترش" + "Extension" : "گسترش", + "Auto" : "خودکار" }, "nplurals=2; plural=(n > 1);"); diff --git a/l10n/fa.json b/l10n/fa.json index 1ee4ebc7..328b30a8 100644 --- a/l10n/fa.json +++ b/l10n/fa.json @@ -35,6 +35,7 @@ "Value" : "مقدار", "Text" : "متن", "Size" : "اندازه", - "Extension" : "گسترش" + "Extension" : "گسترش", + "Auto" : "خودکار" },"pluralForm" :"nplurals=2; plural=(n > 1);" } \ No newline at end of file diff --git a/l10n/fi.js b/l10n/fi.js index 18e07b66..0d5e545a 100644 --- a/l10n/fi.js +++ b/l10n/fi.js @@ -158,6 +158,7 @@ OC.L10N.register( "Quality" : "Laatu", "Actual size (100%)" : "Todellinen koko (100 %)", "Fit size" : "Sovita koko", + "Auto" : "Automaattinen", "Shared Folder" : "Jaa kansio", "Failed to create {albumName}." : "Albumin {albumName} luominen epäonnistui.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Albumin {currentAlbumName} nimen muuttaminen muotoon {newAlbumName} epäonnistui.", diff --git a/l10n/fi.json b/l10n/fi.json index d6b14a80..dbb63006 100644 --- a/l10n/fi.json +++ b/l10n/fi.json @@ -156,6 +156,7 @@ "Quality" : "Laatu", "Actual size (100%)" : "Todellinen koko (100 %)", "Fit size" : "Sovita koko", + "Auto" : "Automaattinen", "Shared Folder" : "Jaa kansio", "Failed to create {albumName}." : "Albumin {albumName} luominen epäonnistui.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Albumin {currentAlbumName} nimen muuttaminen muotoon {newAlbumName} epäonnistui.", diff --git a/l10n/fr.js b/l10n/fr.js index e15a9c91..fa6dc40a 100644 --- a/l10n/fr.js +++ b/l10n/fr.js @@ -182,6 +182,7 @@ OC.L10N.register( "Actual size (100%)" : "Taille actuelle (100%)", "Fit size" : "Adapter à la taille", "Transcoding failed." : "Échec du transcodage.", + "Auto" : "Auto", "Failed to create {albumName}." : "Échec de la création de {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Échec du renommage de {currentAlbumName} en {newAlbumName}.", "General Failure" : "Échec général", diff --git a/l10n/fr.json b/l10n/fr.json index 09e9e8d8..d0be5c33 100644 --- a/l10n/fr.json +++ b/l10n/fr.json @@ -180,6 +180,7 @@ "Actual size (100%)" : "Taille actuelle (100%)", "Fit size" : "Adapter à la taille", "Transcoding failed." : "Échec du transcodage.", + "Auto" : "Auto", "Failed to create {albumName}." : "Échec de la création de {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Échec du renommage de {currentAlbumName} en {newAlbumName}.", "General Failure" : "Échec général", diff --git a/l10n/gl.js b/l10n/gl.js index 27cb2961..4d9591c4 100644 --- a/l10n/gl.js +++ b/l10n/gl.js @@ -48,6 +48,7 @@ OC.L10N.register( "Position" : "Posicion", "Extension" : "Extensión", "Name is required." : "É obrigatorio o nome.", - "Quality" : "Calidade" + "Quality" : "Calidade", + "Auto" : "Automático" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/gl.json b/l10n/gl.json index 440ff7c4..b4ad77c8 100644 --- a/l10n/gl.json +++ b/l10n/gl.json @@ -46,6 +46,7 @@ "Position" : "Posicion", "Extension" : "Extensión", "Name is required." : "É obrigatorio o nome.", - "Quality" : "Calidade" + "Quality" : "Calidade", + "Auto" : "Automático" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/he.js b/l10n/he.js index 7e758f48..d23dd986 100644 --- a/l10n/he.js +++ b/l10n/he.js @@ -45,6 +45,7 @@ OC.L10N.register( "Position" : "מיקום", "Extension" : "הרחבה", "Name is required." : "נדרש שם.", - "Quality" : "איכות" + "Quality" : "איכות", + "Auto" : "אוטומטי" }, "nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;"); diff --git a/l10n/he.json b/l10n/he.json index 3fadedcb..f093d213 100644 --- a/l10n/he.json +++ b/l10n/he.json @@ -43,6 +43,7 @@ "Position" : "מיקום", "Extension" : "הרחבה", "Name is required." : "נדרש שם.", - "Quality" : "איכות" + "Quality" : "איכות", + "Auto" : "אוטומטי" },"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;" } \ No newline at end of file diff --git a/l10n/hr.js b/l10n/hr.js index 6eb70fc9..6d0a94f8 100644 --- a/l10n/hr.js +++ b/l10n/hr.js @@ -48,6 +48,7 @@ OC.L10N.register( "Position" : "Položaj", "Extension" : "Proširenje", "Name is required." : "Ime je obavezno.", - "Quality" : "Kvaliteta" + "Quality" : "Kvaliteta", + "Auto" : "Auto" }, "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"); diff --git a/l10n/hr.json b/l10n/hr.json index 040aebfe..43f8a950 100644 --- a/l10n/hr.json +++ b/l10n/hr.json @@ -46,6 +46,7 @@ "Position" : "Položaj", "Extension" : "Proširenje", "Name is required." : "Ime je obavezno.", - "Quality" : "Kvaliteta" + "Quality" : "Kvaliteta", + "Auto" : "Auto" },"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" } \ No newline at end of file diff --git a/l10n/hu.js b/l10n/hu.js index 44466a51..41c6cc3f 100644 --- a/l10n/hu.js +++ b/l10n/hu.js @@ -15,6 +15,7 @@ OC.L10N.register( "Tags" : "Címkék", "Maps" : "Térképek", "EXIF" : "EXIF", + "Error saving image" : "Hiba a kép mentése során", "Unsaved changes" : "Mentetlen változtatások", "Drop changes" : "Változtatások elvetése", "Edit" : "Szerkesztés", @@ -171,6 +172,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Vegye figyelembe, hogy a kijelölt levágási terület kisebb mint az alkalmazott átméretezés, amely minőségcsökkenést okozhat", "Actual size (100%)" : "Tényleges méret (100%)", "Fit size" : "Illeszkedő méret", + "Auto" : "Automatikus", "Failed to create {albumName}." : "A(z) {albumName} létrehozása sikertelen.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "A(z) {currentAlbumName} átnevezése a következőre sikertelen: {newAlbumName}.", "Failed to delete files." : "A fájlok törlése sikertelen.", diff --git a/l10n/hu.json b/l10n/hu.json index 1b563d02..cd01eaa7 100644 --- a/l10n/hu.json +++ b/l10n/hu.json @@ -13,6 +13,7 @@ "Tags" : "Címkék", "Maps" : "Térképek", "EXIF" : "EXIF", + "Error saving image" : "Hiba a kép mentése során", "Unsaved changes" : "Mentetlen változtatások", "Drop changes" : "Változtatások elvetése", "Edit" : "Szerkesztés", @@ -169,6 +170,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Vegye figyelembe, hogy a kijelölt levágási terület kisebb mint az alkalmazott átméretezés, amely minőségcsökkenést okozhat", "Actual size (100%)" : "Tényleges méret (100%)", "Fit size" : "Illeszkedő méret", + "Auto" : "Automatikus", "Failed to create {albumName}." : "A(z) {albumName} létrehozása sikertelen.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "A(z) {currentAlbumName} átnevezése a következőre sikertelen: {newAlbumName}.", "Failed to delete files." : "A fájlok törlése sikertelen.", diff --git a/l10n/is.js b/l10n/is.js index a961b29a..87bfe66d 100644 --- a/l10n/is.js +++ b/l10n/is.js @@ -48,6 +48,7 @@ OC.L10N.register( "Position" : "Staða", "Extension" : "Skráarending", "Name is required." : "Nafn er nauðsynlegt.", - "Quality" : "Quality" + "Quality" : "Quality", + "Auto" : "Sjálfvirkt" }, "nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"); diff --git a/l10n/is.json b/l10n/is.json index cf39a1b5..093244b0 100644 --- a/l10n/is.json +++ b/l10n/is.json @@ -46,6 +46,7 @@ "Position" : "Staða", "Extension" : "Skráarending", "Name is required." : "Nafn er nauðsynlegt.", - "Quality" : "Quality" + "Quality" : "Quality", + "Auto" : "Sjálfvirkt" },"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);" } \ No newline at end of file diff --git a/l10n/it.js b/l10n/it.js index 53e4808e..033b781a 100644 --- a/l10n/it.js +++ b/l10n/it.js @@ -74,6 +74,7 @@ OC.L10N.register( "Position" : "Posizione", "Extension" : "Estensione", "Name is required." : "Il nome è richiesto.", - "Quality" : "Qualità" + "Quality" : "Qualità", + "Auto" : "Automatico" }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/l10n/it.json b/l10n/it.json index 80770135..cced2d39 100644 --- a/l10n/it.json +++ b/l10n/it.json @@ -72,6 +72,7 @@ "Position" : "Posizione", "Extension" : "Estensione", "Name is required." : "Il nome è richiesto.", - "Quality" : "Qualità" + "Quality" : "Qualità", + "Auto" : "Automatico" },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" } \ No newline at end of file diff --git a/l10n/ja.js b/l10n/ja.js index 027425b9..90aa8137 100644 --- a/l10n/ja.js +++ b/l10n/ja.js @@ -73,6 +73,7 @@ OC.L10N.register( "Position" : "位置", "Extension" : "拡張", "Name is required." : "名前は必須です。", - "Quality" : "品質" + "Quality" : "品質", + "Auto" : "自動" }, "nplurals=1; plural=0;"); diff --git a/l10n/ja.json b/l10n/ja.json index f8d063fe..bff1fd3b 100644 --- a/l10n/ja.json +++ b/l10n/ja.json @@ -71,6 +71,7 @@ "Position" : "位置", "Extension" : "拡張", "Name is required." : "名前は必須です。", - "Quality" : "品質" + "Quality" : "品質", + "Auto" : "自動" },"pluralForm" :"nplurals=1; plural=0;" } \ No newline at end of file diff --git a/l10n/ko.js b/l10n/ko.js index 0432c5ec..37b03299 100644 --- a/l10n/ko.js +++ b/l10n/ko.js @@ -43,6 +43,7 @@ OC.L10N.register( "Size" : "크기", "Position" : "위치", "Extension" : "확장자", - "Quality" : "품질" + "Quality" : "품질", + "Auto" : "자동" }, "nplurals=1; plural=0;"); diff --git a/l10n/ko.json b/l10n/ko.json index 6246ea75..783115f2 100644 --- a/l10n/ko.json +++ b/l10n/ko.json @@ -41,6 +41,7 @@ "Size" : "크기", "Position" : "위치", "Extension" : "확장자", - "Quality" : "품질" + "Quality" : "품질", + "Auto" : "자동" },"pluralForm" :"nplurals=1; plural=0;" } \ No newline at end of file diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js index 0575ce7e..668be953 100644 --- a/l10n/lt_LT.js +++ b/l10n/lt_LT.js @@ -121,6 +121,7 @@ OC.L10N.register( "Position" : "Vieta", "Name is required." : "Vardas yra būtinas.", "Quality" : "Kokybė", + "Auto" : "Automatiškai", "Failed to create {albumName}." : "Nepavyko sukurti {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Nepavyko pervadinti {currentAlbumName} į {newAlbumName}.", "General Failure" : "Bendrinė nesėkmė", diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json index c7091555..c52589fa 100644 --- a/l10n/lt_LT.json +++ b/l10n/lt_LT.json @@ -119,6 +119,7 @@ "Position" : "Vieta", "Name is required." : "Vardas yra būtinas.", "Quality" : "Kokybė", + "Auto" : "Automatiškai", "Failed to create {albumName}." : "Nepavyko sukurti {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Nepavyko pervadinti {currentAlbumName} į {newAlbumName}.", "General Failure" : "Bendrinė nesėkmė", diff --git a/l10n/lv.js b/l10n/lv.js index 567dbb0e..6ef91885 100644 --- a/l10n/lv.js +++ b/l10n/lv.js @@ -51,6 +51,7 @@ OC.L10N.register( "Saved image size (width x height)" : "Saglabātā attēla izmērs (platums x augstums)", "Actual size (100%)" : "Faktiskais izmērs (100%)", "Fit size" : "Atbilst izmēram", + "Auto" : "Automātiski", "Shared Folder" : "Koplietotā mape" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); diff --git a/l10n/lv.json b/l10n/lv.json index 361a0785..a7d13cb6 100644 --- a/l10n/lv.json +++ b/l10n/lv.json @@ -49,6 +49,7 @@ "Saved image size (width x height)" : "Saglabātā attēla izmērs (platums x augstums)", "Actual size (100%)" : "Faktiskais izmērs (100%)", "Fit size" : "Atbilst izmēram", + "Auto" : "Automātiski", "Shared Folder" : "Koplietotā mape" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" } \ No newline at end of file diff --git a/l10n/mk.js b/l10n/mk.js index 79992128..a6545c46 100644 --- a/l10n/mk.js +++ b/l10n/mk.js @@ -94,6 +94,7 @@ OC.L10N.register( "Quality" : "Квалитет", "Actual size (100%)" : "Актуелна големина (100%)", "Fit size" : "Соодветна големина", + "Auto" : "Автоматски", "Failed to create {albumName}." : "Неуспешно креирање {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Неуспешно преименување на {currentAlbumName} во {newAlbumName}.", "Failed to favorite {fileName}." : "Неуспешно додавање во омилени {fileName}." diff --git a/l10n/mk.json b/l10n/mk.json index 172da306..61a34703 100644 --- a/l10n/mk.json +++ b/l10n/mk.json @@ -92,6 +92,7 @@ "Quality" : "Квалитет", "Actual size (100%)" : "Актуелна големина (100%)", "Fit size" : "Соодветна големина", + "Auto" : "Автоматски", "Failed to create {albumName}." : "Неуспешно креирање {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Неуспешно преименување на {currentAlbumName} во {newAlbumName}.", "Failed to favorite {fileName}." : "Неуспешно додавање во омилени {fileName}." diff --git a/l10n/nb.js b/l10n/nb.js index d52db292..93c187d3 100644 --- a/l10n/nb.js +++ b/l10n/nb.js @@ -74,6 +74,7 @@ OC.L10N.register( "Save image as" : "Lagre bilde som", "Extension" : "Filetternavn", "Name is required." : "Navn er påkrevd.", - "Quality" : "Kvalitet" + "Quality" : "Kvalitet", + "Auto" : "Auto" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/nb.json b/l10n/nb.json index 6fb6ac3a..382d4ac3 100644 --- a/l10n/nb.json +++ b/l10n/nb.json @@ -72,6 +72,7 @@ "Save image as" : "Lagre bilde som", "Extension" : "Filetternavn", "Name is required." : "Navn er påkrevd.", - "Quality" : "Kvalitet" + "Quality" : "Kvalitet", + "Auto" : "Auto" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/nl.js b/l10n/nl.js index 5d5f721b..b52cc3b0 100644 --- a/l10n/nl.js +++ b/l10n/nl.js @@ -53,6 +53,7 @@ OC.L10N.register( "Position" : "Positie", "Extension" : "Extensie", "Name is required." : "Naam is verplicht.", - "Quality" : "Kwaliteit" + "Quality" : "Kwaliteit", + "Auto" : "Automatisch" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/nl.json b/l10n/nl.json index f09ec214..d600ac9f 100644 --- a/l10n/nl.json +++ b/l10n/nl.json @@ -51,6 +51,7 @@ "Position" : "Positie", "Extension" : "Extensie", "Name is required." : "Naam is verplicht.", - "Quality" : "Kwaliteit" + "Quality" : "Kwaliteit", + "Auto" : "Automatisch" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/pl.js b/l10n/pl.js index a90a5004..98539d30 100644 --- a/l10n/pl.js +++ b/l10n/pl.js @@ -169,6 +169,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Zwróć uwagę, że wybrany obszar kadrowania jest mniejszy niż zastosowana zmiana rozmiaru, co może spowodować spadek jakości", "Actual size (100%)" : "Rzeczywisty rozmiar (100%)", "Fit size" : "Dopasuj rozmiar", + "Auto" : "Automatycznie", "Failed to create {albumName}." : "Nie udało się utworzyć {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Nie udało się zmienić nazwy {currentAlbumName} na {newAlbumName}.", "General Failure" : "Ogólna awaria", diff --git a/l10n/pl.json b/l10n/pl.json index 80baa5a3..a243670e 100644 --- a/l10n/pl.json +++ b/l10n/pl.json @@ -167,6 +167,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Zwróć uwagę, że wybrany obszar kadrowania jest mniejszy niż zastosowana zmiana rozmiaru, co może spowodować spadek jakości", "Actual size (100%)" : "Rzeczywisty rozmiar (100%)", "Fit size" : "Dopasuj rozmiar", + "Auto" : "Automatycznie", "Failed to create {albumName}." : "Nie udało się utworzyć {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Nie udało się zmienić nazwy {currentAlbumName} na {newAlbumName}.", "General Failure" : "Ogólna awaria", diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js index 2fa2d688..b875cb43 100644 --- a/l10n/pt_BR.js +++ b/l10n/pt_BR.js @@ -200,6 +200,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Observe que a área de corte selecionada é menor que o redimensionamento aplicado, o que pode causar diminuição da qualidade", "Actual size (100%)" : "Tamanho real (100%)", "Fit size" : "Encaixar tamanho", + "Auto" : "Automático", "Failed to create {albumName}." : "Falha ao criar {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Falha ao renomear {currentAlbumName} para {newAlbumName}.", "General Failure" : "Falha Geral", diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json index cd92140f..cba3958f 100644 --- a/l10n/pt_BR.json +++ b/l10n/pt_BR.json @@ -198,6 +198,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Observe que a área de corte selecionada é menor que o redimensionamento aplicado, o que pode causar diminuição da qualidade", "Actual size (100%)" : "Tamanho real (100%)", "Fit size" : "Encaixar tamanho", + "Auto" : "Automático", "Failed to create {albumName}." : "Falha ao criar {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Falha ao renomear {currentAlbumName} para {newAlbumName}.", "General Failure" : "Falha Geral", diff --git a/l10n/pt_PT.js b/l10n/pt_PT.js index b043ecfd..3d4aaca8 100644 --- a/l10n/pt_PT.js +++ b/l10n/pt_PT.js @@ -49,6 +49,7 @@ OC.L10N.register( "Size" : "Altura", "Name is required." : "Nome é obrigatório.", "Quality" : "Qualidade", + "Auto" : "Auto", "Failed to delete files." : "Não foi possível eliminar os ficheiros.", "Failed to delete {fileName}." : "Não foi possível eliminar {fileName}.", "Failed to favorite files." : "Não foi possível colocar os ficheiros nos favoritos.", diff --git a/l10n/pt_PT.json b/l10n/pt_PT.json index da72b5b9..f2212fda 100644 --- a/l10n/pt_PT.json +++ b/l10n/pt_PT.json @@ -47,6 +47,7 @@ "Size" : "Altura", "Name is required." : "Nome é obrigatório.", "Quality" : "Qualidade", + "Auto" : "Auto", "Failed to delete files." : "Não foi possível eliminar os ficheiros.", "Failed to delete {fileName}." : "Não foi possível eliminar {fileName}.", "Failed to favorite files." : "Não foi possível colocar os ficheiros nos favoritos.", diff --git a/l10n/ro.js b/l10n/ro.js index 51a99dfb..0f690abf 100644 --- a/l10n/ro.js +++ b/l10n/ro.js @@ -35,6 +35,7 @@ OC.L10N.register( "Custom" : "Particularizat", "Text" : "Text", "Size" : "Mărime", - "Position" : "Poziție" + "Position" : "Poziție", + "Auto" : "Auto" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/l10n/ro.json b/l10n/ro.json index b571646a..7c82c3e8 100644 --- a/l10n/ro.json +++ b/l10n/ro.json @@ -33,6 +33,7 @@ "Custom" : "Particularizat", "Text" : "Text", "Size" : "Mărime", - "Position" : "Poziție" + "Position" : "Poziție", + "Auto" : "Auto" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" } \ No newline at end of file diff --git a/l10n/ru.js b/l10n/ru.js index 9e8d27a0..84d461f8 100644 --- a/l10n/ru.js +++ b/l10n/ru.js @@ -76,6 +76,7 @@ OC.L10N.register( "Extension" : "Расширение", "Name is required." : "Необходимо указать имя.", "Quality" : "Качество", + "Auto" : "Автоматически", "Failed to delete files." : "Ошибка удаления файлов.", "Failed to delete {fileName}." : "Ошибка удаления файла «{fileName}».", "Failed to favorite files." : "Не удалось добавить файлы в избранное.", diff --git a/l10n/ru.json b/l10n/ru.json index eddd830f..2bf5d1b7 100644 --- a/l10n/ru.json +++ b/l10n/ru.json @@ -74,6 +74,7 @@ "Extension" : "Расширение", "Name is required." : "Необходимо указать имя.", "Quality" : "Качество", + "Auto" : "Автоматически", "Failed to delete files." : "Ошибка удаления файлов.", "Failed to delete {fileName}." : "Ошибка удаления файла «{fileName}».", "Failed to favorite files." : "Не удалось добавить файлы в избранное.", diff --git a/l10n/sc.js b/l10n/sc.js index f12abe77..902b52f9 100644 --- a/l10n/sc.js +++ b/l10n/sc.js @@ -48,6 +48,7 @@ OC.L10N.register( "Position" : "Positzione", "Extension" : "Estensione", "Name is required." : "Su nùmene est rechertu: ", - "Quality" : "Calidade" + "Quality" : "Calidade", + "Auto" : "Auto" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/sc.json b/l10n/sc.json index 33465d9b..91b589ec 100644 --- a/l10n/sc.json +++ b/l10n/sc.json @@ -46,6 +46,7 @@ "Position" : "Positzione", "Extension" : "Estensione", "Name is required." : "Su nùmene est rechertu: ", - "Quality" : "Calidade" + "Quality" : "Calidade", + "Auto" : "Auto" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/sk.js b/l10n/sk.js index c26b8801..8b979448 100644 --- a/l10n/sk.js +++ b/l10n/sk.js @@ -180,6 +180,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Upozorňujeme, že vybratá oblasť orezania je menšia ako použitá zmena veľkosti, čo môže spôsobiť zníženie kvality", "Actual size (100%)" : "Aktuálna veľkosť (100%)", "Fit size" : "Prispôsobiť veľlkosť", + "Auto" : "Automaticky", "Failed to create {albumName}." : "Zlyhalo vytváranie {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Chyba pri premenovávaní {currentAlbumName} na {newAlbumName}.", "General Failure" : "Všeobecné zlyhanie", diff --git a/l10n/sk.json b/l10n/sk.json index f5d341e1..e02db2e8 100644 --- a/l10n/sk.json +++ b/l10n/sk.json @@ -178,6 +178,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Upozorňujeme, že vybratá oblasť orezania je menšia ako použitá zmena veľkosti, čo môže spôsobiť zníženie kvality", "Actual size (100%)" : "Aktuálna veľkosť (100%)", "Fit size" : "Prispôsobiť veľlkosť", + "Auto" : "Automaticky", "Failed to create {albumName}." : "Zlyhalo vytváranie {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Chyba pri premenovávaní {currentAlbumName} na {newAlbumName}.", "General Failure" : "Všeobecné zlyhanie", diff --git a/l10n/sl.js b/l10n/sl.js index 8cc89ae9..19883da4 100644 --- a/l10n/sl.js +++ b/l10n/sl.js @@ -58,6 +58,7 @@ OC.L10N.register( "Position" : "Položaj", "Extension" : "Pripona", "Name is required." : "Ime mora biti vpisano.", - "Quality" : "Kakovost" + "Quality" : "Kakovost", + "Auto" : "Samodejno" }, "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"); diff --git a/l10n/sl.json b/l10n/sl.json index ebd52d55..0dadba3d 100644 --- a/l10n/sl.json +++ b/l10n/sl.json @@ -56,6 +56,7 @@ "Position" : "Položaj", "Extension" : "Pripona", "Name is required." : "Ime mora biti vpisano.", - "Quality" : "Kakovost" + "Quality" : "Kakovost", + "Auto" : "Samodejno" },"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" } \ No newline at end of file diff --git a/l10n/sr.js b/l10n/sr.js index 26b34bb4..f5da664a 100644 --- a/l10n/sr.js +++ b/l10n/sr.js @@ -45,6 +45,7 @@ OC.L10N.register( "Text" : "Текст", "Size" : "величина", "Position" : "Позиција", - "Extension" : "Екстензија" + "Extension" : "Екстензија", + "Auto" : "Аутоматски" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/l10n/sr.json b/l10n/sr.json index df373dd0..04c2b582 100644 --- a/l10n/sr.json +++ b/l10n/sr.json @@ -43,6 +43,7 @@ "Text" : "Текст", "Size" : "величина", "Position" : "Позиција", - "Extension" : "Екстензија" + "Extension" : "Екстензија", + "Auto" : "Аутоматски" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" } \ No newline at end of file diff --git a/l10n/sv.js b/l10n/sv.js index 754c9986..267b3ee9 100644 --- a/l10n/sv.js +++ b/l10n/sv.js @@ -67,6 +67,7 @@ OC.L10N.register( "Position" : "Position", "Extension" : "Tillägg", "Name is required." : "Namn är obligatoriskt.", + "Auto" : "Auto", "Failed to delete files." : "Misslyckades att radera filer.", "Failed to delete {fileName}." : "Misslyckades att radera {fileName}.", "Failed to favorite files." : "Misslyckades att favorisera filer.", diff --git a/l10n/sv.json b/l10n/sv.json index 72d8ec35..1f5ad73b 100644 --- a/l10n/sv.json +++ b/l10n/sv.json @@ -65,6 +65,7 @@ "Position" : "Position", "Extension" : "Tillägg", "Name is required." : "Namn är obligatoriskt.", + "Auto" : "Auto", "Failed to delete files." : "Misslyckades att radera filer.", "Failed to delete {fileName}." : "Misslyckades att radera {fileName}.", "Failed to favorite files." : "Misslyckades att favorisera filer.", diff --git a/l10n/tr.js b/l10n/tr.js index e89e1778..47085f8e 100644 --- a/l10n/tr.js +++ b/l10n/tr.js @@ -3,6 +3,7 @@ OC.L10N.register( { "Memories" : "Anılar", "Yet another photo management app" : "Başka bir fotoğraf yönetimi uygulaması daha", + "# Memories\n\nMemories is a *batteries-included* photo management solution for Nextcloud with advanced features including:\n\n- **📸 Timeline**: Sort photos and videos by date taken, parsed from Exif data.\n- **⏪ Rewind**: Jump to any time in the past instantly and relive your memories.\n- **🤖 AI Tagging**: Group photos by people and objects using AI, powered by [recognize](https://github.com/nextcloud/recognize).\n- **🖼️ Albums**: Create albums to group photos and videos together. Then share these albums with others.\n- **🫱🏻‍🫲🏻 External Sharing**: Share photos and videos with people outside of your Nextcloud instance.\n- **📱 Mobile Support**: Works on devices of any shape and size through the web app.\n- **✏️ Edit Metadata**: Edit dates on photos quickly and easily.\n- **📦 Archive**: Store photos you don't want to see in your timeline in a separate folder.\n- **📹 Video Transcoding**: Memories transcodes videos and uses HLS for maximal performance.\n- **⚡️ Performance**: In general, Memories is extremely fast.\n\n## 🌐 Online Demo\n\n- To get an idea of what memories looks and feels like, check out the [public demo](https://memories-demo.radialapps.com/apps/memories/).\n- The demo is read-only and may be slow (free tier VM from [Oracle Cloud](https://www.oracle.com/cloud/free/)).\n- Photo credits go to [Unsplash](https://unsplash.com/) (for individual credits, refer to each folder).\n\n## 🚀 Installation\n\n1. Install the app from the Nextcloud app store.\n1. Perform the recommended [configuration steps](https://github.com/pulsejet/memories/wiki/Extra-Configuration).\n1. Run `php ./occ memories:index` to generate metadata indices for existing photos.\n1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos." : "# Anılar\n\nAnılar, Nextcloud için \"pilleriyle birlikte\" gelen ve aşağıdaki gibi gelişmiş özellikleri bulunan bir fotoğraf yönetimi uygulamasıdır:\n\n- **📸 Zaman tüneli**: Fotoğrafları ve görüntüleri çekildikleri tarihe göre sıralayabilir, Exif verilerine göre ayrıştırabilirsiniz.\n- **⏪ Geri sarma**: Geçmişte herhangi bir zamana atlayabilir ve anılarınızı yeniden yaşayabilirsiniz.\n- **🤖 Yapay zeka ile etiketleme**: [recognize](https://github.com/nextcloud/recognize) tarafından desteklenen yapay zeka ile fotoğrafları insanlara ve nesnelere göre gruplayabilirsiniz.\n- **🖼️ Albümler**: Fotoğrafları ve görüntüleri birlikte gruplandırmak için albümler oluşturabilirsiniz. Daha sonra bu albümleri başkalarıyla paylaşabilirsiniz.\n- **🫱🏻‍🫲🏻 Dış paylaşım**: Fotoğrafları ve görüntüleri Nextcloud bulut sunucunuzun dışındaki kişilerle paylaşabilirsiniz.\n- **📱 Mobil desteği**: Web uygulaması üzerinden farklı şekil ve boyuttaki aygıtlarda kullanabilirsiniz.\n- **✏️ Üst verileri düzenleme**: Fotoğraflardaki tarihleri ​​hızlı ve kolay bir şekilde düzenleyebilirsiniz.\n- **📦 Arşiv**: Zaman tünelinizde görmek istemediğiniz fotoğrafları ayrı bir klasörde saklayabilirsiniz.\n- **📹 Görüntü dönüştürme**: Anılar görüntüleri dönüştürebilir ve en iyi başarım için HLS kullanır.\n- **⚡️ Başarım**: Anılar uygulaması son derece hızlıdır.\n\n## 🌐 Çevrimiçi Deneme\n\n- Anılar uygulamasının nasıl göründüğü ve nasıl hissettirdiği hakkında bir fikir edinmek için [genel deneme](https://memories-demo.radialapps.com/apps/memories/) sitesine göz atın.\n- Deneme sitesi salt okunurdur ve yavaş olabilir ([Oracle Cloud üzerinde](https://www.oracle.com/cloud/free/) ücretsiz VM paketini kullanır).\n- Fotoğraf hakkında emeği geçenler için [Unsplash](https://unsplash.com/) adresine bakabilirsiniz (bireysel eeği geçenler için her klasöre bakın).\n\n## 🚀 Kurulum\n\n1. Uygulamayı Nextcloud uygulama mağazasından yükleyin.\n1. Önerilen [yapılandırma adımlarını](https://github.com/pulsejet/memories/wiki/Extra-Configuration) gerçekleştirin.\n1. var olan fotoğrafların üst veri dizinlerini oluşturmak için `php ./occ memory:index` komutunu yürütün.\n1. Nextcloud üzerinde 📷 Anılar uygulamasını açın ve fotoğraflarınızın bulunduğu klasörü ayarlayın.", "Settings" : "Ayarlar", "Timeline" : "Zaman tüneli", "Folders" : "Klasörler", @@ -220,6 +221,7 @@ OC.L10N.register( "Actual size (100%)" : "Gerçek boyut (%100)", "Fit size" : "Boyutu sığdır", "Transcoding failed." : "Kod dönüştürülemedi.", + "Auto" : "Otomatik", "Shared Folder" : "Paylaşılmış klasör", "Failed to create {albumName}." : "{albumName} albümü oluşturulamadı.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} albümünün adı {newAlbumName} olarak değiştirilemedi.", diff --git a/l10n/tr.json b/l10n/tr.json index 249f1da4..041915c0 100644 --- a/l10n/tr.json +++ b/l10n/tr.json @@ -1,6 +1,7 @@ { "translations": { "Memories" : "Anılar", "Yet another photo management app" : "Başka bir fotoğraf yönetimi uygulaması daha", + "# Memories\n\nMemories is a *batteries-included* photo management solution for Nextcloud with advanced features including:\n\n- **📸 Timeline**: Sort photos and videos by date taken, parsed from Exif data.\n- **⏪ Rewind**: Jump to any time in the past instantly and relive your memories.\n- **🤖 AI Tagging**: Group photos by people and objects using AI, powered by [recognize](https://github.com/nextcloud/recognize).\n- **🖼️ Albums**: Create albums to group photos and videos together. Then share these albums with others.\n- **🫱🏻‍🫲🏻 External Sharing**: Share photos and videos with people outside of your Nextcloud instance.\n- **📱 Mobile Support**: Works on devices of any shape and size through the web app.\n- **✏️ Edit Metadata**: Edit dates on photos quickly and easily.\n- **📦 Archive**: Store photos you don't want to see in your timeline in a separate folder.\n- **📹 Video Transcoding**: Memories transcodes videos and uses HLS for maximal performance.\n- **⚡️ Performance**: In general, Memories is extremely fast.\n\n## 🌐 Online Demo\n\n- To get an idea of what memories looks and feels like, check out the [public demo](https://memories-demo.radialapps.com/apps/memories/).\n- The demo is read-only and may be slow (free tier VM from [Oracle Cloud](https://www.oracle.com/cloud/free/)).\n- Photo credits go to [Unsplash](https://unsplash.com/) (for individual credits, refer to each folder).\n\n## 🚀 Installation\n\n1. Install the app from the Nextcloud app store.\n1. Perform the recommended [configuration steps](https://github.com/pulsejet/memories/wiki/Extra-Configuration).\n1. Run `php ./occ memories:index` to generate metadata indices for existing photos.\n1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos." : "# Anılar\n\nAnılar, Nextcloud için \"pilleriyle birlikte\" gelen ve aşağıdaki gibi gelişmiş özellikleri bulunan bir fotoğraf yönetimi uygulamasıdır:\n\n- **📸 Zaman tüneli**: Fotoğrafları ve görüntüleri çekildikleri tarihe göre sıralayabilir, Exif verilerine göre ayrıştırabilirsiniz.\n- **⏪ Geri sarma**: Geçmişte herhangi bir zamana atlayabilir ve anılarınızı yeniden yaşayabilirsiniz.\n- **🤖 Yapay zeka ile etiketleme**: [recognize](https://github.com/nextcloud/recognize) tarafından desteklenen yapay zeka ile fotoğrafları insanlara ve nesnelere göre gruplayabilirsiniz.\n- **🖼️ Albümler**: Fotoğrafları ve görüntüleri birlikte gruplandırmak için albümler oluşturabilirsiniz. Daha sonra bu albümleri başkalarıyla paylaşabilirsiniz.\n- **🫱🏻‍🫲🏻 Dış paylaşım**: Fotoğrafları ve görüntüleri Nextcloud bulut sunucunuzun dışındaki kişilerle paylaşabilirsiniz.\n- **📱 Mobil desteği**: Web uygulaması üzerinden farklı şekil ve boyuttaki aygıtlarda kullanabilirsiniz.\n- **✏️ Üst verileri düzenleme**: Fotoğraflardaki tarihleri ​​hızlı ve kolay bir şekilde düzenleyebilirsiniz.\n- **📦 Arşiv**: Zaman tünelinizde görmek istemediğiniz fotoğrafları ayrı bir klasörde saklayabilirsiniz.\n- **📹 Görüntü dönüştürme**: Anılar görüntüleri dönüştürebilir ve en iyi başarım için HLS kullanır.\n- **⚡️ Başarım**: Anılar uygulaması son derece hızlıdır.\n\n## 🌐 Çevrimiçi Deneme\n\n- Anılar uygulamasının nasıl göründüğü ve nasıl hissettirdiği hakkında bir fikir edinmek için [genel deneme](https://memories-demo.radialapps.com/apps/memories/) sitesine göz atın.\n- Deneme sitesi salt okunurdur ve yavaş olabilir ([Oracle Cloud üzerinde](https://www.oracle.com/cloud/free/) ücretsiz VM paketini kullanır).\n- Fotoğraf hakkında emeği geçenler için [Unsplash](https://unsplash.com/) adresine bakabilirsiniz (bireysel eeği geçenler için her klasöre bakın).\n\n## 🚀 Kurulum\n\n1. Uygulamayı Nextcloud uygulama mağazasından yükleyin.\n1. Önerilen [yapılandırma adımlarını](https://github.com/pulsejet/memories/wiki/Extra-Configuration) gerçekleştirin.\n1. var olan fotoğrafların üst veri dizinlerini oluşturmak için `php ./occ memory:index` komutunu yürütün.\n1. Nextcloud üzerinde 📷 Anılar uygulamasını açın ve fotoğraflarınızın bulunduğu klasörü ayarlayın.", "Settings" : "Ayarlar", "Timeline" : "Zaman tüneli", "Folders" : "Klasörler", @@ -218,6 +219,7 @@ "Actual size (100%)" : "Gerçek boyut (%100)", "Fit size" : "Boyutu sığdır", "Transcoding failed." : "Kod dönüştürülemedi.", + "Auto" : "Otomatik", "Shared Folder" : "Paylaşılmış klasör", "Failed to create {albumName}." : "{albumName} albümü oluşturulamadı.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} albümünün adı {newAlbumName} olarak değiştirilemedi.", diff --git a/l10n/uk.js b/l10n/uk.js index e83c0e77..2cb1c135 100644 --- a/l10n/uk.js +++ b/l10n/uk.js @@ -161,6 +161,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Зауважте, що вибрана область кадрування нижча за застосований розмір, що може спричинити погіршення якості", "Actual size (100%)" : "Фактичний розмір (100%)", "Fit size" : "Підходить за розміром", + "Auto" : "Автоматично", "Failed to create {albumName}." : "Не вдалося створити {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Не вдалося перейменувати {currentAlbumName} на {newAlbumName}.", "Failed to delete files." : "Не вдалося видалити файли.", diff --git a/l10n/uk.json b/l10n/uk.json index 64c2a175..8f0d101c 100644 --- a/l10n/uk.json +++ b/l10n/uk.json @@ -159,6 +159,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Зауважте, що вибрана область кадрування нижча за застосований розмір, що може спричинити погіршення якості", "Actual size (100%)" : "Фактичний розмір (100%)", "Fit size" : "Підходить за розміром", + "Auto" : "Автоматично", "Failed to create {albumName}." : "Не вдалося створити {albumName}.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "Не вдалося перейменувати {currentAlbumName} на {newAlbumName}.", "Failed to delete files." : "Не вдалося видалити файли.", diff --git a/l10n/vi.js b/l10n/vi.js index 71899926..7c72362a 100644 --- a/l10n/vi.js +++ b/l10n/vi.js @@ -36,6 +36,7 @@ OC.L10N.register( "Image" : "Hình ảnh", "Text" : "Văn bản", "Size" : "Kích cỡ", - "Name is required." : "Tên là bắt buộc." + "Name is required." : "Tên là bắt buộc.", + "Auto" : "Tự động" }, "nplurals=1; plural=0;"); diff --git a/l10n/vi.json b/l10n/vi.json index c15003c5..f1d9e2af 100644 --- a/l10n/vi.json +++ b/l10n/vi.json @@ -34,6 +34,7 @@ "Image" : "Hình ảnh", "Text" : "Văn bản", "Size" : "Kích cỡ", - "Name is required." : "Tên là bắt buộc." + "Name is required." : "Tên là bắt buộc.", + "Auto" : "Tự động" },"pluralForm" :"nplurals=1; plural=0;" } \ No newline at end of file diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js index 9fbf27f2..6db292b1 100644 --- a/l10n/zh_CN.js +++ b/l10n/zh_CN.js @@ -84,6 +84,7 @@ OC.L10N.register( "Extension" : "扩展", "Name is required." : "名称是必填项。", "Quality" : "质量", + "Auto" : "自动", "Failed to create {albumName}." : "创建 {albumName} 失败", "Failed to rename {currentAlbumName} to {newAlbumName}." : "重命名 {currentAlbumName} 为 {newAlbumName} 的操作失败", "Failed to delete {fileName}." : "删除 {fileName} 失败" diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json index a24b060d..5c4687c2 100644 --- a/l10n/zh_CN.json +++ b/l10n/zh_CN.json @@ -82,6 +82,7 @@ "Extension" : "扩展", "Name is required." : "名称是必填项。", "Quality" : "质量", + "Auto" : "自动", "Failed to create {albumName}." : "创建 {albumName} 失败", "Failed to rename {currentAlbumName} to {newAlbumName}." : "重命名 {currentAlbumName} 为 {newAlbumName} 的操作失败", "Failed to delete {fileName}." : "删除 {fileName} 失败" diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js index 0b56cba3..89eed547 100644 --- a/l10n/zh_HK.js +++ b/l10n/zh_HK.js @@ -221,6 +221,7 @@ OC.L10N.register( "Actual size (100%)" : "實際大小 (100%)", "Fit size" : "調整大小", "Transcoding failed." : "轉碼失敗。", + "Auto" : "自動", "Shared Folder" : "分享資料夾", "Failed to create {albumName}." : "創建 {albumName} 失敗。", "Failed to rename {currentAlbumName} to {newAlbumName}." : "重新命名 {currentAlbumName} 為 {newAlbumName} 失敗。", diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json index 5baa0c97..e6ba70d5 100644 --- a/l10n/zh_HK.json +++ b/l10n/zh_HK.json @@ -219,6 +219,7 @@ "Actual size (100%)" : "實際大小 (100%)", "Fit size" : "調整大小", "Transcoding failed." : "轉碼失敗。", + "Auto" : "自動", "Shared Folder" : "分享資料夾", "Failed to create {albumName}." : "創建 {albumName} 失敗。", "Failed to rename {currentAlbumName} to {newAlbumName}." : "重新命名 {currentAlbumName} 為 {newAlbumName} 失敗。", diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js index e7c85907..e51a6d19 100644 --- a/l10n/zh_TW.js +++ b/l10n/zh_TW.js @@ -26,6 +26,8 @@ OC.L10N.register( "Choose the root of your timeline" : "選擇您時間軸的根", "The selected folder does not seem to be valid. Try again." : "選定的資料夾似乎是無效的。請再試一次。", "Found {total} photos in {path}" : "在 {path} 中找到 {total} 張照片", + "Failed to get Exif data. Metadata may be lost!" : "取得 Exif 資料失敗。詮釋資料可能會遺失!", + "No Exif data found! Continue?" : "未找到 Exif 資料!繼續?", "Image saved successfully" : "圖片儲存成功", "Error saving image" : "儲存影像時發生錯誤", "Unsaved changes" : "未儲存變更", @@ -218,6 +220,8 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "請注意,選定的裁剪區域低於套用的調整大小,這可能會導致品質下降", "Actual size (100%)" : "實際大小 (100%)", "Fit size" : "合適大小", + "Transcoding failed." : "轉換編碼失敗。", + "Auto" : "自動", "Shared Folder" : "已分享的資料夾", "Failed to create {albumName}." : "建立 {albumName} 失敗。", "Failed to rename {currentAlbumName} to {newAlbumName}." : "重新命名 {currentAlbumName} 為 {newAlbumName} 失敗。", diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json index 19c78297..c7c2c79f 100644 --- a/l10n/zh_TW.json +++ b/l10n/zh_TW.json @@ -24,6 +24,8 @@ "Choose the root of your timeline" : "選擇您時間軸的根", "The selected folder does not seem to be valid. Try again." : "選定的資料夾似乎是無效的。請再試一次。", "Found {total} photos in {path}" : "在 {path} 中找到 {total} 張照片", + "Failed to get Exif data. Metadata may be lost!" : "取得 Exif 資料失敗。詮釋資料可能會遺失!", + "No Exif data found! Continue?" : "未找到 Exif 資料!繼續?", "Image saved successfully" : "圖片儲存成功", "Error saving image" : "儲存影像時發生錯誤", "Unsaved changes" : "未儲存變更", @@ -216,6 +218,8 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "請注意,選定的裁剪區域低於套用的調整大小,這可能會導致品質下降", "Actual size (100%)" : "實際大小 (100%)", "Fit size" : "合適大小", + "Transcoding failed." : "轉換編碼失敗。", + "Auto" : "自動", "Shared Folder" : "已分享的資料夾", "Failed to create {albumName}." : "建立 {albumName} 失敗。", "Failed to rename {currentAlbumName} to {newAlbumName}." : "重新命名 {currentAlbumName} 為 {newAlbumName} 失敗。", From c79c3fa3eda8c56051c731d64ce98406229e8b3d Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 07:44:57 -0800 Subject: [PATCH 126/163] Update tar args (#195) --- scripts/bundle.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/bundle.sh b/scripts/bundle.sh index 03c634fb..9ca1b61c 100755 --- a/scripts/bundle.sh +++ b/scripts/bundle.sh @@ -4,7 +4,7 @@ od=`pwd` rm -rf /tmp/memories mkdir -p /tmp/memories -cp -R appinfo l10n img js lib templates COPYING README.md transcoder.yaml exiftest* composer* /tmp/memories +cp -R appinfo l10n img js lib templates COPYING README.md exiftest* composer* /tmp/memories cd /tmp rm -f memories/appinfo/screencap* memories/js/*.map @@ -14,7 +14,7 @@ cd memories sh "$od/scripts/get-exiftool.sh" cd .. -tar -zvcf memories.tar.gz memories/ +tar --no-same-owner -p -zcf memories.tar.gz memories/ rm -rf memories cd $od From 599dacedcd5c93d63cad803c1cb05fb2558a379a Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 08:11:00 -0800 Subject: [PATCH 127/163] Update changelog date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 707f38d3..91be9241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ This file is manually updated. Please file an issue if something is missing. -## v4.7.0, v3.7.0 +## v4.7.0, v3.7.0 (2022-11-14) - **Note**: you must run `occ memories:index -f` to take advantage of new features. - **Massively improved video performance** From 472c0ccc5eb1ea434eb9911c32e4661952ad2f88 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 09:54:19 -0800 Subject: [PATCH 128/163] Add changelog to readme (#199) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0cc2aa36..fff9fdd0 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,10 @@ A shout out to the current and past financial backers of Memories! See the spons [](https://github.com/mpodshivalin) +## Changelog + +For the full changelog, see [CHANGELOG.md](CHANGELOG.md). + ## Special Thanks Nextcloud team. A lot of this work is based on [Photos](https://github.com/nextcloud/photos). From 45abfa9cb70321d7059df341b50c3a5a9118baae Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Tue, 15 Nov 2022 03:17:07 +0000 Subject: [PATCH 129/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/ar.js | 3 ++- l10n/ar.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/l10n/ar.js b/l10n/ar.js index bfb2bfb0..d0e5decf 100644 --- a/l10n/ar.js +++ b/l10n/ar.js @@ -39,6 +39,7 @@ OC.L10N.register( "Size" : "الحجم", "Position" : "الموقع", "Name is required." : "حقل الاسم مطلوب", - "Quality" : "الجودة" + "Quality" : "الجودة", + "Auto" : "تلقائي" }, "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"); diff --git a/l10n/ar.json b/l10n/ar.json index a1412f69..4a0e1703 100644 --- a/l10n/ar.json +++ b/l10n/ar.json @@ -37,6 +37,7 @@ "Size" : "الحجم", "Position" : "الموقع", "Name is required." : "حقل الاسم مطلوب", - "Quality" : "الجودة" + "Quality" : "الجودة", + "Auto" : "تلقائي" },"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;" } \ No newline at end of file From 03ef6a615a8c9a65a17cd3b205411454c1095ece Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 21:32:41 -0800 Subject: [PATCH 130/163] ci: add POSTGRES_DB --- .github/workflows/e2e.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 4309147a..187ab72d 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -118,6 +118,7 @@ jobs: ports: - 4444:5432/tcp env: + POSTGRES_DB: nextcloud POSTGRES_PASSWORD: rootpassword options: >- --health-cmd pg_isready From 467c52053c5ab4dc3be299e3d827d73b240e9e84 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 14 Nov 2022 21:49:41 -0800 Subject: [PATCH 131/163] metaview: fix width on 100% scaling (close #200) --- src/App.vue | 5 +++++ src/components/Metadata.vue | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/App.vue b/src/App.vue index 9d1c0731..7b00bc27 100644 --- a/src/App.vue +++ b/src/App.vue @@ -344,6 +344,11 @@ body.has-viewer header { overflow-x: hidden; } +// Prevent sidebar from becoming too big +aside.app-sidebar { + max-width: 360px !important; +} + // Fill all available space .fill-block { width: 100%; diff --git a/src/components/Metadata.vue b/src/components/Metadata.vue index 850aa392..8e69d8ff 100644 --- a/src/components/Metadata.vue +++ b/src/components/Metadata.vue @@ -343,6 +343,8 @@ export default class Metadata extends Mixins(GlobalMixin) { .map { width: 100%; - height: 200px; + aspect-ratio: 16 / 10; + min-height: 200px; + max-height: 250px; } \ No newline at end of file From e01b536f8349f4edce5ca3b6365e22e65cfe7705 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 01:50:59 -0800 Subject: [PATCH 132/163] fix: regression in non-transcode video (#198) (fix #202) --- src/services/dav/download.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/services/dav/download.ts b/src/services/dav/download.ts index 5cf166a9..4684a371 100644 --- a/src/services/dav/download.ts +++ b/src/services/dav/download.ts @@ -102,10 +102,5 @@ export function getDownloadLink(photo: IPhoto) { } } - try { - const file = "/" + photo.filename.split("/").slice(3).join("/"); - return `/apps/files/ajax/download.php?files=${file}`; // normal route - } catch { - return `/remote.php/dav${photo.filename}`; // fallback - } + return `/remote.php/dav${photo.filename}`; } From 220a685bf65db22163107c503ecff035cb1f746e Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 02:27:20 -0800 Subject: [PATCH 133/163] Allow specifying ff* path (fix #201) --- lib/Command/VideoSetup.php | 16 +++++++--------- lib/Controller/VideoController.php | 18 ++++++++++++------ scripts/get-exiftool.sh | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/Command/VideoSetup.php b/lib/Command/VideoSetup.php index c84960dd..efde576c 100644 --- a/lib/Command/VideoSetup.php +++ b/lib/Command/VideoSetup.php @@ -50,16 +50,12 @@ class VideoSetup extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - // Check nohup binary - $nohup = shell_exec('nohup --version'); - if (!$nohup || false === strpos($nohup, 'nohup')) { - $output->writeln('nohup binary not found. Please install nohup.'); - - return $this->suggestDisable($output); - } + // Preset executables + $ffmpegPath = $this->config->getSystemValue('memories.ffmpeg_path', 'ffmpeg'); + $ffprobePath = $this->config->getSystemValue('memories.ffprobe_path', 'ffprobe'); // Get ffmpeg version - $ffmpeg = shell_exec('ffmpeg -version'); + $ffmpeg = shell_exec("$ffmpegPath -version"); if (false === strpos($ffmpeg, 'ffmpeg version')) { $ffmpeg = null; $output->writeln('ffmpeg is not installed'); @@ -68,7 +64,7 @@ class VideoSetup extends Command } // Get ffprobe version - $ffprobe = shell_exec('ffprobe -version'); + $ffprobe = shell_exec("$ffprobePath -version"); if (false === strpos($ffprobe, 'ffprobe version')) { $ffprobe = null; $output->writeln('ffprobe is not installed'); @@ -129,6 +125,7 @@ class VideoSetup extends Command $this->config->setSystemValue('memories.transcoder', $goVodPath); $this->config->setSystemValue('memories.no_transcode', false); $output->writeln('Transcoding and HLS are now enabled! Monitor the output at /tmp/go-vod.log for any errors'); + $output->writeln('You should restart the server for changes to take effect'); // Check for VAAPI $output->writeln("\nChecking for QSV (/dev/dri/renderD128)"); @@ -171,6 +168,7 @@ class VideoSetup extends Command $this->config->setSystemValue('memories.no_transcode', true); $output->writeln('Transcoding and HLS are now disabled'); + $output->writeln('You should restart the server for changes to take effect'); return 0; } diff --git a/lib/Controller/VideoController.php b/lib/Controller/VideoController.php index bf8d531f..87261372 100644 --- a/lib/Controller/VideoController.php +++ b/lib/Controller/VideoController.php @@ -96,15 +96,21 @@ class VideoController extends ApiBase } // Check for environment variables - $vaapi = $this->config->getSystemValue('memories.qsv', false); $env = ''; - if ($vaapi) { - $env .= 'VAAPI=1 '; - } + + // QSV with VAAPI + $vaapi = $this->config->getSystemValue('memories.qsv', false); + if ($vaapi) $env .= 'VAAPI=1 '; + + // Paths + $ffmpegPath = $this->config->getSystemValue('memories.ffmpeg_path', 'ffmpeg'); + $ffprobePath = $this->config->getSystemValue('memories.ffprobe_path', 'ffprobe'); + $tmpPath = $this->config->getSystemValue('memories.tmp_path', sys_get_temp_dir()); + $env .= "FFMPEG='$ffmpegPath' FFPROBE='$ffprobePath' GOVOD_TEMPDIR='$tmpPath/go-vod' "; // Check if already running - shell_exec("pkill {$transcoder}"); - shell_exec("{$env} nohup {$transcoder} > {$tmpDir}/go-vod.log 2>&1 & > /dev/null"); + exec("pkill {$transcoder}"); + shell_exec("{$env} nohup {$transcoder} > {$tmpPath}/go-vod.log 2>&1 & > /dev/null"); // wait for 1s and try again sleep(1); diff --git a/scripts/get-exiftool.sh b/scripts/get-exiftool.sh index 6f78f136..2cfaea78 100755 --- a/scripts/get-exiftool.sh +++ b/scripts/get-exiftool.sh @@ -17,7 +17,7 @@ mv "exiftool-$exifver" exiftool rm -rf *.zip exiftool/t exiftool/html chmod 755 exiftool/exiftool -govod="0.0.11" +govod="0.0.12" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64" chmod 755 go-vod-* From 8d6e49da7dc516cc118ab69b25534eacac7937d0 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 02:39:15 -0800 Subject: [PATCH 134/163] php-lint --- lib/Command/VideoSetup.php | 4 ++-- lib/Controller/VideoController.php | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/Command/VideoSetup.php b/lib/Command/VideoSetup.php index efde576c..01b80be1 100644 --- a/lib/Command/VideoSetup.php +++ b/lib/Command/VideoSetup.php @@ -55,7 +55,7 @@ class VideoSetup extends Command $ffprobePath = $this->config->getSystemValue('memories.ffprobe_path', 'ffprobe'); // Get ffmpeg version - $ffmpeg = shell_exec("$ffmpegPath -version"); + $ffmpeg = shell_exec("{$ffmpegPath} -version"); if (false === strpos($ffmpeg, 'ffmpeg version')) { $ffmpeg = null; $output->writeln('ffmpeg is not installed'); @@ -64,7 +64,7 @@ class VideoSetup extends Command } // Get ffprobe version - $ffprobe = shell_exec("$ffprobePath -version"); + $ffprobe = shell_exec("{$ffprobePath} -version"); if (false === strpos($ffprobe, 'ffprobe version')) { $ffprobe = null; $output->writeln('ffprobe is not installed'); diff --git a/lib/Controller/VideoController.php b/lib/Controller/VideoController.php index 87261372..8ad56a63 100644 --- a/lib/Controller/VideoController.php +++ b/lib/Controller/VideoController.php @@ -100,13 +100,15 @@ class VideoController extends ApiBase // QSV with VAAPI $vaapi = $this->config->getSystemValue('memories.qsv', false); - if ($vaapi) $env .= 'VAAPI=1 '; + if ($vaapi) { + $env .= 'VAAPI=1 '; + } // Paths $ffmpegPath = $this->config->getSystemValue('memories.ffmpeg_path', 'ffmpeg'); $ffprobePath = $this->config->getSystemValue('memories.ffprobe_path', 'ffprobe'); $tmpPath = $this->config->getSystemValue('memories.tmp_path', sys_get_temp_dir()); - $env .= "FFMPEG='$ffmpegPath' FFPROBE='$ffprobePath' GOVOD_TEMPDIR='$tmpPath/go-vod' "; + $env .= "FFMPEG='{$ffmpegPath}' FFPROBE='{$ffprobePath}' GOVOD_TEMPDIR='{$tmpPath}/go-vod' "; // Check if already running exec("pkill {$transcoder}"); From 19386f2422608da36141dbf57778af49ce7e2ad1 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 05:08:53 -0800 Subject: [PATCH 135/163] release: v4.7.2 --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index e5282414..9ae17a28 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -33,7 +33,7 @@ Memories is a *batteries-included* photo management solution for Nextcloud with 1. Run `php ./occ memories:index` to generate metadata indices for existing photos. 1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos. ]]> - 4.7.1 + 4.7.2 agpl Varun Patil Memories From 5f5918372608d9b7192cea4c88903d7192bc0e7e Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 05:40:46 -0800 Subject: [PATCH 136/163] Add more permissions checks --- lib/Controller/ApiBase.php | 9 +++++++++ lib/Controller/ArchiveController.php | 2 +- lib/Controller/FacesController.php | 5 +++++ lib/Controller/ImageController.php | 2 +- lib/Controller/VideoController.php | 4 ++++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/Controller/ApiBase.php b/lib/Controller/ApiBase.php index 3d3ef667..146e7879 100644 --- a/lib/Controller/ApiBase.php +++ b/lib/Controller/ApiBase.php @@ -131,6 +131,10 @@ class ApiBase extends Controller throw new \Exception('Folder not found'); } + if (!($folder->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + throw new \Exception('Folder not readable'); + } + return $folder; } @@ -160,6 +164,11 @@ class ApiBase extends Controller return null; } + // Check read permission + if (!($file[0]->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + return null; + } + return $file[0]; } diff --git a/lib/Controller/ArchiveController.php b/lib/Controller/ArchiveController.php index 4ca93d0c..f6c518b4 100644 --- a/lib/Controller/ArchiveController.php +++ b/lib/Controller/ArchiveController.php @@ -54,7 +54,7 @@ class ArchiveController extends ApiBase $file = $file[0]; // Check if user has permissions - if (!$file->isUpdateable()) { + if (!$file->isUpdateable() || !($file->getPermissions() & \OCP\Constants::PERMISSION_UPDATE)) { return new JSONResponse(['message' => 'Cannot update this file'], Http::STATUS_FORBIDDEN); } diff --git a/lib/Controller/FacesController.php b/lib/Controller/FacesController.php index a6634ed7..f4dfd097 100644 --- a/lib/Controller/FacesController.php +++ b/lib/Controller/FacesController.php @@ -104,6 +104,11 @@ class FacesController extends ApiBase continue; } + // Check read permission + if (!($files[0]->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + continue; + } + // Get (hopefully cached) preview image try { $preview = $this->previewManager->getPreview($files[0], 2048, 2048, false); diff --git a/lib/Controller/ImageController.php b/lib/Controller/ImageController.php index 43531472..c6cb40bf 100644 --- a/lib/Controller/ImageController.php +++ b/lib/Controller/ImageController.php @@ -71,7 +71,7 @@ class ImageController extends ApiBase } // Check if user has permissions - if (!$file->isUpdateable()) { + if (!$file->isUpdateable() || !($file->getPermissions() & \OCP\Constants::PERMISSION_UPDATE)) { return new JSONResponse([], Http::STATUS_FORBIDDEN); } diff --git a/lib/Controller/VideoController.php b/lib/Controller/VideoController.php index 8ad56a63..9f43bd39 100644 --- a/lib/Controller/VideoController.php +++ b/lib/Controller/VideoController.php @@ -62,6 +62,10 @@ class VideoController extends ApiBase } $file = $files[0]; + if (!($file->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + return new JSONResponse(['message' => 'File not readable'], Http::STATUS_FORBIDDEN); + } + // Local files only for now if (!$file->getStorage()->isLocal()) { return new JSONResponse(['message' => 'External storage not supported'], Http::STATUS_FORBIDDEN); From 34340de5f12ce7ab367989ea7587978c607eabdd Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 07:12:27 -0800 Subject: [PATCH 137/163] big: recurse all mountpoints in timeline path --- lib/Db/TimelineQueryDays.php | 73 +++++++++++++++++++++++------------- src/components/Settings.vue | 6 ++- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 0bbbe9a1..23c405cb 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -8,14 +8,14 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\Folder; use OCP\IDBConnection; -const CTE_FOLDERS = // CTE to get all folders recursively in the given top folder +const CTE_FOLDERS = // CTE to get all folders recursively in the given top folders excluding archive 'WITH RECURSIVE *PREFIX*cte_folders(fileid) AS ( SELECT f.fileid FROM *PREFIX*filecache f WHERE - f.fileid = :topFolderId + f.fileid IN (:topFolderIds) UNION ALL SELECT f.fileid @@ -24,10 +24,43 @@ const CTE_FOLDERS = // CTE to get all folders recursively in the given top folde INNER JOIN *PREFIX*cte_folders c ON (f.parent = c.fileid AND f.mimetype = (SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = \'httpd/unix-directory\') - AND f.fileid <> :excludedFolderId + AND f.name <> \'.archive\' ) )'; +const CTE_FOLDERS_ARCHIVE = // CTE to get all archive folders recursively in the given top folders + 'WITH RECURSIVE *PREFIX*cte_folders_all(fileid, name) AS ( + SELECT + f.fileid, f.name + FROM + *PREFIX*filecache f + WHERE + f.fileid IN (:topFolderIds) + UNION ALL + SELECT + f.fileid, f.name + FROM + *PREFIX*filecache f + INNER JOIN *PREFIX*cte_folders_all c + ON (f.parent = c.fileid + AND f.mimetype = (SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = \'httpd/unix-directory\') + ) + ), *PREFIX*cte_folders(fileid) AS ( + SELECT + f.fileid + FROM + *PREFIX*cte_folders_all f + WHERE + f.name = \'.archive\' + UNION ALL + SELECT + f.fileid + FROM + *PREFIX*filecache f + INNER JOIN *PREFIX*cte_folders c + ON (f.parent = c.fileid) + )'; + trait TimelineQueryDays { protected IDBConnection $connection; @@ -231,9 +264,12 @@ trait TimelineQueryDays $params = $query->getParameters(); $types = $query->getParameterTypes(); + // Get SQL + $CTE_SQL = $params['cteFoldersArchive'] ? CTE_FOLDERS_ARCHIVE : CTE_FOLDERS; + // Add WITH clause if needed if (false !== strpos($sql, 'cte_folders')) { - $sql = CTE_FOLDERS.' '.$sql; + $sql = $CTE_SQL.' '.$sql; } return $this->connection->executeQuery($sql, $params, $types); @@ -247,31 +283,16 @@ trait TimelineQueryDays Folder &$folder, bool $archive ) { - // Query parameters, set at the end - $topFolderId = $folder->getId(); - $excludedFolderId = -1; - - /** @var Folder Archive folder if it exists */ - $archiveFolder = null; - - try { - $archiveFolder = $folder->get('.archive/'); - } catch (\OCP\Files\NotFoundException $e) { - } - - if (!$archive) { - // Exclude archive folder - if ($archiveFolder) { - $excludedFolderId = $archiveFolder->getId(); - } - } else { - // Only include archive folder - $topFolderId = $archiveFolder ? $archiveFolder->getId() : -1; + // Get storages recursively + $topFolderIds = [$folder->getId()]; + $mounts = \OC\Files\Filesystem::getMountManager()->findIn($folder->getPath()); + foreach ($mounts as &$mount) { + $topFolderIds[] = $mount->getStorageRootId(); } // Add query parameters - $query->setParameter('topFolderId', $topFolderId, IQueryBuilder::PARAM_INT); - $query->setParameter('excludedFolderId', $excludedFolderId, IQueryBuilder::PARAM_INT); + $query->setParameter('topFolderIds', $topFolderIds, IQueryBuilder::PARAM_INT_ARRAY); + $query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL); } /** diff --git a/src/components/Settings.vue b/src/components/Settings.vue index 43839041..ecbc95f0 100644 --- a/src/components/Settings.vue +++ b/src/components/Settings.vue @@ -91,10 +91,11 @@ export default class Settings extends Mixins(UserConfig, GlobalMixin) { } async chooseTimelinePath() { - const newPath = await this.chooseFolder( + let newPath = await this.chooseFolder( this.t("memories", "Choose the root of your timeline"), this.config_timelinePath ); + if (newPath === "") newPath = "/"; if (newPath !== this.config_timelinePath) { this.config_timelinePath = newPath; await this.updateSetting("timelinePath"); @@ -102,10 +103,11 @@ export default class Settings extends Mixins(UserConfig, GlobalMixin) { } async chooseFoldersPath() { - const newPath = await this.chooseFolder( + let newPath = await this.chooseFolder( this.t("memories", "Choose the root for the folders view"), this.config_foldersPath ); + if (newPath === "") newPath = "/"; if (newPath !== this.config_foldersPath) { this.config_foldersPath = newPath; await this.updateSetting("foldersPath"); From 6c49ace00a42829c8cd82d85f84c19b6fd88ce82 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 07:16:51 -0800 Subject: [PATCH 138/163] edit-date: fix saveMany call (fix #203) --- src/components/modal/EditDate.vue | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/modal/EditDate.vue b/src/components/modal/EditDate.vue index fbf99c0b..52c5cc82 100644 --- a/src/components/modal/EditDate.vue +++ b/src/components/modal/EditDate.vue @@ -335,12 +335,11 @@ export default class EditDate extends Mixins(GlobalMixin) { const offset = date.getTime() - pDate.getTime(); const scale = diff > 0 ? diffNew / diff : 0; const pDateNew = new Date(dateNew.getTime() - offset * scale); - const res = await axios.patch( - generateUrl(EDIT_API_URL, { id: p.fileid }), - { - date: this.getExifFormat(pDateNew), - } - ); + await axios.patch(generateUrl(EDIT_API_URL, { id: p.fileid }), { + raw: { + DateTimeOriginal: this.getExifFormat(pDateNew), + }, + }); emit("files:file:updated", { fileid: p.fileid }); } catch (e) { if (e.response?.data?.message) { From f1e9765814c10dd2f7a94ae8eab26ae64563f376 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 18:29:26 -0800 Subject: [PATCH 139/163] folders: fix byref error (fix #207) --- lib/Controller/FoldersTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller/FoldersTrait.php b/lib/Controller/FoldersTrait.php index 847e9fb8..37c5d217 100644 --- a/lib/Controller/FoldersTrait.php +++ b/lib/Controller/FoldersTrait.php @@ -34,7 +34,7 @@ trait FoldersTrait return [ 'dayid' => \OCA\Memories\Util::$TAG_DAYID_FOLDERS, 'count' => \count($folders), - 'detail' => array_map(function (&$node) use (&$folder) { + 'detail' => array_map(function ($node) use (&$folder) { return [ 'fileid' => $node->getId(), 'name' => $node->getName(), From 4c786796dae610e1abd2b8528b85b135d321b56a Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Wed, 16 Nov 2022 03:16:56 +0000 Subject: [PATCH 140/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/de.js | 32 ++++++++++++++++++++++++++++++-- l10n/de.json | 32 ++++++++++++++++++++++++++++++-- l10n/fr.js | 13 +++++++++++++ l10n/fr.json | 13 +++++++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) diff --git a/l10n/de.js b/l10n/de.js index 3369af5f..a7f809f7 100644 --- a/l10n/de.js +++ b/l10n/de.js @@ -3,6 +3,7 @@ OC.L10N.register( { "Memories" : "Erinnerungen", "Yet another photo management app" : "Eine weitere App zur Verwaltung von Fotos", + "# Memories\n\nMemories is a *batteries-included* photo management solution for Nextcloud with advanced features including:\n\n- **📸 Timeline**: Sort photos and videos by date taken, parsed from Exif data.\n- **⏪ Rewind**: Jump to any time in the past instantly and relive your memories.\n- **🤖 AI Tagging**: Group photos by people and objects using AI, powered by [recognize](https://github.com/nextcloud/recognize).\n- **🖼️ Albums**: Create albums to group photos and videos together. Then share these albums with others.\n- **🫱🏻‍🫲🏻 External Sharing**: Share photos and videos with people outside of your Nextcloud instance.\n- **📱 Mobile Support**: Works on devices of any shape and size through the web app.\n- **✏️ Edit Metadata**: Edit dates on photos quickly and easily.\n- **📦 Archive**: Store photos you don't want to see in your timeline in a separate folder.\n- **📹 Video Transcoding**: Memories transcodes videos and uses HLS for maximal performance.\n- **⚡️ Performance**: In general, Memories is extremely fast.\n\n## 🌐 Online Demo\n\n- To get an idea of what memories looks and feels like, check out the [public demo](https://memories-demo.radialapps.com/apps/memories/).\n- The demo is read-only and may be slow (free tier VM from [Oracle Cloud](https://www.oracle.com/cloud/free/)).\n- Photo credits go to [Unsplash](https://unsplash.com/) (for individual credits, refer to each folder).\n\n## 🚀 Installation\n\n1. Install the app from the Nextcloud app store.\n1. Perform the recommended [configuration steps](https://github.com/pulsejet/memories/wiki/Extra-Configuration).\n1. Run `php ./occ memories:index` to generate metadata indices for existing photos.\n1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos." : "# Erinnerungen\n\nMemories ist eine Fotoverwaltungs-App für Nextcloud mit erweiterten Funktionen, darunter:\n\n- **📸 Zeitleiste**: Fotos und Videos nach Aufnahmedatum sortieren, geparst aus Exif-Daten.\n- **⏪ Zurückspulen**: Springe sofort zu einem beliebigen Zeitpunkt in der Vergangenheit und erlebe deine Erinnerungen erneut.\n- **🤖 KI-Tagging**: Gruppiere Fotos nach Personen und Objekten mithilfe von KI, unterstützt von der App [recognize](https://github.com/nextcloud/recognize).\n- **🖼️ Alben**: Erstelle Alben, um Fotos und Videos zu gruppieren. Dann teile diese Alben mit anderen.\n- **📁 Ordner**: Durchsuche deine eigenen und freigegebenen Ordner mit einer ähnlichen, effizienten Zeitleiste.\n- **🎦 Diashow**: Zeige ganz einfach Fotos aus deinerr Chronik und deinen Ordnern an.\n- **📱 Mobiler Support**: Funktioniert auf Geräten jeder Form und Größe über die Web-App.\n- **✏️ Metadaten bearbeiten**: Bearbeite Exif-Daten auf Fotos schnell und einfach.\n- **📦 Archiv**: Speichere Fotos, die du nicht in deiner Chronik sehen möchtest, in einem separaten Ordner.\n- **📹 Videotranskodierung**: Memories transkodiert Videos und verwendet HLS für maximale Leistung.\n- **📷 RAW-Unterstützung**: Zeige RAW-Fotos von deiner Kamera mit der App [Camera RAW Previews](https://apps.nextcloud.com/apps/camerarawpreviews) an.\n- **⚡️ Schnell**: Memories ist extrem schnell. Zeitraum.\n\nUm eine Vorstellung davon zu bekommen, wie Erinnerungen aussehen und sich anfühlen, sehe dir die [öffentliche Demo](https://memories-demo.radialapps.com/apps/memories/) an. Beachte, dass die Demo schreibgeschützt ist und möglicherweise langsam ist, da sie in einer von [Oracle Cloud] (https://www.oracle.com/cloud/free/) bereitgestellten Low-End-VM mit kostenlosem Kontingent ausgeführt wird. Fotonachweise gehen zu [Unsplash](https://unsplash.com/) (Einzelnachweise findest du in jedem Ordner).\n\n## 🚀 Installation\n\n1. Installiere die App aus dem Nextcloud App Store\n1. Führe `php ./occ memory:index` aus, um Metadaten-Indizes für vorhandene Fotos zu generieren.\n1. Öffne die App 📷 Erinnerungen in Nextcloud und lege das Verzeichnis mit deinen Fotos fest. Fotos aus diesem Verzeichnis werden in der Zeitleiste angezeigt, einschließlich aller Fotos in verschachtelten Unterverzeichnissen.\n1. Die Installation des [Vorschaugenerators](https://github.com/rullzer/previewgenerator) zum Vorgenerieren von Miniaturansichten wird dringend empfohlen.", "Settings" : "Einstellungen", "Timeline" : "Verlauf", "Folders" : "Ordner", @@ -14,6 +15,7 @@ OC.L10N.register( "On this day" : "An diesem Tag", "Tags" : "Schlagworte", "Maps" : "Karten", + "EXIF" : "EXIF", "A better photos experience awaits you" : "Ein besseres Fotoerlebnis erwartet dich", "Choose the root folder of your timeline to begin" : "Wähle das Wurzelverzeichnis deiner Zeitleiste, um zu beginnen", "If you just installed Memories, run:" : "Wenn du Memorys gerade installiert hast, führe Folgendes aus:", @@ -23,14 +25,20 @@ OC.L10N.register( "You can always change this later in settings" : "Du kannst das auch noch später in den Einstellungen ändern.", "Choose the root of your timeline" : "Wähle den Start deiner Zeitleiste aus", "The selected folder does not seem to be valid. Try again." : "Der ausgewählte Ordner scheint ungültig zu sein. Versuche es nochmal.", + "Found {total} photos in {path}" : "{total} Fotos gefunden in {path}", + "Failed to get Exif data. Metadata may be lost!" : "Exif-Daten konnten nicht abgerufen werden. Metadaten können verloren gehen!", + "No Exif data found! Continue?" : "Keine Exif-Daten gefunden! Fortsetzen?", + "Image saved successfully" : "Bild erfolgreich gespeichert", + "Error saving image" : "Fehler beim Speichern des Bildes", "Unsaved changes" : "Ungespeicherte Änderungen", - "Drop changes" : "Änderungen löschen", + "Drop changes" : "Änderungen verwerfen", "Edit" : "Bearbeiten", "Loading …" : "Lade …", "Cancel" : "Abbrechen", "Delete" : "Löschen", + "Remove from album" : "Aus dem Album entfernen", "Download" : "Herunterladen", - "Favorite" : "Favorit", + "Favorite" : "Favorisieren", "Unarchive" : "Dearchivieren", "Edit Date/Time" : "Datum/Uhrzeit bearbeiten", "View in folder" : "In Ordner anzeigen", @@ -40,6 +48,7 @@ OC.L10N.register( "You are about to download a large number of files. Are you sure?" : "Du bist dabei, eine große Anzahl von Dateien herunterzuladen. Bist du dir sicher?", "You are about to delete a large number of files. Are you sure?" : "Du bist dabei, eine große Anzahl von Dateien zu löschen. Bist du dir sicher?", "You are about to touch a large number of files. Are you sure?" : "Du bist dabei, eine große Anzahl von Dateien zu ändern. Bist du dir sicher?", + "Could not remove photos from album" : "Fotos konnten nicht aus dem Album entfernt werden", "_{n} selected_::_{n} selected_" : ["{n} ausgewählt","{n} ausgewählt"], "Timeline Path" : "Pfad der Zeitlachse", "Folders Path" : "Ordnerpfad", @@ -50,7 +59,10 @@ OC.L10N.register( "Failed to load some photos" : "Laden einiger Fotos fehlgeschlagen", "Share" : "Teilen", "Sidebar" : "Seitenleiste", + "Video sharing not supported yet" : "Teilen von Videos wird bislang nicht unterstützt", + "Cannot share this type of data" : "Diese Art von Daten kann nicht geteilt werden", "Processing … {n}/{m}" : "Verarbeite … {n}/{m}", + "{n} photos added to album" : "{n} Fotos zum Album hinzugefügt", "Search for collaborators" : "Suche nach Mitbearbeitenden", "Search people or groups" : "Nach Benutzer oder Gruppen suchen", "Add {collaboratorLabel} to the collaborators list" : "{collaboratorLabel} zur Liste der Mitarbeitenden hinzufügen", @@ -69,6 +81,8 @@ OC.L10N.register( "New album" : "Neues Album", "Create new album" : "Neues Album erstellen", "Edit album details" : "Albumdetails bearbeiten", + "Could not load the selected album" : "Gewähltes Album konnte nicht geladen werden", + "Remove Album" : "Album entfernen", "Failed to delete {name}." : "{name} konnte nicht gelöscht werden.", "Name of the album" : "Name des Albums", "Location of the album" : "Ort des Albums", @@ -81,7 +95,10 @@ OC.L10N.register( "Create album" : "Album erstellen", "Add selection to album {albumName}" : "Auswahl zum Album {albumName} hinzufügen", "Create a new album." : "Ein neues Album erstellen", + "_Share with %n user_::_Share with %n users_" : ["Mit %n Benutzer teilen","Mit %n Benutzern telken"], + "_%n item_::_%n items_" : ["%n Element","%n Elemente"], "Save collaborators for this album." : "Mitbearbeitende für dieses Album speichern.", + "Share Album" : "Album teilen", "Year" : "Jahr", "Month" : "Monat", "Day" : "Tag", @@ -95,6 +112,7 @@ OC.L10N.register( "Exercise caution and make sure you have backups." : "Sei vorsichtig und stelle sicher, dass du Backups hast.", "Loading data … {n}/{m}" : "Lade … {n}/{m}", "Remove person" : "Person entfernen", + "Are you sure you want to remove {name}?" : "Soll {name} wirklich entfernt werden?", "Name" : "Name", "Rename person" : "Person umbenennen", "Update" : "Aktualisieren", @@ -105,7 +123,13 @@ OC.L10N.register( "Error while moving {basename}" : "Fehler beim Verschieben von {basename}", "Failed to move {name}." : "{name} konnte nicht verschoben werden.", "Move selected photos to person" : "Ausgewählte Fotos zu einer Person verschieben", + "Are you sure you want to move the selected photos from {name} to {newName}?" : "Möchtest du die ausgewählten Fotos wirklich von {name} nach {newName} verschieben?", + "Share Folder" : "Ordner teilen", + "You cannot share the root folder" : "Du kannst den Wurzelordner nicht teilen", + "Use the sidebar to share this folder." : "Verwende die Seitenleiste, um diesen Ordner zu teilen.", + "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Wenn du eine öffentliche Linkfreigabe erstellst, klicke auf Aktualisieren und ein entsprechender Link zu Memories wird unten angezeigt.", "Refresh" : "Aktualisieren", + "Share album" : "Album teilen", "Delete album" : "Album löschen", "Merge with different person" : "Mit einer anderen Person zusammenführen", "Mark person in preview" : "Person in Vorschau markieren", @@ -196,14 +220,18 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Beachte, dass der ausgewählte Zuschneidebereich kleiner ist als die angewendete Größenänderung, was zu Qualitätseinbußen führen kann.", "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", + "Transcoding failed." : "Transkodierung fehlgeschlagen", "Auto" : "Automatisch", + "Shared Folder" : "Geteilter Ordner", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", "General Failure" : "Allgemeiner Fehler", "Error: {msg}" : "Fehler: {msg}", "Failed to delete files." : "Löschen der Dateien fehlgeschlagen", "Failed to delete {fileName}." : "{fileName} konnte nicht gelöscht werden.", + "Failed to download some files." : "Einige Dateien konnten nicht heruntergeladen werden.", "Failed to favorite files." : "Favorisieren von Dateien fehlgeschlagen", + "Failed to favorite some files." : "Einige Dateien konnten nicht zu den Favoriten hinzugefügt werden.", "Failed to favorite {fileName}." : "{fileName} konnte nicht zu den Favoriten hinzugefügt werden." }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/de.json b/l10n/de.json index 2548d1f4..9a2a67bf 100644 --- a/l10n/de.json +++ b/l10n/de.json @@ -1,6 +1,7 @@ { "translations": { "Memories" : "Erinnerungen", "Yet another photo management app" : "Eine weitere App zur Verwaltung von Fotos", + "# Memories\n\nMemories is a *batteries-included* photo management solution for Nextcloud with advanced features including:\n\n- **📸 Timeline**: Sort photos and videos by date taken, parsed from Exif data.\n- **⏪ Rewind**: Jump to any time in the past instantly and relive your memories.\n- **🤖 AI Tagging**: Group photos by people and objects using AI, powered by [recognize](https://github.com/nextcloud/recognize).\n- **🖼️ Albums**: Create albums to group photos and videos together. Then share these albums with others.\n- **🫱🏻‍🫲🏻 External Sharing**: Share photos and videos with people outside of your Nextcloud instance.\n- **📱 Mobile Support**: Works on devices of any shape and size through the web app.\n- **✏️ Edit Metadata**: Edit dates on photos quickly and easily.\n- **📦 Archive**: Store photos you don't want to see in your timeline in a separate folder.\n- **📹 Video Transcoding**: Memories transcodes videos and uses HLS for maximal performance.\n- **⚡️ Performance**: In general, Memories is extremely fast.\n\n## 🌐 Online Demo\n\n- To get an idea of what memories looks and feels like, check out the [public demo](https://memories-demo.radialapps.com/apps/memories/).\n- The demo is read-only and may be slow (free tier VM from [Oracle Cloud](https://www.oracle.com/cloud/free/)).\n- Photo credits go to [Unsplash](https://unsplash.com/) (for individual credits, refer to each folder).\n\n## 🚀 Installation\n\n1. Install the app from the Nextcloud app store.\n1. Perform the recommended [configuration steps](https://github.com/pulsejet/memories/wiki/Extra-Configuration).\n1. Run `php ./occ memories:index` to generate metadata indices for existing photos.\n1. Open the 📷 Memories app in Nextcloud and set the directory containing your photos." : "# Erinnerungen\n\nMemories ist eine Fotoverwaltungs-App für Nextcloud mit erweiterten Funktionen, darunter:\n\n- **📸 Zeitleiste**: Fotos und Videos nach Aufnahmedatum sortieren, geparst aus Exif-Daten.\n- **⏪ Zurückspulen**: Springe sofort zu einem beliebigen Zeitpunkt in der Vergangenheit und erlebe deine Erinnerungen erneut.\n- **🤖 KI-Tagging**: Gruppiere Fotos nach Personen und Objekten mithilfe von KI, unterstützt von der App [recognize](https://github.com/nextcloud/recognize).\n- **🖼️ Alben**: Erstelle Alben, um Fotos und Videos zu gruppieren. Dann teile diese Alben mit anderen.\n- **📁 Ordner**: Durchsuche deine eigenen und freigegebenen Ordner mit einer ähnlichen, effizienten Zeitleiste.\n- **🎦 Diashow**: Zeige ganz einfach Fotos aus deinerr Chronik und deinen Ordnern an.\n- **📱 Mobiler Support**: Funktioniert auf Geräten jeder Form und Größe über die Web-App.\n- **✏️ Metadaten bearbeiten**: Bearbeite Exif-Daten auf Fotos schnell und einfach.\n- **📦 Archiv**: Speichere Fotos, die du nicht in deiner Chronik sehen möchtest, in einem separaten Ordner.\n- **📹 Videotranskodierung**: Memories transkodiert Videos und verwendet HLS für maximale Leistung.\n- **📷 RAW-Unterstützung**: Zeige RAW-Fotos von deiner Kamera mit der App [Camera RAW Previews](https://apps.nextcloud.com/apps/camerarawpreviews) an.\n- **⚡️ Schnell**: Memories ist extrem schnell. Zeitraum.\n\nUm eine Vorstellung davon zu bekommen, wie Erinnerungen aussehen und sich anfühlen, sehe dir die [öffentliche Demo](https://memories-demo.radialapps.com/apps/memories/) an. Beachte, dass die Demo schreibgeschützt ist und möglicherweise langsam ist, da sie in einer von [Oracle Cloud] (https://www.oracle.com/cloud/free/) bereitgestellten Low-End-VM mit kostenlosem Kontingent ausgeführt wird. Fotonachweise gehen zu [Unsplash](https://unsplash.com/) (Einzelnachweise findest du in jedem Ordner).\n\n## 🚀 Installation\n\n1. Installiere die App aus dem Nextcloud App Store\n1. Führe `php ./occ memory:index` aus, um Metadaten-Indizes für vorhandene Fotos zu generieren.\n1. Öffne die App 📷 Erinnerungen in Nextcloud und lege das Verzeichnis mit deinen Fotos fest. Fotos aus diesem Verzeichnis werden in der Zeitleiste angezeigt, einschließlich aller Fotos in verschachtelten Unterverzeichnissen.\n1. Die Installation des [Vorschaugenerators](https://github.com/rullzer/previewgenerator) zum Vorgenerieren von Miniaturansichten wird dringend empfohlen.", "Settings" : "Einstellungen", "Timeline" : "Verlauf", "Folders" : "Ordner", @@ -12,6 +13,7 @@ "On this day" : "An diesem Tag", "Tags" : "Schlagworte", "Maps" : "Karten", + "EXIF" : "EXIF", "A better photos experience awaits you" : "Ein besseres Fotoerlebnis erwartet dich", "Choose the root folder of your timeline to begin" : "Wähle das Wurzelverzeichnis deiner Zeitleiste, um zu beginnen", "If you just installed Memories, run:" : "Wenn du Memorys gerade installiert hast, führe Folgendes aus:", @@ -21,14 +23,20 @@ "You can always change this later in settings" : "Du kannst das auch noch später in den Einstellungen ändern.", "Choose the root of your timeline" : "Wähle den Start deiner Zeitleiste aus", "The selected folder does not seem to be valid. Try again." : "Der ausgewählte Ordner scheint ungültig zu sein. Versuche es nochmal.", + "Found {total} photos in {path}" : "{total} Fotos gefunden in {path}", + "Failed to get Exif data. Metadata may be lost!" : "Exif-Daten konnten nicht abgerufen werden. Metadaten können verloren gehen!", + "No Exif data found! Continue?" : "Keine Exif-Daten gefunden! Fortsetzen?", + "Image saved successfully" : "Bild erfolgreich gespeichert", + "Error saving image" : "Fehler beim Speichern des Bildes", "Unsaved changes" : "Ungespeicherte Änderungen", - "Drop changes" : "Änderungen löschen", + "Drop changes" : "Änderungen verwerfen", "Edit" : "Bearbeiten", "Loading …" : "Lade …", "Cancel" : "Abbrechen", "Delete" : "Löschen", + "Remove from album" : "Aus dem Album entfernen", "Download" : "Herunterladen", - "Favorite" : "Favorit", + "Favorite" : "Favorisieren", "Unarchive" : "Dearchivieren", "Edit Date/Time" : "Datum/Uhrzeit bearbeiten", "View in folder" : "In Ordner anzeigen", @@ -38,6 +46,7 @@ "You are about to download a large number of files. Are you sure?" : "Du bist dabei, eine große Anzahl von Dateien herunterzuladen. Bist du dir sicher?", "You are about to delete a large number of files. Are you sure?" : "Du bist dabei, eine große Anzahl von Dateien zu löschen. Bist du dir sicher?", "You are about to touch a large number of files. Are you sure?" : "Du bist dabei, eine große Anzahl von Dateien zu ändern. Bist du dir sicher?", + "Could not remove photos from album" : "Fotos konnten nicht aus dem Album entfernt werden", "_{n} selected_::_{n} selected_" : ["{n} ausgewählt","{n} ausgewählt"], "Timeline Path" : "Pfad der Zeitlachse", "Folders Path" : "Ordnerpfad", @@ -48,7 +57,10 @@ "Failed to load some photos" : "Laden einiger Fotos fehlgeschlagen", "Share" : "Teilen", "Sidebar" : "Seitenleiste", + "Video sharing not supported yet" : "Teilen von Videos wird bislang nicht unterstützt", + "Cannot share this type of data" : "Diese Art von Daten kann nicht geteilt werden", "Processing … {n}/{m}" : "Verarbeite … {n}/{m}", + "{n} photos added to album" : "{n} Fotos zum Album hinzugefügt", "Search for collaborators" : "Suche nach Mitbearbeitenden", "Search people or groups" : "Nach Benutzer oder Gruppen suchen", "Add {collaboratorLabel} to the collaborators list" : "{collaboratorLabel} zur Liste der Mitarbeitenden hinzufügen", @@ -67,6 +79,8 @@ "New album" : "Neues Album", "Create new album" : "Neues Album erstellen", "Edit album details" : "Albumdetails bearbeiten", + "Could not load the selected album" : "Gewähltes Album konnte nicht geladen werden", + "Remove Album" : "Album entfernen", "Failed to delete {name}." : "{name} konnte nicht gelöscht werden.", "Name of the album" : "Name des Albums", "Location of the album" : "Ort des Albums", @@ -79,7 +93,10 @@ "Create album" : "Album erstellen", "Add selection to album {albumName}" : "Auswahl zum Album {albumName} hinzufügen", "Create a new album." : "Ein neues Album erstellen", + "_Share with %n user_::_Share with %n users_" : ["Mit %n Benutzer teilen","Mit %n Benutzern telken"], + "_%n item_::_%n items_" : ["%n Element","%n Elemente"], "Save collaborators for this album." : "Mitbearbeitende für dieses Album speichern.", + "Share Album" : "Album teilen", "Year" : "Jahr", "Month" : "Monat", "Day" : "Tag", @@ -93,6 +110,7 @@ "Exercise caution and make sure you have backups." : "Sei vorsichtig und stelle sicher, dass du Backups hast.", "Loading data … {n}/{m}" : "Lade … {n}/{m}", "Remove person" : "Person entfernen", + "Are you sure you want to remove {name}?" : "Soll {name} wirklich entfernt werden?", "Name" : "Name", "Rename person" : "Person umbenennen", "Update" : "Aktualisieren", @@ -103,7 +121,13 @@ "Error while moving {basename}" : "Fehler beim Verschieben von {basename}", "Failed to move {name}." : "{name} konnte nicht verschoben werden.", "Move selected photos to person" : "Ausgewählte Fotos zu einer Person verschieben", + "Are you sure you want to move the selected photos from {name} to {newName}?" : "Möchtest du die ausgewählten Fotos wirklich von {name} nach {newName} verschieben?", + "Share Folder" : "Ordner teilen", + "You cannot share the root folder" : "Du kannst den Wurzelordner nicht teilen", + "Use the sidebar to share this folder." : "Verwende die Seitenleiste, um diesen Ordner zu teilen.", + "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Wenn du eine öffentliche Linkfreigabe erstellst, klicke auf Aktualisieren und ein entsprechender Link zu Memories wird unten angezeigt.", "Refresh" : "Aktualisieren", + "Share album" : "Album teilen", "Delete album" : "Album löschen", "Merge with different person" : "Mit einer anderen Person zusammenführen", "Mark person in preview" : "Person in Vorschau markieren", @@ -194,14 +218,18 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Beachte, dass der ausgewählte Zuschneidebereich kleiner ist als die angewendete Größenänderung, was zu Qualitätseinbußen führen kann.", "Actual size (100%)" : "Tatsächliche Größe (100%)", "Fit size" : "Größe anpassen", + "Transcoding failed." : "Transkodierung fehlgeschlagen", "Auto" : "Automatisch", + "Shared Folder" : "Geteilter Ordner", "Failed to create {albumName}." : "{albumName} konnte nicht erstellt werden.", "Failed to rename {currentAlbumName} to {newAlbumName}." : "{currentAlbumName} konnte nicht in {newAlbumName} umbenannt werden.", "General Failure" : "Allgemeiner Fehler", "Error: {msg}" : "Fehler: {msg}", "Failed to delete files." : "Löschen der Dateien fehlgeschlagen", "Failed to delete {fileName}." : "{fileName} konnte nicht gelöscht werden.", + "Failed to download some files." : "Einige Dateien konnten nicht heruntergeladen werden.", "Failed to favorite files." : "Favorisieren von Dateien fehlgeschlagen", + "Failed to favorite some files." : "Einige Dateien konnten nicht zu den Favoriten hinzugefügt werden.", "Failed to favorite {fileName}." : "{fileName} konnte nicht zu den Favoriten hinzugefügt werden." },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/fr.js b/l10n/fr.js index fa6dc40a..4a8fa48c 100644 --- a/l10n/fr.js +++ b/l10n/fr.js @@ -14,7 +14,14 @@ OC.L10N.register( "On this day" : "Ce même jour", "Tags" : "Étiquettes", "Maps" : "Cartes", + "Choose the root folder of your timeline to begin" : "Choisissez le dossier racine de votre fil chronologique pour commencer", "If you just installed Memories, run:" : "Si vous venez d'installer Souvenirs, exécuter :", + "Continue to Memories" : "Continuer vers Souvenirs", + "Choose again" : "Choisir à nouveau", + "Click here to start" : "Cliquer ici pour commencer", + "You can always change this later in settings" : "Vous pouvez toujours changer cela ultérieurement dans les paramètres", + "Choose the root of your timeline" : "Choisissez le début de votre fil chronologique", + "The selected folder does not seem to be valid. Try again." : "Le dossier sélectionné ne semble pas être valide. Essayer à nouveau.", "Image saved successfully" : "Image enregistrée avec succès", "Error saving image" : "Erreur lors de l'enregistrement de l'image", "Unsaved changes" : "Modifications non enregistrées", @@ -36,6 +43,7 @@ OC.L10N.register( "You are about to touch a large number of files. Are you sure?" : "Vous êtes sur le point de modifier un grand nombre de fichiers. Êtes-vous sûr(e) ?", "_{n} selected_::_{n} selected_" : ["{n} sélectionné","{n} sélectionnés","{n} sélectionnés"], "Timeline Path" : "Emplacement du Fil chronologique", + "Folders Path" : "Chemin du dossier", "Show hidden folders" : "Afficher les dossiers cachés", "Your Timeline" : "Votre fil chronologique", "Failed to load some photos" : "Échec du chargement de certaines photos", @@ -93,10 +101,15 @@ OC.L10N.register( "Rename person" : "Renommer la personne", "Update" : "Mise à jour", "Failed to rename {oldName} to {name}." : "Échec du renommage de {oldName} en {name}.", + "You cannot share the root folder" : "Vous ne pouvez pas partager le dossier racine", + "Use the sidebar to share this folder." : "Utiliser la barre latérale pour partager ce dossier.", + "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si vous créez un partage de lien public, cliquez sur rafraîchir et un lien correspondant à Souvenirs sera visible ci-dessous.", "Refresh" : "Actualiser", "Delete album" : "Supprimer l'album", "Merge with different person" : "Fusionner avec une différente personne", "Share folder" : "Partager le dossier", + "Move left" : "Vers la gauche", + "Move right" : "Vers la droite", "Save as" : "Enregistrer sous", "Reset" : "Réinitialiser", "All changes will be lost." : "Tous les changements seront perdus.", diff --git a/l10n/fr.json b/l10n/fr.json index d0be5c33..c9670f8b 100644 --- a/l10n/fr.json +++ b/l10n/fr.json @@ -12,7 +12,14 @@ "On this day" : "Ce même jour", "Tags" : "Étiquettes", "Maps" : "Cartes", + "Choose the root folder of your timeline to begin" : "Choisissez le dossier racine de votre fil chronologique pour commencer", "If you just installed Memories, run:" : "Si vous venez d'installer Souvenirs, exécuter :", + "Continue to Memories" : "Continuer vers Souvenirs", + "Choose again" : "Choisir à nouveau", + "Click here to start" : "Cliquer ici pour commencer", + "You can always change this later in settings" : "Vous pouvez toujours changer cela ultérieurement dans les paramètres", + "Choose the root of your timeline" : "Choisissez le début de votre fil chronologique", + "The selected folder does not seem to be valid. Try again." : "Le dossier sélectionné ne semble pas être valide. Essayer à nouveau.", "Image saved successfully" : "Image enregistrée avec succès", "Error saving image" : "Erreur lors de l'enregistrement de l'image", "Unsaved changes" : "Modifications non enregistrées", @@ -34,6 +41,7 @@ "You are about to touch a large number of files. Are you sure?" : "Vous êtes sur le point de modifier un grand nombre de fichiers. Êtes-vous sûr(e) ?", "_{n} selected_::_{n} selected_" : ["{n} sélectionné","{n} sélectionnés","{n} sélectionnés"], "Timeline Path" : "Emplacement du Fil chronologique", + "Folders Path" : "Chemin du dossier", "Show hidden folders" : "Afficher les dossiers cachés", "Your Timeline" : "Votre fil chronologique", "Failed to load some photos" : "Échec du chargement de certaines photos", @@ -91,10 +99,15 @@ "Rename person" : "Renommer la personne", "Update" : "Mise à jour", "Failed to rename {oldName} to {name}." : "Échec du renommage de {oldName} en {name}.", + "You cannot share the root folder" : "Vous ne pouvez pas partager le dossier racine", + "Use the sidebar to share this folder." : "Utiliser la barre latérale pour partager ce dossier.", + "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si vous créez un partage de lien public, cliquez sur rafraîchir et un lien correspondant à Souvenirs sera visible ci-dessous.", "Refresh" : "Actualiser", "Delete album" : "Supprimer l'album", "Merge with different person" : "Fusionner avec une différente personne", "Share folder" : "Partager le dossier", + "Move left" : "Vers la gauche", + "Move right" : "Vers la droite", "Save as" : "Enregistrer sous", "Reset" : "Réinitialiser", "All changes will be lost." : "Tous les changements seront perdus.", From 0c6d5a57b58e22839de04df3de4ec7fa88ca7c39 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 21:05:11 -0800 Subject: [PATCH 141/163] Fix filename of recursive mounts --- lib/Db/TimelineQueryDays.php | 98 ++++++++++++++++++++++++------------ src/components/Timeline.vue | 4 +- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 23c405cb..dee83296 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -9,16 +9,18 @@ use OCP\Files\Folder; use OCP\IDBConnection; const CTE_FOLDERS = // CTE to get all folders recursively in the given top folders excluding archive - 'WITH RECURSIVE *PREFIX*cte_folders(fileid) AS ( + 'WITH RECURSIVE *PREFIX*cte_folders(fileid, rootid) AS ( SELECT - f.fileid + f.fileid, + f.fileid AS rootid FROM *PREFIX*filecache f WHERE f.fileid IN (:topFolderIds) UNION ALL SELECT - f.fileid + f.fileid, + c.rootid FROM *PREFIX*filecache f INNER JOIN *PREFIX*cte_folders c @@ -65,6 +67,9 @@ trait TimelineQueryDays { protected IDBConnection $connection; + /** Map of rootid => mount point */ + private $topFolderPaths = []; + /** * Get the days response from the database for the timeline. * @@ -196,30 +201,51 @@ trait TimelineQueryDays */ private function processDay(&$day, $uid, $folder) { - $basePath = '#__#__#'; - $davPath = ''; + /** + * Path entry in database for folder. + * We need to splice this from the start of the file path. + */ + $internalPaths = []; + + /** + * DAV paths for the folders. + * We need to prefix this to the start of the file path. + */ + $davPaths = []; + + /** + * The root folder id for the folder. + * We fallback to this if rootid is not found + */ + $defaultRootId = 0; + if (null !== $folder) { + // Get root id of the top folder + $defaultRootId = $folder->getId(); + // No way to get the internal path from the folder $query = $this->connection->getQueryBuilder(); - $query->select('path') + $query->select('fileid', 'path') ->from('filecache') - ->where($query->expr()->eq('fileid', $query->createNamedParameter($folder->getId(), IQueryBuilder::PARAM_INT))) + ->where($query->expr()->in('fileid', $query->createNamedParameter(array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY))) ; - $path = $query->executeQuery()->fetchOne(); - $basePath = $path ?: $basePath; + $paths = $query->executeQuery()->fetchAll(); + foreach ($paths as &$path) { + $fileid = (int) $path['fileid']; + $internalPaths[$fileid] = $path['path']; - // Get user facing path - // getPath looks like /user/files/... but we want /files/user/... - // Split at / and swap these - // For public shares, we just give the relative path - if (!empty($uid)) { - $actualPath = $folder->getPath(); - $actualPath = explode('/', $actualPath); - if (\count($actualPath) >= 3) { - $tmp = $actualPath[1]; - $actualPath[1] = $actualPath[2]; - $actualPath[2] = $tmp; - $davPath = implode('/', $actualPath); + // Get DAV path. + // getPath looks like /user/files/... but we want /files/user/... + // Split at / and swap these + // For public shares, we just give the relative path + if (!empty($uid) && ($actualPath = $this->topFolderPaths[$fileid])) { + $actualPath = explode('/', $actualPath); + if (\count($actualPath) >= 3) { + $tmp = $actualPath[1]; + $actualPath[1] = $actualPath[2]; + $actualPath[2] = $tmp; + $davPaths[$fileid] = implode('/', $actualPath); + } } } } @@ -245,9 +271,14 @@ trait TimelineQueryDays // Check if path exists and starts with basePath and remove if (isset($row['path']) && !empty($row['path'])) { + $rootId = $row['rootid'] ?: $defaultRootId; + $basePath = $internalPaths[$rootId] ?: '#__#'; + $davPath = $davPaths[$rootId] ?: ''; + if (0 === strpos($row['path'], $basePath)) { $row['filename'] = $davPath.substr($row['path'], \strlen($basePath)); } + unset($row['path']); } @@ -280,18 +311,10 @@ trait TimelineQueryDays */ private function addSubfolderJoinParams( IQueryBuilder &$query, - Folder &$folder, bool $archive ) { - // Get storages recursively - $topFolderIds = [$folder->getId()]; - $mounts = \OC\Files\Filesystem::getMountManager()->findIn($folder->getPath()); - foreach ($mounts as &$mount) { - $topFolderIds[] = $mount->getStorageRootId(); - } - // Add query parameters - $query->setParameter('topFolderIds', $topFolderIds, IQueryBuilder::PARAM_INT_ARRAY); + $query->setParameter('topFolderIds', array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY); $query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL); } @@ -315,12 +338,25 @@ trait TimelineQueryDays return $query->innerJoin('m', 'filecache', 'f', $baseOp); } + // Create top folders paths for later processing + $this->topFolderPaths = []; + $this->topFolderPaths[$folder->getId()] = $folder->getPath(); + // Filter by folder (recursive or otherwise) $pathOp = null; if ($recursive) { + // Add mountpoints recursively + $this->mounts = \OC\Files\Filesystem::getMountManager()->findIn($folder->getPath()); + foreach ($this->mounts as &$mount) { + $id = $mount->getStorageRootId(); + $path = $mount->getMountPoint(); + $this->topFolderPaths[$id] = $path; + } + // Join with folders CTE - $this->addSubfolderJoinParams($query, $folder, $archive); + $this->addSubfolderJoinParams($query, $archive); $query->innerJoin('f', 'cte_folders', 'cte_f', $query->expr()->eq('f.parent', 'cte_f.fileid')); + $query->addSelect('cte_f.rootid'); } else { // If getting non-recursively folder only check for parent $pathOp = $query->expr()->eq('f.parent', $query->createNamedParameter($folder->getId(), IQueryBuilder::PARAM_INT)); diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue index 419ef280..c7bbd2df 100644 --- a/src/components/Timeline.vue +++ b/src/components/Timeline.vue @@ -917,7 +917,9 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) { head.day.detail.length === photos.length && head.day.detail.every( (p, i) => - p.fileid === photos[i].fileid && p.etag === photos[i].etag + p.fileid === photos[i].fileid && + p.etag === photos[i].etag && + p.filename === photos[i].filename ) ) { continue; From 46ac8cf55e8c45370b1d8e8c4290513a3ee67b75 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 21:22:40 -0800 Subject: [PATCH 142/163] Fix archive rootid --- lib/Db/TimelineQueryDays.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index dee83296..bd0a1749 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -31,32 +31,38 @@ const CTE_FOLDERS = // CTE to get all folders recursively in the given top folde )'; const CTE_FOLDERS_ARCHIVE = // CTE to get all archive folders recursively in the given top folders - 'WITH RECURSIVE *PREFIX*cte_folders_all(fileid, name) AS ( + 'WITH RECURSIVE *PREFIX*cte_folders_all(fileid, name, rootid) AS ( SELECT - f.fileid, f.name + f.fileid, + f.name, + f.fileid AS rootid FROM *PREFIX*filecache f WHERE f.fileid IN (:topFolderIds) UNION ALL SELECT - f.fileid, f.name + f.fileid, + f.name, + c.rootid FROM *PREFIX*filecache f INNER JOIN *PREFIX*cte_folders_all c ON (f.parent = c.fileid AND f.mimetype = (SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = \'httpd/unix-directory\') ) - ), *PREFIX*cte_folders(fileid) AS ( + ), *PREFIX*cte_folders(fileid, rootid) AS ( SELECT - f.fileid + cfa.fileid, + cfa.rootid FROM - *PREFIX*cte_folders_all f + *PREFIX*cte_folders_all cfa WHERE - f.name = \'.archive\' + cfa.name = \'.archive\' UNION ALL SELECT - f.fileid + f.fileid, + c.rootid FROM *PREFIX*filecache f INNER JOIN *PREFIX*cte_folders c From c41ad9549afbd1a968cfcc3a6d1a5c35c33b885e Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 21:45:32 -0800 Subject: [PATCH 143/163] Fix archive logic for mounts --- lib/Controller/ArchiveController.php | 71 ++++++++++++++++------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/lib/Controller/ArchiveController.php b/lib/Controller/ArchiveController.php index f6c518b4..c4510489 100644 --- a/lib/Controller/ArchiveController.php +++ b/lib/Controller/ArchiveController.php @@ -64,52 +64,65 @@ class ArchiveController extends ApiBase if (null === $timelineFolder || !$timelineFolder instanceof Folder) { return new JSONResponse(['message' => 'Cannot get timeline'], Http::STATUS_INTERNAL_SERVER_ERROR); } - if (!$timelineFolder->isCreatable()) { - return new JSONResponse(['message' => 'Cannot create archive folder'], Http::STATUS_FORBIDDEN); + + // Bubble up from file until we reach the correct folder + $fileStorageId = $file->getStorage()->getId(); + $parent = $file->getParent(); + $isArchived = false; + while (true) { + if (null === $parent) { + throw new \Exception('Cannot get correct parent of file'); + } + + if ($parent->getPath() === $timelineFolder->getPath()) { + break; + } + + if ($parent->getParent()->getStorage()->getId() !== $fileStorageId) { + break; + } + + if ($parent->getName() === \OCA\Memories\Util::$ARCHIVE_FOLDER) { + $isArchived = true; + break; + } + + $parent = $parent->getParent(); } - // Get path of current file relative to the timeline folder - // remove timelineFolder path from start of file path - $timelinePath = $timelineFolder->getPath(); // no trailing slash - if (substr($file->getPath(), 0, \strlen($timelinePath)) !== $timelinePath) { - return new JSONResponse(['message' => 'Files outside timeline cannot be archived'], Http::STATUS_INTERNAL_SERVER_ERROR); - } - $relativePath = substr($file->getPath(), \strlen($timelinePath)); // has a leading slash - - // Final path of the file including the file name - $destinationPath = ''; + // Get path of current file relative to the parent folder + $relativeFilePath = $parent->getRelativePath($file->getPath()); // Check if we want to archive or unarchive $body = $this->request->getParams(); $unarchive = isset($body['archive']) && false === $body['archive']; + if ($isArchived && !$unarchive) { + return new JSONResponse(['message' => 'File already archived'], Http::STATUS_BAD_REQUEST); + } else if (!$isArchived && $unarchive) { + return new JSONResponse(['message' => 'File not archived'], Http::STATUS_BAD_REQUEST); + } + + // Final path of the file including the file name + $destinationPath = ''; // Get if the file is already in the archive (relativePath starts with archive) - $archiveFolderWithLeadingSlash = '/'.\OCA\Memories\Util::$ARCHIVE_FOLDER; - if (substr($relativePath, 0, \strlen($archiveFolderWithLeadingSlash)) === $archiveFolderWithLeadingSlash) { - // file already in archive, remove it instead - $destinationPath = substr($relativePath, \strlen($archiveFolderWithLeadingSlash)); - if (!$unarchive) { - return new JSONResponse(['message' => 'File already archived'], Http::STATUS_BAD_REQUEST); - } + if ($isArchived) { + // file already in archive, remove it + $destinationPath = $relativeFilePath; + $parent = $parent->getParent(); } else { // file not in archive, put it in there - $destinationPath = Exif::removeExtraSlash(\OCA\Memories\Util::$ARCHIVE_FOLDER.$relativePath); - if ($unarchive) { - return new JSONResponse(['message' => 'File not archived'], Http::STATUS_BAD_REQUEST); - } + $af = \OCA\Memories\Util::$ARCHIVE_FOLDER; + $destinationPath = Exif::removeExtraSlash($af.$relativeFilePath); } // Remove the filename - $destinationFolders = explode('/', $destinationPath); + $destinationFolders = array_filter(explode('/', $destinationPath)); array_pop($destinationFolders); // Create folder tree - $folder = $timelineFolder; + $folder = $parent; foreach ($destinationFolders as $folderName) { - if ('' === $folderName) { - continue; - } - try { $existingFolder = $folder->get($folderName.'/'); if (!$existingFolder instanceof Folder) { From e9f67b24e68bcb9b30aae67cad0be1be20cb1001 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 21:45:52 -0800 Subject: [PATCH 144/163] Lint PHP --- lib/Controller/ArchiveController.php | 4 +++- lib/Db/TimelineQueryDays.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Controller/ArchiveController.php b/lib/Controller/ArchiveController.php index c4510489..1e416d14 100644 --- a/lib/Controller/ArchiveController.php +++ b/lib/Controller/ArchiveController.php @@ -84,6 +84,7 @@ class ArchiveController extends ApiBase if ($parent->getName() === \OCA\Memories\Util::$ARCHIVE_FOLDER) { $isArchived = true; + break; } @@ -98,7 +99,8 @@ class ArchiveController extends ApiBase $unarchive = isset($body['archive']) && false === $body['archive']; if ($isArchived && !$unarchive) { return new JSONResponse(['message' => 'File already archived'], Http::STATUS_BAD_REQUEST); - } else if (!$isArchived && $unarchive) { + } + if (!$isArchived && $unarchive) { return new JSONResponse(['message' => 'File not archived'], Http::STATUS_BAD_REQUEST); } diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index bd0a1749..9b74ca5f 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -221,7 +221,7 @@ trait TimelineQueryDays /** * The root folder id for the folder. - * We fallback to this if rootid is not found + * We fallback to this if rootid is not found. */ $defaultRootId = 0; From 4a5408b846cbe863320bd92cdeaf545c1cbbee4b Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 22:44:55 -0800 Subject: [PATCH 145/163] image-editor: remove more extraneous props --- src/components/ImageEditor.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/ImageEditor.vue b/src/components/ImageEditor.vue index 80131b84..8e051e9e 100644 --- a/src/components/ImageEditor.vue +++ b/src/components/ImageEditor.vue @@ -220,6 +220,11 @@ export default class ImageEditor extends Mixins(GlobalMixin) { delete exif.ExifImageHeight; delete exif.ExifImageWidth; delete exif.ExifImageSize; + delete exif.CompatibleBrands; + delete exif.FileType; + delete exif.FileTypeExtension; + delete exif.MIMEType; + delete exif.MajorBrand; // Update exif data await axios.patch( From d9afbbe710e60d606d6e2f5420e2bfe1a44f5282 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 15 Nov 2022 23:45:01 -0800 Subject: [PATCH 146/163] Refactor all calls to use TimelineRoot --- lib/Controller/ApiBase.php | 21 +++++++-- lib/Controller/DaysController.php | 28 +++++------ lib/Controller/FacesController.php | 15 +++--- lib/Controller/TagsController.php | 12 ++--- lib/Db/TimelineQueryDays.php | 75 +++++++++++------------------- lib/Db/TimelineQueryFaces.php | 8 ++-- lib/Db/TimelineQueryFolders.php | 4 +- lib/Db/TimelineQueryTags.php | 8 ++-- lib/Db/TimelineRoot.php | 67 ++++++++++++++++++++++++++ 9 files changed, 150 insertions(+), 88 deletions(-) create mode 100644 lib/Db/TimelineRoot.php diff --git a/lib/Controller/ApiBase.php b/lib/Controller/ApiBase.php index 146e7879..d8484389 100644 --- a/lib/Controller/ApiBase.php +++ b/lib/Controller/ApiBase.php @@ -25,6 +25,7 @@ namespace OCA\Memories\Controller; use OCA\Memories\AppInfo\Application; use OCA\Memories\Db\TimelineQuery; +use OCA\Memories\Db\TimelineRoot; use OCA\Memories\Db\TimelineWrite; use OCA\Memories\Exif; use OCP\App\IAppManager; @@ -88,12 +89,14 @@ class ApiBase extends Controller return $user ? $user->getUID() : ''; } - /** Get the Folder object relevant to the request */ - protected function getRequestFolder() + /** Get the TimelineRoot object relevant to the request */ + protected function getRequestRoot() { + $root = new TimelineRoot(); + // Albums have no folder if ($this->request->getParam('album')) { - return null; + return $root; } // Public shared folder @@ -103,7 +106,9 @@ class ApiBase extends Controller throw new \Exception('Share not found or invalid'); } - return $share; + $root->addFolder($share); + + return $root; } // Anything else needs a user @@ -135,7 +140,13 @@ class ApiBase extends Controller throw new \Exception('Folder not readable'); } - return $folder; + // Don't add mount points for folder view + $root->addFolder($folder); + if (null === $folderPath) { + $root->addMountPoints(); + } + + return $root; } /** diff --git a/lib/Controller/DaysController.php b/lib/Controller/DaysController.php index 5133676b..f3512cf3 100644 --- a/lib/Controller/DaysController.php +++ b/lib/Controller/DaysController.php @@ -23,9 +23,9 @@ declare(strict_types=1); namespace OCA\Memories\Controller; +use OCA\Memories\Db\TimelineRoot; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; -use OCP\Files\Folder; class DaysController extends ApiBase { @@ -42,10 +42,10 @@ class DaysController extends ApiBase $uid = $this->getUid(); // Get the folder to show - $folder = null; + $root = null; try { - $folder = $this->getRequestFolder(); + $root = $this->getRequestRoot(); } catch (\Exception $e) { return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND); } @@ -53,7 +53,7 @@ class DaysController extends ApiBase // Run actual query try { $list = $this->timelineQuery->getDays( - $folder, + $root, $uid, $this->isRecursive(), $this->isArchive(), @@ -65,7 +65,7 @@ class DaysController extends ApiBase $list = $this->timelineQuery->daysToMonths($list); } else { // Preload some day responses - $this->preloadDays($list, $uid, $folder); + $this->preloadDays($list, $uid, $root); } // Reverse response if requested. Folders still stay at top. @@ -75,7 +75,7 @@ class DaysController extends ApiBase // Add subfolder info if querying non-recursively if (!$this->isRecursive()) { - array_unshift($list, $this->getSubfoldersEntry($folder)); + array_unshift($list, $this->getSubfoldersEntry($root->getFolder($root->getOneId()))); } return new JSONResponse($list, Http::STATUS_OK); @@ -111,10 +111,10 @@ class DaysController extends ApiBase } // Get the folder to show - $folder = null; + $root = null; try { - $folder = $this->getRequestFolder(); + $root = $this->getRequestRoot(); } catch (\Exception $e) { return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND); } @@ -127,7 +127,7 @@ class DaysController extends ApiBase // Run actual query try { $list = $this->timelineQuery->getDay( - $folder, + $root, $uid, $dayIds, $this->isRecursive(), @@ -237,11 +237,11 @@ class DaysController extends ApiBase /** * Preload a few "day" at the start of "days" response. * - * @param array $days the days array - * @param string $uid User ID or blank for public shares - * @param null|Folder $folder the folder to search in + * @param array $days the days array + * @param string $uid User ID or blank for public shares + * @param TimelineRoot $root the root folder */ - private function preloadDays(array &$days, string $uid, &$folder) + private function preloadDays(array &$days, string $uid, TimelineRoot &$root) { $transforms = $this->getTransformations(false); $preloaded = 0; @@ -263,7 +263,7 @@ class DaysController extends ApiBase if (\count($preloadDayIds) > 0) { $allDetails = $this->timelineQuery->getDay( - $folder, + $root, $uid, $preloadDayIds, $this->isRecursive(), diff --git a/lib/Controller/FacesController.php b/lib/Controller/FacesController.php index f4dfd097..c768129e 100644 --- a/lib/Controller/FacesController.php +++ b/lib/Controller/FacesController.php @@ -49,14 +49,14 @@ class FacesController extends ApiBase } // If this isn't the timeline folder then things aren't going to work - $folder = $this->getRequestFolder(); - if (null === $folder) { + $root = $this->getRequestRoot(); + if ($root->isEmpty()) { return new JSONResponse([], Http::STATUS_NOT_FOUND); } // Run actual query $list = $this->timelineQuery->getFaces( - $folder, + $root, ); return new JSONResponse($list, Http::STATUS_OK); @@ -84,22 +84,23 @@ class FacesController extends ApiBase } // Get folder to search for - $folder = $this->getRequestFolder(); - if (null === $folder) { + $root = $this->getRequestRoot(); + if ($root->isEmpty()) { return new JSONResponse([], Http::STATUS_NOT_FOUND); } // Run actual query - $detections = $this->timelineQuery->getFacePreviewDetection($folder, (int) $id); + $detections = $this->timelineQuery->getFacePreviewDetection($root, (int) $id); if (null === $detections || 0 === \count($detections)) { return new DataResponse([], Http::STATUS_NOT_FOUND); } // Find the first detection that has a preview $preview = null; + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); foreach ($detections as &$detection) { // Get the file (also checks permissions) - $files = $folder->getById($detection['file_id']); + $files = $userFolder->getById($detection['file_id']); if (0 === \count($files) || FileInfo::TYPE_FILE !== $files[0]->getType()) { continue; } diff --git a/lib/Controller/TagsController.php b/lib/Controller/TagsController.php index d4c3c667..c689253d 100644 --- a/lib/Controller/TagsController.php +++ b/lib/Controller/TagsController.php @@ -46,14 +46,14 @@ class TagsController extends ApiBase } // If this isn't the timeline folder then things aren't going to work - $folder = $this->getRequestFolder(); - if (null === $folder) { + $root = $this->getRequestRoot(); + if ($root->isEmpty()) { return new JSONResponse([], Http::STATUS_NOT_FOUND); } // Run actual query $list = $this->timelineQuery->getTags( - $folder, + $root, ); return new JSONResponse($list, Http::STATUS_OK); @@ -77,8 +77,8 @@ class TagsController extends ApiBase } // If this isn't the timeline folder then things aren't going to work - $folder = $this->getRequestFolder(); - if (null === $folder) { + $root = $this->getRequestRoot(); + if ($root->isEmpty()) { return new JSONResponse([], Http::STATUS_NOT_FOUND); } @@ -88,7 +88,7 @@ class TagsController extends ApiBase // Run actual query $list = $this->timelineQuery->getTagPreviews( $tagName, - $folder, + $root, ); return new JSONResponse($list, Http::STATUS_OK); diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 9b74ca5f..40526edf 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace OCA\Memories\Db; use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\Files\Folder; use OCP\IDBConnection; const CTE_FOLDERS = // CTE to get all folders recursively in the given top folders excluding archive @@ -73,21 +72,18 @@ trait TimelineQueryDays { protected IDBConnection $connection; - /** Map of rootid => mount point */ - private $topFolderPaths = []; - /** * Get the days response from the database for the timeline. * - * @param null|Folder $folder The folder to get the days from - * @param bool $recursive Whether to get the days recursively - * @param bool $archive Whether to get the days only from the archive folder - * @param array $queryTransforms An array of query transforms to apply to the query + * @param TimelineRoot $root The root to get the days from + * @param bool $recursive Whether to get the days recursively + * @param bool $archive Whether to get the days only from the archive folder + * @param array $queryTransforms An array of query transforms to apply to the query * * @return array The days response */ public function getDays( - &$folder, + TimelineRoot &$root, string $uid, bool $recursive, bool $archive, @@ -100,7 +96,7 @@ trait TimelineQueryDays $query->select('m.dayid', $count) ->from('memories', 'm') ; - $query = $this->joinFilecache($query, $folder, $recursive, $archive); + $query = $this->joinFilecache($query, $root, $recursive, $archive); // Group and sort by dayid $query->groupBy('m.dayid') @@ -120,18 +116,18 @@ trait TimelineQueryDays /** * Get the day response from the database for the timeline. * - * @param null|Folder $folder The folder to get the day from - * @param string $uid The user id - * @param int[] $day_ids The day ids to fetch - * @param bool $recursive If the query should be recursive - * @param bool $archive If the query should include only the archive folder - * @param array $queryTransforms The query transformations to apply - * @param mixed $day_ids + * @param TimelineRoot $root The root to get the day from + * @param string $uid The user id + * @param int[] $day_ids The day ids to fetch + * @param bool $recursive If the query should be recursive + * @param bool $archive If the query should include only the archive folder + * @param array $queryTransforms The query transformations to apply + * @param mixed $day_ids * * @return array An array of day responses */ public function getDay( - &$folder, + TimelineRoot &$root, string $uid, $day_ids, bool $recursive, @@ -151,7 +147,7 @@ trait TimelineQueryDays ; // JOIN with filecache for existing files - $query = $this->joinFilecache($query, $folder, $recursive, $archive); + $query = $this->joinFilecache($query, $root, $recursive, $archive); $query->addSelect('f.etag', 'f.path', 'f.name AS basename'); // JOIN with mimetypes to get the mimetype @@ -180,7 +176,7 @@ trait TimelineQueryDays $rows = $cursor->fetchAll(); $cursor->closeCursor(); - return $this->processDay($rows, $uid, $folder); + return $this->processDay($rows, $uid, $root); } /** @@ -200,12 +196,8 @@ trait TimelineQueryDays /** * Process the single day response. - * - * @param array $day - * @param string $uid User or blank if not logged in - * @param null|Folder $folder */ - private function processDay(&$day, $uid, $folder) + private function processDay(array &$day, string $uid, TimelineRoot &$root) { /** * Path entry in database for folder. @@ -225,15 +217,15 @@ trait TimelineQueryDays */ $defaultRootId = 0; - if (null !== $folder) { + if (!$root->isEmpty()) { // Get root id of the top folder - $defaultRootId = $folder->getId(); + $defaultRootId = $root->getOneId(); // No way to get the internal path from the folder $query = $this->connection->getQueryBuilder(); $query->select('fileid', 'path') ->from('filecache') - ->where($query->expr()->in('fileid', $query->createNamedParameter(array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY))) + ->where($query->expr()->in('fileid', $query->createNamedParameter($root->getIds(), IQueryBuilder::PARAM_INT_ARRAY))) ; $paths = $query->executeQuery()->fetchAll(); foreach ($paths as &$path) { @@ -244,7 +236,7 @@ trait TimelineQueryDays // getPath looks like /user/files/... but we want /files/user/... // Split at / and swap these // For public shares, we just give the relative path - if (!empty($uid) && ($actualPath = $this->topFolderPaths[$fileid])) { + if (!empty($uid) && ($actualPath = $root->getFolderPath($fileid))) { $actualPath = explode('/', $actualPath); if (\count($actualPath) >= 3) { $tmp = $actualPath[1]; @@ -317,10 +309,11 @@ trait TimelineQueryDays */ private function addSubfolderJoinParams( IQueryBuilder &$query, + TimelineRoot &$root, bool $archive ) { // Add query parameters - $query->setParameter('topFolderIds', array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY); + $query->setParameter('topFolderIds', $root->getIds(), IQueryBuilder::PARAM_INT_ARRAY); $query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL); } @@ -328,44 +321,32 @@ trait TimelineQueryDays * Inner join with oc_filecache. * * @param IQueryBuilder $query Query builder - * @param null|Folder $folder Either the top folder or null for all + * @param TimelineRoot $root Either the top folder or null for all * @param bool $recursive Whether to get the days recursively * @param bool $archive Whether to get the days only from the archive folder */ private function joinFilecache( IQueryBuilder &$query, - &$folder, + TimelineRoot &$root, bool $recursive, bool $archive ) { // Join with memories $baseOp = $query->expr()->eq('f.fileid', 'm.fileid'); - if (null === $folder) { + if ($root->isEmpty()) { return $query->innerJoin('m', 'filecache', 'f', $baseOp); } - // Create top folders paths for later processing - $this->topFolderPaths = []; - $this->topFolderPaths[$folder->getId()] = $folder->getPath(); - // Filter by folder (recursive or otherwise) $pathOp = null; if ($recursive) { - // Add mountpoints recursively - $this->mounts = \OC\Files\Filesystem::getMountManager()->findIn($folder->getPath()); - foreach ($this->mounts as &$mount) { - $id = $mount->getStorageRootId(); - $path = $mount->getMountPoint(); - $this->topFolderPaths[$id] = $path; - } - // Join with folders CTE - $this->addSubfolderJoinParams($query, $archive); + $this->addSubfolderJoinParams($query, $root, $archive); $query->innerJoin('f', 'cte_folders', 'cte_f', $query->expr()->eq('f.parent', 'cte_f.fileid')); $query->addSelect('cte_f.rootid'); } else { // If getting non-recursively folder only check for parent - $pathOp = $query->expr()->eq('f.parent', $query->createNamedParameter($folder->getId(), IQueryBuilder::PARAM_INT)); + $pathOp = $query->expr()->eq('f.parent', $query->createNamedParameter($root->getOneId(), IQueryBuilder::PARAM_INT)); } return $query->innerJoin('m', 'filecache', 'f', $query->expr()->andX( diff --git a/lib/Db/TimelineQueryFaces.php b/lib/Db/TimelineQueryFaces.php index ed01fd2e..4cf6f6f2 100644 --- a/lib/Db/TimelineQueryFaces.php +++ b/lib/Db/TimelineQueryFaces.php @@ -47,7 +47,7 @@ trait TimelineQueryFaces ); } - public function getFaces(Folder $folder) + public function getFaces(TimelineRoot &$root) { $query = $this->connection->getQueryBuilder(); @@ -62,7 +62,7 @@ trait TimelineQueryFaces $query->innerJoin('rfd', 'memories', 'm', $query->expr()->eq('m.fileid', 'rfd.file_id')); // WHERE these photos are in the user's requested folder recursively - $query = $this->joinFilecache($query, $folder, true, false); + $query = $this->joinFilecache($query, $root, true, false); // GROUP by ID of face cluster $query->groupBy('rfc.id'); @@ -87,7 +87,7 @@ trait TimelineQueryFaces return $faces; } - public function getFacePreviewDetection(Folder &$folder, int $id) + public function getFacePreviewDetection(TimelineRoot &$root, int $id) { $query = $this->connection->getQueryBuilder(); @@ -109,7 +109,7 @@ trait TimelineQueryFaces $query->innerJoin('rfd', 'memories', 'm', $query->expr()->eq('m.fileid', 'rfd.file_id')); // WHERE these photos are in the user's requested folder recursively - $query = $this->joinFilecache($query, $folder, true, false); + $query = $this->joinFilecache($query, $root, true, false); // LIMIT results $query->setMaxResults(15); diff --git a/lib/Db/TimelineQueryFolders.php b/lib/Db/TimelineQueryFolders.php index 26910ece..347e7e64 100644 --- a/lib/Db/TimelineQueryFolders.php +++ b/lib/Db/TimelineQueryFolders.php @@ -19,7 +19,9 @@ trait TimelineQueryFolders $query->select('f.fileid', 'f.etag')->from('memories', 'm'); // WHERE these photos are in the user's requested folder recursively - $query = $this->joinFilecache($query, $folder, true, false); + $root = new TimelineRoot(); + $root->addFolder($folder); + $query = $this->joinFilecache($query, $root, true, false); // ORDER descending by fileid $query->orderBy('f.fileid', 'DESC'); diff --git a/lib/Db/TimelineQueryTags.php b/lib/Db/TimelineQueryTags.php index 8a3b9bfd..4c4224eb 100644 --- a/lib/Db/TimelineQueryTags.php +++ b/lib/Db/TimelineQueryTags.php @@ -38,7 +38,7 @@ trait TimelineQueryTags )); } - public function getTags(Folder $folder) + public function getTags(TimelineRoot &$root) { $query = $this->connection->getQueryBuilder(); @@ -58,7 +58,7 @@ trait TimelineQueryTags $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid')); // WHERE these photos are in the user's requested folder recursively - $query = $this->joinFilecache($query, $folder, true, false); + $query = $this->joinFilecache($query, $root, true, false); // GROUP and ORDER by tag name $query->groupBy('st.id'); @@ -78,7 +78,7 @@ trait TimelineQueryTags return $tags; } - public function getTagPreviews(string $tagName, Folder &$folder) + public function getTagPreviews(string $tagName, TimelineRoot &$root) { $query = $this->connection->getQueryBuilder(); $tagId = $this->getSystemTagId($query, $tagName); @@ -99,7 +99,7 @@ trait TimelineQueryTags $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid')); // WHERE these photos are in the user's requested folder recursively - $query = $this->joinFilecache($query, $folder, true, false); + $query = $this->joinFilecache($query, $root, true, false); // MAX 4 $query->setMaxResults(4); diff --git a/lib/Db/TimelineRoot.php b/lib/Db/TimelineRoot.php new file mode 100644 index 00000000..04490a73 --- /dev/null +++ b/lib/Db/TimelineRoot.php @@ -0,0 +1,67 @@ +getId(); + $folderPath = $folder->getPath(); + $this->folders[$id] = $folder; + $this->folderPaths[$id] = $folderPath; + } + + // Add mountpoints recursively + public function addMountPoints() + { + $mp = []; + foreach ($this->folderPaths as $id => $folderPath) { + $mounts = \OC\Files\Filesystem::getMountManager()->findIn($folderPath); + foreach ($mounts as &$mount) { + $id = $mount->getStorageRootId(); + $path = $mount->getMountPoint(); + $mp[$id] = $path; + } + } + $this->folderPaths += $mp; + } + + public function getFolderPath(int $id) + { + return $this->folderPaths[$id]; + } + + public function getIds() + { + return array_keys($this->folderPaths); + } + + public function getOneId() + { + return array_key_first($this->folders); + } + + public function getFolder(int $id) + { + return $this->folders[$id]; + } + + public function isEmpty() + { + return empty($this->folderPaths); + } +} From a6ef3ac9bf5a936dd9d6c38799c81eff6393fdc3 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 00:16:01 -0800 Subject: [PATCH 147/163] Add support for multiple timeline paths --- lib/Controller/ApiBase.php | 40 +++---- lib/Db/TimelineQueryDays.php | 5 +- lib/Db/TimelineRoot.php | 21 +++- src/components/Settings.vue | 28 +++-- .../modal/MultiPathSelectionModal.vue | 112 ++++++++++++++++++ 5 files changed, 174 insertions(+), 32 deletions(-) create mode 100644 src/components/modal/MultiPathSelectionModal.vue diff --git a/lib/Controller/ApiBase.php b/lib/Controller/ApiBase.php index d8484389..a7ea2319 100644 --- a/lib/Controller/ApiBase.php +++ b/lib/Controller/ApiBase.php @@ -114,36 +114,34 @@ class ApiBase extends Controller // Anything else needs a user $user = $this->userSession->getUser(); if (null === $user) { - return null; + throw new \Exception('User not logged in'); } $uid = $user->getUID(); $folder = null; $folderPath = $this->request->getParam('folder'); - $forcedTimelinePath = $this->request->getParam('timelinePath'); $userFolder = $this->rootFolder->getUserFolder($uid); - if (null !== $folderPath) { - $folder = $userFolder->get($folderPath); - } elseif (null !== $forcedTimelinePath) { - $folder = $userFolder->get($forcedTimelinePath); - } else { - $configPath = Exif::removeExtraSlash(Exif::getPhotosPath($this->config, $uid)); - $folder = $userFolder->get($configPath); - } + try { + if (null !== $folderPath) { + $folder = $userFolder->get(Exif::removeExtraSlash($folderPath)); + $root->addFolder($folder); + } else { + $timelinePath = $this->request->getParam('timelinePath', Exif::getPhotosPath($this->config, $uid)); + $timelinePath = Exif::removeExtraSlash($timelinePath); - if (!$folder instanceof Folder) { - throw new \Exception('Folder not found'); - } + // Multiple timeline path support + $paths = explode(';', $timelinePath); + foreach ($paths as &$path) { + $folder = $userFolder->get(trim($path)); + $root->addFolder($folder); + } + $root->addMountPoints(); + } + } catch (\OCP\Files\NotFoundException $e) { + $msg = $e->getMessage(); - if (!($folder->getPermissions() & \OCP\Constants::PERMISSION_READ)) { - throw new \Exception('Folder not readable'); - } - - // Don't add mount points for folder view - $root->addFolder($folder); - if (null === $folderPath) { - $root->addMountPoints(); + throw new \Exception("Folder not found: {$msg}"); } return $root; diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 40526edf..5e5ce948 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -242,7 +242,8 @@ trait TimelineQueryDays $tmp = $actualPath[1]; $actualPath[1] = $actualPath[2]; $actualPath[2] = $tmp; - $davPaths[$fileid] = implode('/', $actualPath); + $davPath = implode('/', $actualPath); + $davPaths[$fileid] = \OCA\Memories\Exif::removeExtraSlash('/'.$davPath.'/'); } } } @@ -270,7 +271,7 @@ trait TimelineQueryDays // Check if path exists and starts with basePath and remove if (isset($row['path']) && !empty($row['path'])) { $rootId = $row['rootid'] ?: $defaultRootId; - $basePath = $internalPaths[$rootId] ?: '#__#'; + $basePath = $internalPaths[$rootId] ?? '#__#'; $davPath = $davPaths[$rootId] ?: ''; if (0 === strpos($row['path'], $basePath)) { diff --git a/lib/Db/TimelineRoot.php b/lib/Db/TimelineRoot.php index 04490a73..fc6b8f52 100644 --- a/lib/Db/TimelineRoot.php +++ b/lib/Db/TimelineRoot.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace OCA\Memories\Db; use OCP\Files\Folder; +use OCP\Files\Node; class TimelineRoot { @@ -16,11 +17,27 @@ class TimelineRoot { } - public function addFolder(Folder &$folder) + /** + * Add a folder to the root. + * + * @param Node $folder Node to add + * + * @throws \Exception if node is not valid readable folder + */ + public function addFolder(Node &$folder) { + $folderPath = $folder->getPath(); + + if (!$folder instanceof Folder) { + throw new \Exception("Not a folder: {$folderPath}"); + } + + if (!($folder->getPermissions() & \OCP\Constants::PERMISSION_READ)) { + throw new \Exception("Folder not readable: {$folderPath}"); + } + // Add top level folder $id = $folder->getId(); - $folderPath = $folder->getPath(); $this->folders[$id] = $folder; $this->folderPaths[$id] = $folderPath; } diff --git a/src/components/Settings.vue b/src/components/Settings.vue index ecbc95f0..1d13d705 100644 --- a/src/components/Settings.vue +++ b/src/components/Settings.vue @@ -53,6 +53,12 @@ > {{ t("memories", "Square grid mode") }} + + @@ -65,18 +71,24 @@ input[type="text"] { + + From bd89c9d355e555ba105fb145ef139fa964df718c Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 00:16:07 -0800 Subject: [PATCH 148/163] Fix some errors --- lib/Controller/FoldersTrait.php | 2 +- lib/Db/TimelineQueryDays.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Controller/FoldersTrait.php b/lib/Controller/FoldersTrait.php index 37c5d217..c8a087b0 100644 --- a/lib/Controller/FoldersTrait.php +++ b/lib/Controller/FoldersTrait.php @@ -13,7 +13,7 @@ trait FoldersTrait /** * Get subfolders entry for days response. */ - public function getSubfoldersEntry(Folder &$folder) + public function getSubfoldersEntry(Folder $folder) { // Ugly: get the view of the folder with reflection // This is unfortunately the only way to get the contents of a folder diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 5e5ce948..f84535c2 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -295,7 +295,9 @@ trait TimelineQueryDays $types = $query->getParameterTypes(); // Get SQL - $CTE_SQL = $params['cteFoldersArchive'] ? CTE_FOLDERS_ARCHIVE : CTE_FOLDERS; + $CTE_SQL = \array_key_exists('cteFoldersArchive', $params) && $params['cteFoldersArchive'] + ? CTE_FOLDERS_ARCHIVE + : CTE_FOLDERS; // Add WITH clause if needed if (false !== strpos($sql, 'cte_folders')) { From cd3fb4b897158f827d31e89abca884fbb739c287 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 00:23:57 -0800 Subject: [PATCH 149/163] Fix rootid warning --- lib/Db/TimelineQueryDays.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index f84535c2..f3bcfaa5 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -270,7 +270,7 @@ trait TimelineQueryDays // Check if path exists and starts with basePath and remove if (isset($row['path']) && !empty($row['path'])) { - $rootId = $row['rootid'] ?: $defaultRootId; + $rootId = \array_key_exists('rootid', $row) ? $row['rootid'] : $defaultRootId; $basePath = $internalPaths[$rootId] ?? '#__#'; $davPath = $davPaths[$rootId] ?: ''; From 3154de7ac909b7086312b795f8d68b063a661c21 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 01:17:01 -0800 Subject: [PATCH 150/163] Select rootid only for day query --- lib/Db/TimelineQueryDays.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index f3bcfaa5..64947ac7 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -150,6 +150,9 @@ trait TimelineQueryDays $query = $this->joinFilecache($query, $root, $recursive, $archive); $query->addSelect('f.etag', 'f.path', 'f.name AS basename'); + // SELECT rootid if not a single folder + if ($recursive) $query->addSelect('cte_f.rootid'); + // JOIN with mimetypes to get the mimetype $query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id')); $query->addSelect('mimetypes.mimetype'); @@ -346,7 +349,6 @@ trait TimelineQueryDays // Join with folders CTE $this->addSubfolderJoinParams($query, $root, $archive); $query->innerJoin('f', 'cte_folders', 'cte_f', $query->expr()->eq('f.parent', 'cte_f.fileid')); - $query->addSelect('cte_f.rootid'); } else { // If getting non-recursively folder only check for parent $pathOp = $query->expr()->eq('f.parent', $query->createNamedParameter($root->getOneId(), IQueryBuilder::PARAM_INT)); From 0a0d1d9e52691e4d151d3b6d57cd38fdda34c187 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 01:49:03 -0800 Subject: [PATCH 151/163] Fix duplicate folders in CTE response --- lib/Db/TimelineQueryDays.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 64947ac7..d754e542 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -8,7 +8,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; const CTE_FOLDERS = // CTE to get all folders recursively in the given top folders excluding archive - 'WITH RECURSIVE *PREFIX*cte_folders(fileid, rootid) AS ( + 'WITH RECURSIVE *PREFIX*cte_folders_all(fileid, rootid) AS ( SELECT f.fileid, f.fileid AS rootid @@ -22,11 +22,19 @@ const CTE_FOLDERS = // CTE to get all folders recursively in the given top folde c.rootid FROM *PREFIX*filecache f - INNER JOIN *PREFIX*cte_folders c + INNER JOIN *PREFIX*cte_folders_all c ON (f.parent = c.fileid AND f.mimetype = (SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = \'httpd/unix-directory\') AND f.name <> \'.archive\' ) + ), *PREFIX*cte_folders AS ( + SELECT + fileid, + MIN(rootid) AS rootid + FROM + *PREFIX*cte_folders_all + GROUP BY + fileid )'; const CTE_FOLDERS_ARCHIVE = // CTE to get all archive folders recursively in the given top folders @@ -53,11 +61,13 @@ const CTE_FOLDERS_ARCHIVE = // CTE to get all archive folders recursively in the ), *PREFIX*cte_folders(fileid, rootid) AS ( SELECT cfa.fileid, - cfa.rootid + MIN(cfa.rootid) AS rootid FROM *PREFIX*cte_folders_all cfa WHERE cfa.name = \'.archive\' + GROUP BY + cfa.fileid UNION ALL SELECT f.fileid, From c1ae720656486b3c05f7a37c3ddbbd75f174fb72 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 02:30:18 -0800 Subject: [PATCH 152/163] archive: fix for multipath --- lib/Controller/ArchiveController.php | 29 ++++++++++++++++++++++------ lib/Util.php | 13 ------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/Controller/ArchiveController.php b/lib/Controller/ArchiveController.php index 1e416d14..7fe86035 100644 --- a/lib/Controller/ArchiveController.php +++ b/lib/Controller/ArchiveController.php @@ -59,10 +59,20 @@ class ArchiveController extends ApiBase } // Create archive folder in the root of the user's configured timeline - $timelinePath = Exif::removeExtraSlash(Exif::getPhotosPath($this->config, $uid)); - $timelineFolder = $userFolder->get($timelinePath); - if (null === $timelineFolder || !$timelineFolder instanceof Folder) { - return new JSONResponse(['message' => 'Cannot get timeline'], Http::STATUS_INTERNAL_SERVER_ERROR); + $configPath = Exif::removeExtraSlash(Exif::getPhotosPath($this->config, $uid)); + $configPaths = \explode(';', $configPath); + $timelineFolders = []; + $timelinePaths = []; + + // Get all timeline paths + foreach ($configPaths as $path) { + try { + $f = $userFolder->get($path); + $timelineFolders[] = $f; + $timelinePaths[] = $f->getPath(); + } catch (\OCP\Files\NotFoundException $e) { + return new JSONResponse(['message' => 'Timeline folder not found'], Http::STATUS_NOT_FOUND); + } } // Bubble up from file until we reach the correct folder @@ -74,14 +84,21 @@ class ArchiveController extends ApiBase throw new \Exception('Cannot get correct parent of file'); } - if ($parent->getPath() === $timelineFolder->getPath()) { + // Hit a timeline folder + if (in_array($parent->getPath(), $timelinePaths)) { break; } - if ($parent->getParent()->getStorage()->getId() !== $fileStorageId) { + // Hit a storage root + try { + if ($parent->getParent()->getStorage()->getId() !== $fileStorageId) { + break; + } + } catch (\OCP\Files\NotFoundException $e) { break; } + // Hit an archive folder root if ($parent->getName() === \OCA\Memories\Util::$ARCHIVE_FOLDER) { $isArchived = true; diff --git a/lib/Util.php b/lib/Util.php index d20b52ab..a2c661e4 100644 --- a/lib/Util.php +++ b/lib/Util.php @@ -47,19 +47,6 @@ class Util return null; } - /** - * Get the path to the user's configured photos directory. - */ - public static function getPhotosPath(IConfig &$config, string $userId) - { - $p = $config->getUserValue($userId, Application::APPNAME, 'timelinePath', ''); - if (empty($p)) { - return '/Photos/'; - } - - return $p; - } - /** * Check if albums are enabled for this user. * From c3f874d4b4f96c9154e24e19b3f79afaa53a6e18 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 02:30:51 -0800 Subject: [PATCH 153/163] PHP Lint --- lib/Controller/ArchiveController.php | 4 ++-- lib/Db/TimelineQueryDays.php | 4 +++- lib/Util.php | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Controller/ArchiveController.php b/lib/Controller/ArchiveController.php index 7fe86035..8c5a4ba6 100644 --- a/lib/Controller/ArchiveController.php +++ b/lib/Controller/ArchiveController.php @@ -60,7 +60,7 @@ class ArchiveController extends ApiBase // Create archive folder in the root of the user's configured timeline $configPath = Exif::removeExtraSlash(Exif::getPhotosPath($this->config, $uid)); - $configPaths = \explode(';', $configPath); + $configPaths = explode(';', $configPath); $timelineFolders = []; $timelinePaths = []; @@ -85,7 +85,7 @@ class ArchiveController extends ApiBase } // Hit a timeline folder - if (in_array($parent->getPath(), $timelinePaths)) { + if (\in_array($parent->getPath(), $timelinePaths, true)) { break; } diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index d754e542..49e29c04 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -161,7 +161,9 @@ trait TimelineQueryDays $query->addSelect('f.etag', 'f.path', 'f.name AS basename'); // SELECT rootid if not a single folder - if ($recursive) $query->addSelect('cte_f.rootid'); + if ($recursive) { + $query->addSelect('cte_f.rootid'); + } // JOIN with mimetypes to get the mimetype $query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id')); diff --git a/lib/Util.php b/lib/Util.php index a2c661e4..2ddd9cb6 100644 --- a/lib/Util.php +++ b/lib/Util.php @@ -4,9 +4,6 @@ declare(strict_types=1); namespace OCA\Memories; -use OCA\Memories\AppInfo\Application; -use OCP\IConfig; - class Util { public static $TAG_DAYID_START = -(1 << 30); // the world surely didn't exist From 579984041a3c036430f76e961861507e208750e1 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 02:35:17 -0800 Subject: [PATCH 154/163] albums: fix for multipath --- lib/Db/TimelineQueryDays.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Db/TimelineQueryDays.php b/lib/Db/TimelineQueryDays.php index 49e29c04..d1f58ffc 100644 --- a/lib/Db/TimelineQueryDays.php +++ b/lib/Db/TimelineQueryDays.php @@ -161,7 +161,7 @@ trait TimelineQueryDays $query->addSelect('f.etag', 'f.path', 'f.name AS basename'); // SELECT rootid if not a single folder - if ($recursive) { + if ($recursive && !$root->isEmpty()) { $query->addSelect('cte_f.rootid'); } From 5cadd168b4b046f5655053cafc6ad14b6e146bc4 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 02:38:40 -0800 Subject: [PATCH 155/163] Remove mp4 from src --- src/components/PsVideo.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 1d35a678..7838da9e 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -197,7 +197,6 @@ class VideoContentSetup { content.videojs.src({ src: content.data.src, - type: "video/mp4", }); this.updateRotation(content, 0); } From 79780f3e2b79460b58afc914f1168a523fb8e121 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 02:52:17 -0800 Subject: [PATCH 156/163] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91be9241..9dea378d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ This file is manually updated. Please file an issue if something is missing. +## v4.8.0, v3.8.0 + +- **Feature**: Timeline path now scans recursively for mounted volumes / shares inside it. +- **Feature**: Multiple timeline paths can be specified. + ## v4.7.0, v3.7.0 (2022-11-14) - **Note**: you must run `occ memories:index -f` to take advantage of new features. From c75e94108ce0c709cf3b20fa9ad66c19d98950a4 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 03:05:48 -0800 Subject: [PATCH 157/163] Store unknown exif fields --- lib/Exif.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Exif.php b/lib/Exif.php index 1d98df75..ab8f3a6b 100644 --- a/lib/Exif.php +++ b/lib/Exif.php @@ -368,7 +368,7 @@ class Exif private static function getExifFromLocalPathWithStaticProc(string &$path) { - fwrite(self::$staticPipes[0], "{$path}\n-json\n-b\n-api\nQuickTimeUTC=1\n-n\n-execute\n"); + fwrite(self::$staticPipes[0], "{$path}\n-U\n-json\n-b\n-api\nQuickTimeUTC=1\n-n\n-execute\n"); fflush(self::$staticPipes[0]); $readyToken = "\n{ready}\n"; @@ -390,7 +390,7 @@ class Exif private static function getExifFromLocalPathWithSeparateProc(string &$path) { $pipes = []; - $proc = proc_open(array_merge(self::getExiftool(), ['-api', 'QuickTimeUTC=1', '-n', '-json', '-b', $path]), [ + $proc = proc_open(array_merge(self::getExiftool(), ['-api', 'QuickTimeUTC=1', '-n', '-U', '-json', '-b', $path]), [ 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ], $pipes); From cc7567aca376c01305bbe0a3406b1805cec88048 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 03:24:59 -0800 Subject: [PATCH 158/163] exif: exclude binary fields --- lib/Exif.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Exif.php b/lib/Exif.php index ab8f3a6b..ebef819b 100644 --- a/lib/Exif.php +++ b/lib/Exif.php @@ -368,7 +368,7 @@ class Exif private static function getExifFromLocalPathWithStaticProc(string &$path) { - fwrite(self::$staticPipes[0], "{$path}\n-U\n-json\n-b\n-api\nQuickTimeUTC=1\n-n\n-execute\n"); + fwrite(self::$staticPipes[0], "{$path}\n-U\n-json\n--b\n-api\nQuickTimeUTC=1\n-n\n-execute\n"); fflush(self::$staticPipes[0]); $readyToken = "\n{ready}\n"; @@ -390,7 +390,7 @@ class Exif private static function getExifFromLocalPathWithSeparateProc(string &$path) { $pipes = []; - $proc = proc_open(array_merge(self::getExiftool(), ['-api', 'QuickTimeUTC=1', '-n', '-U', '-json', '-b', $path]), [ + $proc = proc_open(array_merge(self::getExiftool(), ['-api', 'QuickTimeUTC=1', '-n', '-U', '-json', '--b', $path]), [ 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ], $pipes); From 1e7c29736182cf2d1662a8890e19dd4f15640429 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 06:15:09 -0800 Subject: [PATCH 159/163] =?UTF-8?q?video:=20everything=20is=20mp4=20?= =?UTF-8?q?=F0=9F=A4=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/PsVideo.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 7838da9e..4b8b0b41 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -164,6 +164,7 @@ class VideoContentSetup { sources.push({ src: content.data.src, + type: "video/mp4", }); const overrideNative = !videojs.browser.IS_SAFARI; @@ -197,6 +198,7 @@ class VideoContentSetup { content.videojs.src({ src: content.data.src, + type: "video/mp4", }); this.updateRotation(content, 0); } From 38c6b2104e56b7e29839248e982cd3ea37205668 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Wed, 16 Nov 2022 07:11:44 -0800 Subject: [PATCH 160/163] Bump up go-vod (#197) --- scripts/get-exiftool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get-exiftool.sh b/scripts/get-exiftool.sh index 2cfaea78..e83df762 100755 --- a/scripts/get-exiftool.sh +++ b/scripts/get-exiftool.sh @@ -17,7 +17,7 @@ mv "exiftool-$exifver" exiftool rm -rf *.zip exiftool/t exiftool/html chmod 755 exiftool/exiftool -govod="0.0.12" +govod="0.0.13" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64" chmod 755 go-vod-* From ce3750467f6ffea89cac4f635dab8a2261a4e8ad Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Thu, 17 Nov 2022 03:19:02 +0000 Subject: [PATCH 161/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/el.js | 1 + l10n/el.json | 1 + l10n/en_GB.js | 1 + l10n/en_GB.json | 1 + l10n/eo.js | 1 + l10n/eo.json | 1 + l10n/es.js | 1 + l10n/es.json | 1 + l10n/es_419.js | 1 + l10n/es_419.json | 1 + l10n/es_AR.js | 1 + l10n/es_AR.json | 1 + l10n/es_CL.js | 1 + l10n/es_CL.json | 1 + l10n/es_CO.js | 1 + l10n/es_CO.json | 1 + l10n/es_CR.js | 1 + l10n/es_CR.json | 1 + l10n/es_DO.js | 1 + l10n/es_DO.json | 1 + l10n/es_EC.js | 1 + l10n/es_EC.json | 1 + l10n/es_GT.js | 1 + l10n/es_GT.json | 1 + l10n/es_HN.js | 1 + l10n/es_HN.json | 1 + l10n/es_MX.js | 1 + l10n/es_MX.json | 1 + l10n/es_NI.js | 1 + l10n/es_NI.json | 1 + l10n/es_PA.js | 1 + l10n/es_PA.json | 1 + l10n/es_PE.js | 1 + l10n/es_PE.json | 1 + l10n/es_PR.js | 1 + l10n/es_PR.json | 1 + l10n/es_PY.js | 1 + l10n/es_PY.json | 1 + l10n/es_SV.js | 1 + l10n/es_SV.json | 1 + l10n/es_UY.js | 1 + l10n/es_UY.json | 1 + l10n/et_EE.js | 1 + l10n/et_EE.json | 1 + l10n/eu.js | 1 + l10n/eu.json | 1 + l10n/fa.js | 1 + l10n/fa.json | 1 + l10n/fi.js | 1 + l10n/fi.json | 1 + l10n/fr.js | 1 + l10n/fr.json | 1 + l10n/gd.js | 1 + l10n/gd.json | 1 + l10n/gl.js | 1 + l10n/gl.json | 1 + l10n/he.js | 1 + l10n/he.json | 1 + l10n/hr.js | 1 + l10n/hr.json | 1 + l10n/hu.js | 1 + l10n/hu.json | 1 + l10n/id.js | 1 + l10n/id.json | 1 + l10n/is.js | 1 + l10n/is.json | 1 + l10n/it.js | 1 + l10n/it.json | 1 + l10n/ja.js | 1 + l10n/ja.json | 1 + l10n/ka_GE.js | 1 + l10n/ka_GE.json | 1 + l10n/kab.js | 1 + l10n/kab.json | 1 + l10n/km.js | 1 + l10n/km.json | 1 + l10n/kn.js | 1 + l10n/kn.json | 1 + l10n/ko.js | 1 + l10n/ko.json | 1 + l10n/lb.js | 1 + l10n/lb.json | 1 + l10n/lo.js | 1 + l10n/lo.json | 1 + l10n/lt_LT.js | 1 + l10n/lt_LT.json | 1 + l10n/lv.js | 1 + l10n/lv.json | 1 + l10n/mk.js | 1 + l10n/mk.json | 1 + l10n/mn.js | 1 + l10n/mn.json | 1 + l10n/ms_MY.js | 1 + l10n/ms_MY.json | 1 + l10n/nb.js | 1 + l10n/nb.json | 1 + l10n/nl.js | 1 + l10n/nl.json | 1 + l10n/nn_NO.js | 1 + l10n/nn_NO.json | 1 + l10n/oc.js | 1 + l10n/oc.json | 1 + l10n/pl.js | 1 + l10n/pl.json | 1 + l10n/pt_BR.js | 1 + l10n/pt_BR.json | 1 + l10n/pt_PT.js | 1 + l10n/pt_PT.json | 1 + l10n/ro.js | 1 + l10n/ro.json | 1 + l10n/ru.js | 1 + l10n/ru.json | 1 + l10n/sc.js | 1 + l10n/sc.json | 1 + l10n/si.js | 1 + l10n/si.json | 1 + l10n/sk.js | 1 + l10n/sk.json | 1 + l10n/sl.js | 1 + l10n/sl.json | 1 + l10n/sq.js | 1 + l10n/sq.json | 1 + l10n/sr.js | 1 + l10n/sr.json | 1 + l10n/sr@latin.js | 1 + l10n/sr@latin.json | 1 + l10n/sv.js | 1 + l10n/sv.json | 1 + l10n/ta.js | 1 + l10n/ta.json | 1 + l10n/th.js | 1 + l10n/th.json | 1 + l10n/tk.js | 3 ++- l10n/tk.json | 3 ++- l10n/tr.js | 1 + l10n/tr.json | 1 + l10n/ug.js | 1 + l10n/ug.json | 1 + l10n/uk.js | 1 + l10n/uk.json | 1 + l10n/uz.js | 1 + l10n/uz.json | 1 + l10n/vi.js | 1 + l10n/vi.json | 1 + l10n/zh_CN.js | 1 + l10n/zh_CN.json | 1 + l10n/zh_HK.js | 1 + l10n/zh_HK.json | 1 + l10n/zh_TW.js | 1 + l10n/zh_TW.json | 1 + 150 files changed, 152 insertions(+), 2 deletions(-) diff --git a/l10n/el.js b/l10n/el.js index 336c7cce..b2cfb358 100644 --- a/l10n/el.js +++ b/l10n/el.js @@ -35,6 +35,7 @@ OC.L10N.register( "Name" : "Όνομα", "Update" : "Ενημέρωση", "Refresh" : "Ανανέωση", + "Remove" : "Αφαίρεση", "Share folder" : "Διαμοιρασμός φακέλου", "Reset" : "Επαναφορά", "Continue" : "Συνεχίστε", diff --git a/l10n/el.json b/l10n/el.json index 04095a2a..f41ffd76 100644 --- a/l10n/el.json +++ b/l10n/el.json @@ -33,6 +33,7 @@ "Name" : "Όνομα", "Update" : "Ενημέρωση", "Refresh" : "Ανανέωση", + "Remove" : "Αφαίρεση", "Share folder" : "Διαμοιρασμός φακέλου", "Reset" : "Επαναφορά", "Continue" : "Συνεχίστε", diff --git a/l10n/en_GB.js b/l10n/en_GB.js index b3477b7c..55d34ef4 100644 --- a/l10n/en_GB.js +++ b/l10n/en_GB.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Surname", "Update" : "Update", "Refresh" : "Refresh", + "Remove" : "Remove", "Reset" : "Reset", "Continue" : "Continue", "Undo" : "Undo", diff --git a/l10n/en_GB.json b/l10n/en_GB.json index 79e01300..aef5ec3d 100644 --- a/l10n/en_GB.json +++ b/l10n/en_GB.json @@ -26,6 +26,7 @@ "Name" : "Surname", "Update" : "Update", "Refresh" : "Refresh", + "Remove" : "Remove", "Reset" : "Reset", "Continue" : "Continue", "Undo" : "Undo", diff --git a/l10n/eo.js b/l10n/eo.js index d66be403..9af7ffb7 100644 --- a/l10n/eo.js +++ b/l10n/eo.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Nomo", "Update" : "Ĝisdatigi", "Refresh" : "Aktualigi", + "Remove" : "Forigi", "Reset" : "Restarigi", "Continue" : "Daŭrigi", "Undo" : "Malfari", diff --git a/l10n/eo.json b/l10n/eo.json index f7ddbb26..0486007c 100644 --- a/l10n/eo.json +++ b/l10n/eo.json @@ -26,6 +26,7 @@ "Name" : "Nomo", "Update" : "Ĝisdatigi", "Refresh" : "Aktualigi", + "Remove" : "Forigi", "Reset" : "Restarigi", "Continue" : "Daŭrigi", "Undo" : "Malfari", diff --git a/l10n/es.js b/l10n/es.js index 0d35a957..97c2f326 100644 --- a/l10n/es.js +++ b/l10n/es.js @@ -127,6 +127,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "Utilice la barra lateral para compartir esta carpeta.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si crea un enlace público de compartición, haga click en refrescar y se mostrará abajo el enlace correspondiente a Memories.", "Refresh" : "Actualizar", + "Remove" : "Quitar", "Share album" : "Compartir álbum", "Delete album" : "Eliminar álbum", "Merge with different person" : "Unir con una persona diferente", diff --git a/l10n/es.json b/l10n/es.json index b85bfb00..772b99ac 100644 --- a/l10n/es.json +++ b/l10n/es.json @@ -125,6 +125,7 @@ "Use the sidebar to share this folder." : "Utilice la barra lateral para compartir esta carpeta.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si crea un enlace público de compartición, haga click en refrescar y se mostrará abajo el enlace correspondiente a Memories.", "Refresh" : "Actualizar", + "Remove" : "Quitar", "Share album" : "Compartir álbum", "Delete album" : "Eliminar álbum", "Merge with different person" : "Unir con una persona diferente", diff --git a/l10n/es_419.js b/l10n/es_419.js index 73444a4d..ec053a73 100644 --- a/l10n/es_419.js +++ b/l10n/es_419.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restaurar", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_419.json b/l10n/es_419.json index e022b67c..97fe40e3 100644 --- a/l10n/es_419.json +++ b/l10n/es_419.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restaurar", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_AR.js b/l10n/es_AR.js index 3c216ac0..dcb5f0a9 100644 --- a/l10n/es_AR.js +++ b/l10n/es_AR.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Recargar", + "Remove" : "Borrar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_AR.json b/l10n/es_AR.json index 79ddc9f4..dbb01598 100644 --- a/l10n/es_AR.json +++ b/l10n/es_AR.json @@ -26,6 +26,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Recargar", + "Remove" : "Borrar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_CL.js b/l10n/es_CL.js index 500b5448..255ef414 100644 --- a/l10n/es_CL.js +++ b/l10n/es_CL.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_CL.json b/l10n/es_CL.json index 393112cd..3fc1c534 100644 --- a/l10n/es_CL.json +++ b/l10n/es_CL.json @@ -26,6 +26,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_CO.js b/l10n/es_CO.js index 054b5bd5..b6978230 100644 --- a/l10n/es_CO.js +++ b/l10n/es_CO.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Reiniciar", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_CO.json b/l10n/es_CO.json index 1801a1c6..a97d797a 100644 --- a/l10n/es_CO.json +++ b/l10n/es_CO.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Reiniciar", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_CR.js b/l10n/es_CR.js index 1adbcbc4..98feb706 100644 --- a/l10n/es_CR.js +++ b/l10n/es_CR.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_CR.json b/l10n/es_CR.json index 8a97726f..78039437 100644 --- a/l10n/es_CR.json +++ b/l10n/es_CR.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_DO.js b/l10n/es_DO.js index 1adbcbc4..98feb706 100644 --- a/l10n/es_DO.js +++ b/l10n/es_DO.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_DO.json b/l10n/es_DO.json index 8a97726f..78039437 100644 --- a/l10n/es_DO.json +++ b/l10n/es_DO.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_EC.js b/l10n/es_EC.js index 1478a63e..4e7075e8 100644 --- a/l10n/es_EC.js +++ b/l10n/es_EC.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_EC.json b/l10n/es_EC.json index 02c57b56..57cf5aca 100644 --- a/l10n/es_EC.json +++ b/l10n/es_EC.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_GT.js b/l10n/es_GT.js index eb02434f..78bf6f77 100644 --- a/l10n/es_GT.js +++ b/l10n/es_GT.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_GT.json b/l10n/es_GT.json index b6b8b812..a195612f 100644 --- a/l10n/es_GT.json +++ b/l10n/es_GT.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_HN.js b/l10n/es_HN.js index 1adbcbc4..98feb706 100644 --- a/l10n/es_HN.js +++ b/l10n/es_HN.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_HN.json b/l10n/es_HN.json index 8a97726f..78039437 100644 --- a/l10n/es_HN.json +++ b/l10n/es_HN.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_MX.js b/l10n/es_MX.js index e90cdf93..db6dc122 100644 --- a/l10n/es_MX.js +++ b/l10n/es_MX.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Reiniciar", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_MX.json b/l10n/es_MX.json index 8aa54c4b..5cc06742 100644 --- a/l10n/es_MX.json +++ b/l10n/es_MX.json @@ -26,6 +26,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Reiniciar", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_NI.js b/l10n/es_NI.js index 854c75e8..f12d5960 100644 --- a/l10n/es_NI.js +++ b/l10n/es_NI.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_NI.json b/l10n/es_NI.json index ed884725..35337f74 100644 --- a/l10n/es_NI.json +++ b/l10n/es_NI.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PA.js b/l10n/es_PA.js index 854c75e8..f12d5960 100644 --- a/l10n/es_PA.js +++ b/l10n/es_PA.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PA.json b/l10n/es_PA.json index ed884725..35337f74 100644 --- a/l10n/es_PA.json +++ b/l10n/es_PA.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PE.js b/l10n/es_PE.js index 114445c1..d093dbf5 100644 --- a/l10n/es_PE.js +++ b/l10n/es_PE.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PE.json b/l10n/es_PE.json index fa3f1dd4..583ca914 100644 --- a/l10n/es_PE.json +++ b/l10n/es_PE.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PR.js b/l10n/es_PR.js index 854c75e8..f12d5960 100644 --- a/l10n/es_PR.js +++ b/l10n/es_PR.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PR.json b/l10n/es_PR.json index ed884725..35337f74 100644 --- a/l10n/es_PR.json +++ b/l10n/es_PR.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PY.js b/l10n/es_PY.js index 854c75e8..f12d5960 100644 --- a/l10n/es_PY.js +++ b/l10n/es_PY.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_PY.json b/l10n/es_PY.json index ed884725..35337f74 100644 --- a/l10n/es_PY.json +++ b/l10n/es_PY.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_SV.js b/l10n/es_SV.js index 1adbcbc4..98feb706 100644 --- a/l10n/es_SV.js +++ b/l10n/es_SV.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_SV.json b/l10n/es_SV.json index 8a97726f..78039437 100644 --- a/l10n/es_SV.json +++ b/l10n/es_SV.json @@ -25,6 +25,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_UY.js b/l10n/es_UY.js index 854c75e8..f12d5960 100644 --- a/l10n/es_UY.js +++ b/l10n/es_UY.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/es_UY.json b/l10n/es_UY.json index ed884725..35337f74 100644 --- a/l10n/es_UY.json +++ b/l10n/es_UY.json @@ -24,6 +24,7 @@ "Name" : "Nombre", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Eliminar", "Reset" : "Restablecer", "Continue" : "Continuar", "Undo" : "Deshacer", diff --git a/l10n/et_EE.js b/l10n/et_EE.js index e17229f1..83cc3814 100644 --- a/l10n/et_EE.js +++ b/l10n/et_EE.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Nimi", "Update" : "Uuenda", "Refresh" : "Värskenda", + "Remove" : "Eemalda", "Reset" : "Lähtesta", "Continue" : "Jätka", "Custom" : "Kohandatud", diff --git a/l10n/et_EE.json b/l10n/et_EE.json index 364934d9..a29dccc9 100644 --- a/l10n/et_EE.json +++ b/l10n/et_EE.json @@ -25,6 +25,7 @@ "Name" : "Nimi", "Update" : "Uuenda", "Refresh" : "Värskenda", + "Remove" : "Eemalda", "Reset" : "Lähtesta", "Continue" : "Jätka", "Custom" : "Kohandatud", diff --git a/l10n/eu.js b/l10n/eu.js index 880b196a..ba5df9a7 100644 --- a/l10n/eu.js +++ b/l10n/eu.js @@ -89,6 +89,7 @@ OC.L10N.register( "Update" : "Eguneratu", "Failed to move {name}." : "{name} mugitzeak huts egin du.", "Refresh" : "Freskatu", + "Remove" : "Kendu", "Delete album" : "Ezabatu albuma", "Merge with different person" : "Bateratu beste pertsona batekin", "Share folder" : "Partekatu karpeta", diff --git a/l10n/eu.json b/l10n/eu.json index fb2488de..c7c26795 100644 --- a/l10n/eu.json +++ b/l10n/eu.json @@ -87,6 +87,7 @@ "Update" : "Eguneratu", "Failed to move {name}." : "{name} mugitzeak huts egin du.", "Refresh" : "Freskatu", + "Remove" : "Kendu", "Delete album" : "Ezabatu albuma", "Merge with different person" : "Bateratu beste pertsona batekin", "Share folder" : "Partekatu karpeta", diff --git a/l10n/fa.js b/l10n/fa.js index 0a25b373..a92e4e09 100644 --- a/l10n/fa.js +++ b/l10n/fa.js @@ -29,6 +29,7 @@ OC.L10N.register( "Name" : "نام", "Update" : "یه‌روزرسانی", "Refresh" : "تازه‌سازی", + "Remove" : "حذف", "Share folder" : "اشتراک‌گذاری پوشه", "Reset" : "بازنشاندن", "Continue" : "ادامه دادن", diff --git a/l10n/fa.json b/l10n/fa.json index 328b30a8..daddd426 100644 --- a/l10n/fa.json +++ b/l10n/fa.json @@ -27,6 +27,7 @@ "Name" : "نام", "Update" : "یه‌روزرسانی", "Refresh" : "تازه‌سازی", + "Remove" : "حذف", "Share folder" : "اشتراک‌گذاری پوشه", "Reset" : "بازنشاندن", "Continue" : "ادامه دادن", diff --git a/l10n/fi.js b/l10n/fi.js index 0d5e545a..8503f275 100644 --- a/l10n/fi.js +++ b/l10n/fi.js @@ -107,6 +107,7 @@ OC.L10N.register( "You cannot share the root folder" : "Et voi jakaa juurikansiota", "Use the sidebar to share this folder." : "Käytä sivupalkkia jakaaksesi tämän kansion.", "Refresh" : "Päivitä", + "Remove" : "Poista", "Share album" : "Jaa albumi", "Delete album" : "Poista albumi", "Merge with different person" : "Yhdistä toisen henkilön kanssa", diff --git a/l10n/fi.json b/l10n/fi.json index dbb63006..f75d4fa7 100644 --- a/l10n/fi.json +++ b/l10n/fi.json @@ -105,6 +105,7 @@ "You cannot share the root folder" : "Et voi jakaa juurikansiota", "Use the sidebar to share this folder." : "Käytä sivupalkkia jakaaksesi tämän kansion.", "Refresh" : "Päivitä", + "Remove" : "Poista", "Share album" : "Jaa albumi", "Delete album" : "Poista albumi", "Merge with different person" : "Yhdistä toisen henkilön kanssa", diff --git a/l10n/fr.js b/l10n/fr.js index 4a8fa48c..57cbb38a 100644 --- a/l10n/fr.js +++ b/l10n/fr.js @@ -105,6 +105,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "Utiliser la barre latérale pour partager ce dossier.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si vous créez un partage de lien public, cliquez sur rafraîchir et un lien correspondant à Souvenirs sera visible ci-dessous.", "Refresh" : "Actualiser", + "Remove" : "Retirer", "Delete album" : "Supprimer l'album", "Merge with different person" : "Fusionner avec une différente personne", "Share folder" : "Partager le dossier", diff --git a/l10n/fr.json b/l10n/fr.json index c9670f8b..d5827338 100644 --- a/l10n/fr.json +++ b/l10n/fr.json @@ -103,6 +103,7 @@ "Use the sidebar to share this folder." : "Utiliser la barre latérale pour partager ce dossier.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si vous créez un partage de lien public, cliquez sur rafraîchir et un lien correspondant à Souvenirs sera visible ci-dessous.", "Refresh" : "Actualiser", + "Remove" : "Retirer", "Delete album" : "Supprimer l'album", "Merge with different person" : "Fusionner avec une différente personne", "Share folder" : "Partager le dossier", diff --git a/l10n/gd.js b/l10n/gd.js index 89df6194..c0b032b3 100644 --- a/l10n/gd.js +++ b/l10n/gd.js @@ -15,6 +15,7 @@ OC.L10N.register( "Save" : "Sàbhail", "Name" : "Ainm", "Refresh" : "Ath-nuadhaich", + "Remove" : "Thoir air falbh", "Undo" : "Neo-dhèan" }, "nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;"); diff --git a/l10n/gd.json b/l10n/gd.json index 0ff3a547..94fb6346 100644 --- a/l10n/gd.json +++ b/l10n/gd.json @@ -13,6 +13,7 @@ "Save" : "Sàbhail", "Name" : "Ainm", "Refresh" : "Ath-nuadhaich", + "Remove" : "Thoir air falbh", "Undo" : "Neo-dhèan" },"pluralForm" :"nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;" } \ No newline at end of file diff --git a/l10n/gl.js b/l10n/gl.js index 4d9591c4..32be2af7 100644 --- a/l10n/gl.js +++ b/l10n/gl.js @@ -33,6 +33,7 @@ OC.L10N.register( "Name" : "Nome", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Retirar", "Reset" : "Restabelecer", "Continue" : "Continuar", "Undo" : "Desfacer", diff --git a/l10n/gl.json b/l10n/gl.json index b4ad77c8..dc1f9bf4 100644 --- a/l10n/gl.json +++ b/l10n/gl.json @@ -31,6 +31,7 @@ "Name" : "Nome", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Retirar", "Reset" : "Restabelecer", "Continue" : "Continuar", "Undo" : "Desfacer", diff --git a/l10n/he.js b/l10n/he.js index d23dd986..19b1e757 100644 --- a/l10n/he.js +++ b/l10n/he.js @@ -32,6 +32,7 @@ OC.L10N.register( "Name" : "שם", "Update" : "עדכון", "Refresh" : "רענון", + "Remove" : "הסרה", "Reset" : "איפוס", "Continue" : "להמשך", "Undo" : "ביטול", diff --git a/l10n/he.json b/l10n/he.json index f093d213..cfae3dd0 100644 --- a/l10n/he.json +++ b/l10n/he.json @@ -30,6 +30,7 @@ "Name" : "שם", "Update" : "עדכון", "Refresh" : "רענון", + "Remove" : "הסרה", "Reset" : "איפוס", "Continue" : "להמשך", "Undo" : "ביטול", diff --git a/l10n/hr.js b/l10n/hr.js index 6d0a94f8..ebad7be5 100644 --- a/l10n/hr.js +++ b/l10n/hr.js @@ -33,6 +33,7 @@ OC.L10N.register( "Name" : "Naziv", "Update" : "Ažuriraj", "Refresh" : "Osvježi", + "Remove" : "Ukloni", "Share folder" : "Dijeli mapu", "Reset" : "Resetiraj", "Continue" : "Nastavi", diff --git a/l10n/hr.json b/l10n/hr.json index 43f8a950..831150b7 100644 --- a/l10n/hr.json +++ b/l10n/hr.json @@ -31,6 +31,7 @@ "Name" : "Naziv", "Update" : "Ažuriraj", "Refresh" : "Osvježi", + "Remove" : "Ukloni", "Share folder" : "Dijeli mapu", "Reset" : "Resetiraj", "Continue" : "Nastavi", diff --git a/l10n/hu.js b/l10n/hu.js index 41c6cc3f..d6c229ff 100644 --- a/l10n/hu.js +++ b/l10n/hu.js @@ -85,6 +85,7 @@ OC.L10N.register( "Rename person" : "Személy átnevezése", "Update" : "Frissítés", "Refresh" : "Frissítés", + "Remove" : "Eltávolítás", "Delete album" : "Album törlése", "Merge with different person" : "Összevonás egy másik személlyel", "Share folder" : "Mappa megosztása", diff --git a/l10n/hu.json b/l10n/hu.json index cd01eaa7..abd63e53 100644 --- a/l10n/hu.json +++ b/l10n/hu.json @@ -83,6 +83,7 @@ "Rename person" : "Személy átnevezése", "Update" : "Frissítés", "Refresh" : "Frissítés", + "Remove" : "Eltávolítás", "Delete album" : "Album törlése", "Merge with different person" : "Összevonás egy másik személlyel", "Share folder" : "Mappa megosztása", diff --git a/l10n/id.js b/l10n/id.js index fbe4dfe7..c5a77fac 100644 --- a/l10n/id.js +++ b/l10n/id.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Nama", "Update" : "Perbarui", "Refresh" : "Muat ulang", + "Remove" : "Buang", "Reset" : "Setel ulang", "Continue" : "Lanjutkan", "Undo" : "Undo", diff --git a/l10n/id.json b/l10n/id.json index 166e369b..254827eb 100644 --- a/l10n/id.json +++ b/l10n/id.json @@ -24,6 +24,7 @@ "Name" : "Nama", "Update" : "Perbarui", "Refresh" : "Muat ulang", + "Remove" : "Buang", "Reset" : "Setel ulang", "Continue" : "Lanjutkan", "Undo" : "Undo", diff --git a/l10n/is.js b/l10n/is.js index 87bfe66d..3d246e28 100644 --- a/l10n/is.js +++ b/l10n/is.js @@ -34,6 +34,7 @@ OC.L10N.register( "Name" : "Heiti", "Update" : "Uppfæra", "Refresh" : "Endurnýja", + "Remove" : "Fjarlægja", "Reset" : "Endurstilla", "Continue" : "Halda áfram", "Undo" : "Undo", diff --git a/l10n/is.json b/l10n/is.json index 093244b0..2465dfdd 100644 --- a/l10n/is.json +++ b/l10n/is.json @@ -32,6 +32,7 @@ "Name" : "Heiti", "Update" : "Uppfæra", "Refresh" : "Endurnýja", + "Remove" : "Fjarlægja", "Reset" : "Endurstilla", "Continue" : "Halda áfram", "Undo" : "Undo", diff --git a/l10n/it.js b/l10n/it.js index 033b781a..a5255172 100644 --- a/l10n/it.js +++ b/l10n/it.js @@ -54,6 +54,7 @@ OC.L10N.register( "Rename person" : "Rinomina persona", "Update" : "Aggiorna", "Refresh" : "Aggiorna", + "Remove" : "Rimuovi", "Delete album" : "Elimina album", "Merge with different person" : "Unisci ad un'altra persona", "Share folder" : "Condividi cartella", diff --git a/l10n/it.json b/l10n/it.json index cced2d39..caacafb6 100644 --- a/l10n/it.json +++ b/l10n/it.json @@ -52,6 +52,7 @@ "Rename person" : "Rinomina persona", "Update" : "Aggiorna", "Refresh" : "Aggiorna", + "Remove" : "Rimuovi", "Delete album" : "Elimina album", "Merge with different person" : "Unisci ad un'altra persona", "Share folder" : "Condividi cartella", diff --git a/l10n/ja.js b/l10n/ja.js index 90aa8137..c6cbf833 100644 --- a/l10n/ja.js +++ b/l10n/ja.js @@ -42,6 +42,7 @@ OC.L10N.register( "Name" : "名前", "Update" : "更新", "Refresh" : "更新", + "Remove" : "削除", "Share folder" : "フォルダーを共有", "Reset" : "リセット", "All changes will be lost." : "全ての変更がなくなります", diff --git a/l10n/ja.json b/l10n/ja.json index bff1fd3b..8c4d589b 100644 --- a/l10n/ja.json +++ b/l10n/ja.json @@ -40,6 +40,7 @@ "Name" : "名前", "Update" : "更新", "Refresh" : "更新", + "Remove" : "削除", "Share folder" : "フォルダーを共有", "Reset" : "リセット", "All changes will be lost." : "全ての変更がなくなります", diff --git a/l10n/ka_GE.js b/l10n/ka_GE.js index 6db14874..d6bc89a3 100644 --- a/l10n/ka_GE.js +++ b/l10n/ka_GE.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "სახელი", "Update" : "განახლება", "Refresh" : "განახლება", + "Remove" : "წაშლა", "Reset" : "საწყის მდოგმარეობაში დაბრუნება", "Continue" : "გაგრძელება", "Undo" : "დაბრუნება", diff --git a/l10n/ka_GE.json b/l10n/ka_GE.json index 41069df2..997e5b6a 100644 --- a/l10n/ka_GE.json +++ b/l10n/ka_GE.json @@ -24,6 +24,7 @@ "Name" : "სახელი", "Update" : "განახლება", "Refresh" : "განახლება", + "Remove" : "წაშლა", "Reset" : "საწყის მდოგმარეობაში დაბრუნება", "Continue" : "გაგრძელება", "Undo" : "დაბრუნება", diff --git a/l10n/kab.js b/l10n/kab.js index ad2a8775..bbba92d4 100644 --- a/l10n/kab.js +++ b/l10n/kab.js @@ -16,6 +16,7 @@ OC.L10N.register( "Hour" : "Asrag", "Name" : "Nom", "Refresh" : "Sismeḍ", + "Remove" : "Kkes", "Continue" : "Continuer", "Size" : "Teɣzi" }, diff --git a/l10n/kab.json b/l10n/kab.json index 63f3ef15..b23f3ba7 100644 --- a/l10n/kab.json +++ b/l10n/kab.json @@ -14,6 +14,7 @@ "Hour" : "Asrag", "Name" : "Nom", "Refresh" : "Sismeḍ", + "Remove" : "Kkes", "Continue" : "Continuer", "Size" : "Teɣzi" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/l10n/km.js b/l10n/km.js index ce4a4429..de2960b5 100644 --- a/l10n/km.js +++ b/l10n/km.js @@ -18,6 +18,7 @@ OC.L10N.register( "Time" : "ម៉ោង", "Name" : "ឈ្មោះ", "Update" : "ធ្វើ​បច្ចុប្បន្នភាព", + "Remove" : "ដកចេញ", "Continue" : "បន្ត", "Value" : "តម្លៃ", "Line" : "បន្ទាត់", diff --git a/l10n/km.json b/l10n/km.json index 0f3ee5cb..cd73b8af 100644 --- a/l10n/km.json +++ b/l10n/km.json @@ -16,6 +16,7 @@ "Time" : "ម៉ោង", "Name" : "ឈ្មោះ", "Update" : "ធ្វើ​បច្ចុប្បន្នភាព", + "Remove" : "ដកចេញ", "Continue" : "បន្ត", "Value" : "តម្លៃ", "Line" : "បន្ទាត់", diff --git a/l10n/kn.js b/l10n/kn.js index e8481205..01462cf5 100644 --- a/l10n/kn.js +++ b/l10n/kn.js @@ -13,6 +13,7 @@ OC.L10N.register( "Save" : "ಉಳಿಸಿ", "Time" : "ಸಮಯ", "Name" : "ಹೆಸರು", + "Remove" : "ತೆಗೆದುಹಾಕಿ", "Reset" : "ಮರುಹೊಂದಿಸಿ", "Continue" : "ಮುಂದುವರಿಸಿ", "Size" : " ಗಾತ್ರ" diff --git a/l10n/kn.json b/l10n/kn.json index 550a8279..b02bf403 100644 --- a/l10n/kn.json +++ b/l10n/kn.json @@ -11,6 +11,7 @@ "Save" : "ಉಳಿಸಿ", "Time" : "ಸಮಯ", "Name" : "ಹೆಸರು", + "Remove" : "ತೆಗೆದುಹಾಕಿ", "Reset" : "ಮರುಹೊಂದಿಸಿ", "Continue" : "ಮುಂದುವರಿಸಿ", "Size" : " ಗಾತ್ರ" diff --git a/l10n/ko.js b/l10n/ko.js index 37b03299..800603eb 100644 --- a/l10n/ko.js +++ b/l10n/ko.js @@ -31,6 +31,7 @@ OC.L10N.register( "Name" : "이름", "Update" : "업데이트", "Refresh" : "새로 고침", + "Remove" : "삭제", "Reset" : "초기화", "Continue" : "계속", "Undo" : "실행 취소", diff --git a/l10n/ko.json b/l10n/ko.json index 783115f2..62749376 100644 --- a/l10n/ko.json +++ b/l10n/ko.json @@ -29,6 +29,7 @@ "Name" : "이름", "Update" : "업데이트", "Refresh" : "새로 고침", + "Remove" : "삭제", "Reset" : "초기화", "Continue" : "계속", "Undo" : "실행 취소", diff --git a/l10n/lb.js b/l10n/lb.js index fff5088a..22b6ad8f 100644 --- a/l10n/lb.js +++ b/l10n/lb.js @@ -21,6 +21,7 @@ OC.L10N.register( "Name" : "Numm", "Update" : "Update", "Refresh" : "Opfrëschen", + "Remove" : "Läschen", "Reset" : "Zeréck setzen", "Continue" : "Weider", "Custom" : "Individualiséier", diff --git a/l10n/lb.json b/l10n/lb.json index b6b9dccc..8fa4b101 100644 --- a/l10n/lb.json +++ b/l10n/lb.json @@ -19,6 +19,7 @@ "Name" : "Numm", "Update" : "Update", "Refresh" : "Opfrëschen", + "Remove" : "Läschen", "Reset" : "Zeréck setzen", "Continue" : "Weider", "Custom" : "Individualiséier", diff --git a/l10n/lo.js b/l10n/lo.js index 81ee13d9..e4eb65d4 100644 --- a/l10n/lo.js +++ b/l10n/lo.js @@ -17,6 +17,7 @@ OC.L10N.register( "Save" : "ບັນທຶກ", "Name" : "ຊື່", "Refresh" : "Refresh", + "Remove" : "ຍ້າຍອອກ", "Continue" : "ສືບຕໍ່", "Original" : "ຕົ້ນສະບັບ", "Size" : "ຂະຫນາດ" diff --git a/l10n/lo.json b/l10n/lo.json index 74e031ee..dc081a26 100644 --- a/l10n/lo.json +++ b/l10n/lo.json @@ -15,6 +15,7 @@ "Save" : "ບັນທຶກ", "Name" : "ຊື່", "Refresh" : "Refresh", + "Remove" : "ຍ້າຍອອກ", "Continue" : "ສືບຕໍ່", "Original" : "ຕົ້ນສະບັບ", "Size" : "ຂະຫນາດ" diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js index 668be953..d89ebc8e 100644 --- a/l10n/lt_LT.js +++ b/l10n/lt_LT.js @@ -90,6 +90,7 @@ OC.L10N.register( "Failed to move {name}." : "Nepavyko perkelti {name}.", "Share Folder" : "Bendrinti aplanką", "Refresh" : "Įkelti iš naujo", + "Remove" : "Šalinti", "Share album" : "Bendrinti albumą", "Delete album" : "Ištrinti albumą", "Merge with different person" : "Sulieti su kitu žmogumi", diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json index c52589fa..1ef85ba0 100644 --- a/l10n/lt_LT.json +++ b/l10n/lt_LT.json @@ -88,6 +88,7 @@ "Failed to move {name}." : "Nepavyko perkelti {name}.", "Share Folder" : "Bendrinti aplanką", "Refresh" : "Įkelti iš naujo", + "Remove" : "Šalinti", "Share album" : "Bendrinti albumą", "Delete album" : "Ištrinti albumą", "Merge with different person" : "Sulieti su kitu žmogumi", diff --git a/l10n/lv.js b/l10n/lv.js index 6ef91885..4c55d1c4 100644 --- a/l10n/lv.js +++ b/l10n/lv.js @@ -35,6 +35,7 @@ OC.L10N.register( "Update" : "Atjaunināt", "Share Folder" : "Kopīgot mapi", "Refresh" : "Atsvaidzināt", + "Remove" : "Noņemt", "Save as" : "Saglabāt kā", "Reset" : "Atiestatīt", "Continue" : "Turpināt", diff --git a/l10n/lv.json b/l10n/lv.json index a7d13cb6..fe87e73c 100644 --- a/l10n/lv.json +++ b/l10n/lv.json @@ -33,6 +33,7 @@ "Update" : "Atjaunināt", "Share Folder" : "Kopīgot mapi", "Refresh" : "Atsvaidzināt", + "Remove" : "Noņemt", "Save as" : "Saglabāt kā", "Reset" : "Atiestatīt", "Continue" : "Turpināt", diff --git a/l10n/mk.js b/l10n/mk.js index a6545c46..0d6b14e9 100644 --- a/l10n/mk.js +++ b/l10n/mk.js @@ -45,6 +45,7 @@ OC.L10N.register( "Rename person" : "Преименувај личност", "Update" : "Ажурирај", "Refresh" : "Освежи", + "Remove" : "Отстрани ", "Delete album" : "Избриши албум", "Merge with different person" : "Спој со друга личност", "Share folder" : "Сподели папка", diff --git a/l10n/mk.json b/l10n/mk.json index 61a34703..af353775 100644 --- a/l10n/mk.json +++ b/l10n/mk.json @@ -43,6 +43,7 @@ "Rename person" : "Преименувај личност", "Update" : "Ажурирај", "Refresh" : "Освежи", + "Remove" : "Отстрани ", "Delete album" : "Избриши албум", "Merge with different person" : "Спој со друга личност", "Share folder" : "Сподели папка", diff --git a/l10n/mn.js b/l10n/mn.js index 04b030a1..804d009d 100644 --- a/l10n/mn.js +++ b/l10n/mn.js @@ -25,6 +25,7 @@ OC.L10N.register( "Name" : "Нэр", "Update" : "Шинэчлэх", "Refresh" : "Сэргээх", + "Remove" : "Устгах", "Reset" : "тохируулах", "Continue" : "үргэлжлүүлэх", "Undo" : "буцах", diff --git a/l10n/mn.json b/l10n/mn.json index 9e987dd0..febd8b2b 100644 --- a/l10n/mn.json +++ b/l10n/mn.json @@ -23,6 +23,7 @@ "Name" : "Нэр", "Update" : "Шинэчлэх", "Refresh" : "Сэргээх", + "Remove" : "Устгах", "Reset" : "тохируулах", "Continue" : "үргэлжлүүлэх", "Undo" : "буцах", diff --git a/l10n/ms_MY.js b/l10n/ms_MY.js index ad8adcc8..993eaf0d 100644 --- a/l10n/ms_MY.js +++ b/l10n/ms_MY.js @@ -15,6 +15,7 @@ OC.L10N.register( "Name" : "Nama", "Update" : "Kemaskini", "Refresh" : "Refresh", + "Remove" : "Buang", "Size" : "Saiz" }, "nplurals=1; plural=0;"); diff --git a/l10n/ms_MY.json b/l10n/ms_MY.json index bdef3a5c..df3a6ca6 100644 --- a/l10n/ms_MY.json +++ b/l10n/ms_MY.json @@ -13,6 +13,7 @@ "Name" : "Nama", "Update" : "Kemaskini", "Refresh" : "Refresh", + "Remove" : "Buang", "Size" : "Saiz" },"pluralForm" :"nplurals=1; plural=0;" } \ No newline at end of file diff --git a/l10n/nb.js b/l10n/nb.js index 93c187d3..c8a9c3e6 100644 --- a/l10n/nb.js +++ b/l10n/nb.js @@ -33,6 +33,7 @@ OC.L10N.register( "Name" : "Navn", "Update" : "Oppdater", "Refresh" : "Oppdater", + "Remove" : "Fjern", "Share folder" : "Del mappe", "Save as" : "Lagre som", "Reset" : "Tilbakestill", diff --git a/l10n/nb.json b/l10n/nb.json index 382d4ac3..14e32996 100644 --- a/l10n/nb.json +++ b/l10n/nb.json @@ -31,6 +31,7 @@ "Name" : "Navn", "Update" : "Oppdater", "Refresh" : "Oppdater", + "Remove" : "Fjern", "Share folder" : "Del mappe", "Save as" : "Lagre som", "Reset" : "Tilbakestill", diff --git a/l10n/nl.js b/l10n/nl.js index b52cc3b0..b69994c6 100644 --- a/l10n/nl.js +++ b/l10n/nl.js @@ -35,6 +35,7 @@ OC.L10N.register( "Name" : "Naam", "Update" : "Update", "Refresh" : "Verversen", + "Remove" : "Verwijderen", "Share folder" : "Map delen", "Reset" : "Herstellen", "Continue" : "Doorgaan", diff --git a/l10n/nl.json b/l10n/nl.json index d600ac9f..a7da3d57 100644 --- a/l10n/nl.json +++ b/l10n/nl.json @@ -33,6 +33,7 @@ "Name" : "Naam", "Update" : "Update", "Refresh" : "Verversen", + "Remove" : "Verwijderen", "Share folder" : "Map delen", "Reset" : "Herstellen", "Continue" : "Doorgaan", diff --git a/l10n/nn_NO.js b/l10n/nn_NO.js index e38cff24..ba0cea64 100644 --- a/l10n/nn_NO.js +++ b/l10n/nn_NO.js @@ -21,6 +21,7 @@ OC.L10N.register( "Name" : "Namn", "Update" : "Oppdater", "Refresh" : "Last inn på nytt", + "Remove" : "Fjern", "Continue" : "Gå vidare", "Value" : "Verdi", "Size" : "Storleik" diff --git a/l10n/nn_NO.json b/l10n/nn_NO.json index 86f97d25..6507821f 100644 --- a/l10n/nn_NO.json +++ b/l10n/nn_NO.json @@ -19,6 +19,7 @@ "Name" : "Namn", "Update" : "Oppdater", "Refresh" : "Last inn på nytt", + "Remove" : "Fjern", "Continue" : "Gå vidare", "Value" : "Verdi", "Size" : "Storleik" diff --git a/l10n/oc.js b/l10n/oc.js index ef6e1396..ade963c7 100644 --- a/l10n/oc.js +++ b/l10n/oc.js @@ -30,6 +30,7 @@ OC.L10N.register( "Name" : "Nom", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Suprimir", "Reset" : "Reïnicializar", "Continue" : "Contunhar", "Undo" : "Desfar", diff --git a/l10n/oc.json b/l10n/oc.json index cc9a344f..b41a982e 100644 --- a/l10n/oc.json +++ b/l10n/oc.json @@ -28,6 +28,7 @@ "Name" : "Nom", "Update" : "Actualizar", "Refresh" : "Actualizar", + "Remove" : "Suprimir", "Reset" : "Reïnicializar", "Continue" : "Contunhar", "Undo" : "Desfar", diff --git a/l10n/pl.js b/l10n/pl.js index 98539d30..56a70019 100644 --- a/l10n/pl.js +++ b/l10n/pl.js @@ -82,6 +82,7 @@ OC.L10N.register( "Rename person" : "Zmień nazwę osoby", "Update" : "Aktualizuj", "Refresh" : "Odśwież", + "Remove" : "Usuń", "Delete album" : "Usuń album", "Merge with different person" : "Połącz z inną osobą", "Share folder" : "Udostępnij katalog", diff --git a/l10n/pl.json b/l10n/pl.json index a243670e..549422fb 100644 --- a/l10n/pl.json +++ b/l10n/pl.json @@ -80,6 +80,7 @@ "Rename person" : "Zmień nazwę osoby", "Update" : "Aktualizuj", "Refresh" : "Odśwież", + "Remove" : "Usuń", "Delete album" : "Usuń album", "Merge with different person" : "Połącz z inną osobą", "Share folder" : "Udostępnij katalog", diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js index b875cb43..142658c1 100644 --- a/l10n/pt_BR.js +++ b/l10n/pt_BR.js @@ -110,6 +110,7 @@ OC.L10N.register( "Move selected photos to person" : "Mover fotos selecionadas para pessoa", "Are you sure you want to move the selected photos from {name} to {newName}?" : "Tem certeza de que deseja mover as fotos selecionadas de {name} para {newName}?", "Refresh" : "Atualizar", + "Remove" : "Remover", "Delete album" : "Remover álbum", "Merge with different person" : "Unir com outra pessoa", "Mark person in preview" : "Marcar pessoa na visualização", diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json index cba3958f..baa8c1be 100644 --- a/l10n/pt_BR.json +++ b/l10n/pt_BR.json @@ -108,6 +108,7 @@ "Move selected photos to person" : "Mover fotos selecionadas para pessoa", "Are you sure you want to move the selected photos from {name} to {newName}?" : "Tem certeza de que deseja mover as fotos selecionadas de {name} para {newName}?", "Refresh" : "Atualizar", + "Remove" : "Remover", "Delete album" : "Remover álbum", "Merge with different person" : "Unir com outra pessoa", "Mark person in preview" : "Marcar pessoa na visualização", diff --git a/l10n/pt_PT.js b/l10n/pt_PT.js index 3d4aaca8..c6720693 100644 --- a/l10n/pt_PT.js +++ b/l10n/pt_PT.js @@ -36,6 +36,7 @@ OC.L10N.register( "Name" : "Nome", "Update" : "Atualizar", "Refresh" : "Atualizar", + "Remove" : "Remover", "Share folder" : "Partilhar pasta", "Reset" : "Reiniciar", "Continue" : "Continuar", diff --git a/l10n/pt_PT.json b/l10n/pt_PT.json index f2212fda..0ebb9372 100644 --- a/l10n/pt_PT.json +++ b/l10n/pt_PT.json @@ -34,6 +34,7 @@ "Name" : "Nome", "Update" : "Atualizar", "Refresh" : "Atualizar", + "Remove" : "Remover", "Share folder" : "Partilhar pasta", "Reset" : "Reiniciar", "Continue" : "Continuar", diff --git a/l10n/ro.js b/l10n/ro.js index 0f690abf..df876cbd 100644 --- a/l10n/ro.js +++ b/l10n/ro.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Nume", "Update" : "Actualizare", "Refresh" : "Reîmprospătează", + "Remove" : "Elimină", "Share folder" : "Distribuie dosar", "Reset" : "Resetare", "Continue" : "Continuă", diff --git a/l10n/ro.json b/l10n/ro.json index 7c82c3e8..f452423a 100644 --- a/l10n/ro.json +++ b/l10n/ro.json @@ -26,6 +26,7 @@ "Name" : "Nume", "Update" : "Actualizare", "Refresh" : "Reîmprospătează", + "Remove" : "Elimină", "Share folder" : "Distribuie dosar", "Reset" : "Resetare", "Continue" : "Continuă", diff --git a/l10n/ru.js b/l10n/ru.js index 84d461f8..d8d2fb38 100644 --- a/l10n/ru.js +++ b/l10n/ru.js @@ -45,6 +45,7 @@ OC.L10N.register( "Name" : "Имя", "Update" : "Обновить", "Refresh" : "Обновить", + "Remove" : "Удалить", "Share folder" : "Поделиться папкой", "Save as" : "Сохранить как", "Reset" : "Сброс", diff --git a/l10n/ru.json b/l10n/ru.json index 2bf5d1b7..22c40c28 100644 --- a/l10n/ru.json +++ b/l10n/ru.json @@ -43,6 +43,7 @@ "Name" : "Имя", "Update" : "Обновить", "Refresh" : "Обновить", + "Remove" : "Удалить", "Share folder" : "Поделиться папкой", "Save as" : "Сохранить как", "Reset" : "Сброс", diff --git a/l10n/sc.js b/l10n/sc.js index 902b52f9..d3e3679f 100644 --- a/l10n/sc.js +++ b/l10n/sc.js @@ -33,6 +33,7 @@ OC.L10N.register( "Name" : "Nùmene", "Update" : "Agiorna", "Refresh" : "Agiorna", + "Remove" : "Boga", "Share folder" : "Cumpartzi cartella", "Reset" : "Torra a impostare", "Continue" : "Sighi", diff --git a/l10n/sc.json b/l10n/sc.json index 91b589ec..cd5b5565 100644 --- a/l10n/sc.json +++ b/l10n/sc.json @@ -31,6 +31,7 @@ "Name" : "Nùmene", "Update" : "Agiorna", "Refresh" : "Agiorna", + "Remove" : "Boga", "Share folder" : "Cumpartzi cartella", "Reset" : "Torra a impostare", "Continue" : "Sighi", diff --git a/l10n/si.js b/l10n/si.js index 704ba7c0..f0844f9d 100644 --- a/l10n/si.js +++ b/l10n/si.js @@ -20,6 +20,7 @@ OC.L10N.register( "Time" : "වේලාව", "Name" : "නම", "Update" : "යාවත්කාල", + "Remove" : "ඉවත් කරන්න", "Undo" : "පෙරසේ", "Value" : "අගය", "Size" : "ප්‍රමාණය" diff --git a/l10n/si.json b/l10n/si.json index 9a1e7fed..bd4928a9 100644 --- a/l10n/si.json +++ b/l10n/si.json @@ -18,6 +18,7 @@ "Time" : "වේලාව", "Name" : "නම", "Update" : "යාවත්කාල", + "Remove" : "ඉවත් කරන්න", "Undo" : "පෙරසේ", "Value" : "අගය", "Size" : "ප්‍රමාණය" diff --git a/l10n/sk.js b/l10n/sk.js index 8b979448..86fd56b3 100644 --- a/l10n/sk.js +++ b/l10n/sk.js @@ -93,6 +93,7 @@ OC.L10N.register( "Error while moving {basename}" : "Chyba pri presúvaní {basename}", "Failed to move {name}." : "Nepodarilo sa presunúť {name}.", "Refresh" : "Obnoviť", + "Remove" : "Odobrať", "Delete album" : "Zmazať album", "Merge with different person" : "Spojiť s inou osobou", "Share folder" : "Zdieľať priečinok", diff --git a/l10n/sk.json b/l10n/sk.json index e02db2e8..4ab2812b 100644 --- a/l10n/sk.json +++ b/l10n/sk.json @@ -91,6 +91,7 @@ "Error while moving {basename}" : "Chyba pri presúvaní {basename}", "Failed to move {name}." : "Nepodarilo sa presunúť {name}.", "Refresh" : "Obnoviť", + "Remove" : "Odobrať", "Delete album" : "Zmazať album", "Merge with different person" : "Spojiť s inou osobou", "Share folder" : "Zdieľať priečinok", diff --git a/l10n/sl.js b/l10n/sl.js index 19883da4..66e1c043 100644 --- a/l10n/sl.js +++ b/l10n/sl.js @@ -39,6 +39,7 @@ OC.L10N.register( "Name" : "Ime", "Update" : "Posodobi", "Refresh" : "Osveži", + "Remove" : "Odstrani", "Share folder" : "Omogoči souporabo mape", "Reset" : "Ponastavi", "Continue" : "Nadaljuj", diff --git a/l10n/sl.json b/l10n/sl.json index 0dadba3d..8a82fda0 100644 --- a/l10n/sl.json +++ b/l10n/sl.json @@ -37,6 +37,7 @@ "Name" : "Ime", "Update" : "Posodobi", "Refresh" : "Osveži", + "Remove" : "Odstrani", "Share folder" : "Omogoči souporabo mape", "Reset" : "Ponastavi", "Continue" : "Nadaljuj", diff --git a/l10n/sq.js b/l10n/sq.js index 59317995..d7f13f47 100644 --- a/l10n/sq.js +++ b/l10n/sq.js @@ -26,6 +26,7 @@ OC.L10N.register( "Name" : "Emri", "Update" : "Përditëso", "Refresh" : "Rifresko", + "Remove" : "Hiq", "Reset" : "Rivendos", "Continue" : "Vazhdo", "Undo" : "Ktheje pas", diff --git a/l10n/sq.json b/l10n/sq.json index 44fd2057..47fc0b13 100644 --- a/l10n/sq.json +++ b/l10n/sq.json @@ -24,6 +24,7 @@ "Name" : "Emri", "Update" : "Përditëso", "Refresh" : "Rifresko", + "Remove" : "Hiq", "Reset" : "Rivendos", "Continue" : "Vazhdo", "Undo" : "Ktheje pas", diff --git a/l10n/sr.js b/l10n/sr.js index f5da664a..bbfe298c 100644 --- a/l10n/sr.js +++ b/l10n/sr.js @@ -33,6 +33,7 @@ OC.L10N.register( "Name" : "Име", "Update" : "Ажурирај", "Refresh" : "Освежи", + "Remove" : "Уклони", "Reset" : "Ресетуј", "Continue" : "Настави", "Undo" : "Опозови", diff --git a/l10n/sr.json b/l10n/sr.json index 04c2b582..3d219a83 100644 --- a/l10n/sr.json +++ b/l10n/sr.json @@ -31,6 +31,7 @@ "Name" : "Име", "Update" : "Ажурирај", "Refresh" : "Освежи", + "Remove" : "Уклони", "Reset" : "Ресетуј", "Continue" : "Настави", "Undo" : "Опозови", diff --git a/l10n/sr@latin.js b/l10n/sr@latin.js index dfb67f3f..64711c6e 100644 --- a/l10n/sr@latin.js +++ b/l10n/sr@latin.js @@ -16,6 +16,7 @@ OC.L10N.register( "Name" : "Ime", "Update" : "Ažuriraj", "Refresh" : "Osveži", + "Remove" : "Ukloni", "Undo" : "Opozovi" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/l10n/sr@latin.json b/l10n/sr@latin.json index 6e85a878..9b01ee08 100644 --- a/l10n/sr@latin.json +++ b/l10n/sr@latin.json @@ -14,6 +14,7 @@ "Name" : "Ime", "Update" : "Ažuriraj", "Refresh" : "Osveži", + "Remove" : "Ukloni", "Undo" : "Opozovi" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" } \ No newline at end of file diff --git a/l10n/sv.js b/l10n/sv.js index 267b3ee9..d6454f09 100644 --- a/l10n/sv.js +++ b/l10n/sv.js @@ -52,6 +52,7 @@ OC.L10N.register( "Name" : "Namn", "Update" : "Uppdatera", "Refresh" : "Uppdatera", + "Remove" : "Ta bort", "Share folder" : "Dela mapp", "Reset" : "Återställ", "Continue" : "Fortsätt", diff --git a/l10n/sv.json b/l10n/sv.json index 1f5ad73b..27c9b12f 100644 --- a/l10n/sv.json +++ b/l10n/sv.json @@ -50,6 +50,7 @@ "Name" : "Namn", "Update" : "Uppdatera", "Refresh" : "Uppdatera", + "Remove" : "Ta bort", "Share folder" : "Dela mapp", "Reset" : "Återställ", "Continue" : "Fortsätt", diff --git a/l10n/ta.js b/l10n/ta.js index dd456d0f..388b6dcd 100644 --- a/l10n/ta.js +++ b/l10n/ta.js @@ -16,6 +16,7 @@ OC.L10N.register( "Name" : "பெயர்", "Update" : "இற்றைப்படுத்தல்", "Refresh" : "மீள் ஏற்றுக", + "Remove" : "அகற்றுக", "Continue" : "Continue", "Value" : "Value", "Size" : "அளவு" diff --git a/l10n/ta.json b/l10n/ta.json index a149b509..1c02c5b1 100644 --- a/l10n/ta.json +++ b/l10n/ta.json @@ -14,6 +14,7 @@ "Name" : "பெயர்", "Update" : "இற்றைப்படுத்தல்", "Refresh" : "மீள் ஏற்றுக", + "Remove" : "அகற்றுக", "Continue" : "Continue", "Value" : "Value", "Size" : "அளவு" diff --git a/l10n/th.js b/l10n/th.js index 103b15d3..ffba94a8 100644 --- a/l10n/th.js +++ b/l10n/th.js @@ -24,6 +24,7 @@ OC.L10N.register( "Name" : "ชื่อ", "Update" : "อัปเดต", "Refresh" : "รีเฟรช", + "Remove" : "ลบออก", "Share folder" : "แชร์โฟลเดอร์", "Reset" : "ตั้งค่าใหม่", "Continue" : "ดำเนินการต่อ", diff --git a/l10n/th.json b/l10n/th.json index b336c076..ae8954ff 100644 --- a/l10n/th.json +++ b/l10n/th.json @@ -22,6 +22,7 @@ "Name" : "ชื่อ", "Update" : "อัปเดต", "Refresh" : "รีเฟรช", + "Remove" : "ลบออก", "Share folder" : "แชร์โฟลเดอร์", "Reset" : "ตั้งค่าใหม่", "Continue" : "ดำเนินการต่อ", diff --git a/l10n/tk.js b/l10n/tk.js index 49fdf11c..1c38a94e 100644 --- a/l10n/tk.js +++ b/l10n/tk.js @@ -14,6 +14,7 @@ OC.L10N.register( "Back" : "Yzyna", "Save" : "Saklamak", "Name" : "Ady", - "Refresh" : "Täzelemek" + "Refresh" : "Täzelemek", + "Remove" : "Aýyrmak" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/tk.json b/l10n/tk.json index 6129807d..fc3520e2 100644 --- a/l10n/tk.json +++ b/l10n/tk.json @@ -12,6 +12,7 @@ "Back" : "Yzyna", "Save" : "Saklamak", "Name" : "Ady", - "Refresh" : "Täzelemek" + "Refresh" : "Täzelemek", + "Remove" : "Aýyrmak" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/tr.js b/l10n/tr.js index 47085f8e..dc0cdd5b 100644 --- a/l10n/tr.js +++ b/l10n/tr.js @@ -129,6 +129,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "Bu klasörü paylaşmak için yan çubuğu kullanın.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Herkese açık bir bağlantı paylaşımı oluşturduktan sonra yenile üzerine tıklayın. Anılar için ilgili bağlantı aşağıda görüntülenir.", "Refresh" : "Yenlle", + "Remove" : "Kaldır", "Share album" : "Albümü paylaş", "Delete album" : "Albümü sil", "Merge with different person" : "Başka bir kişi ile birleştir", diff --git a/l10n/tr.json b/l10n/tr.json index 041915c0..fe7db735 100644 --- a/l10n/tr.json +++ b/l10n/tr.json @@ -127,6 +127,7 @@ "Use the sidebar to share this folder." : "Bu klasörü paylaşmak için yan çubuğu kullanın.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Herkese açık bir bağlantı paylaşımı oluşturduktan sonra yenile üzerine tıklayın. Anılar için ilgili bağlantı aşağıda görüntülenir.", "Refresh" : "Yenlle", + "Remove" : "Kaldır", "Share album" : "Albümü paylaş", "Delete album" : "Albümü sil", "Merge with different person" : "Başka bir kişi ile birleştir", diff --git a/l10n/ug.js b/l10n/ug.js index 308dfdbc..14fe96b6 100644 --- a/l10n/ug.js +++ b/l10n/ug.js @@ -16,6 +16,7 @@ OC.L10N.register( "Name" : "ئاتى", "Update" : "يېڭىلا", "Refresh" : "يېڭىلا", + "Remove" : "چىقىرىۋەت", "Size" : "چوڭلۇقى" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/ug.json b/l10n/ug.json index 43c4c0f0..641c9311 100644 --- a/l10n/ug.json +++ b/l10n/ug.json @@ -14,6 +14,7 @@ "Name" : "ئاتى", "Update" : "يېڭىلا", "Refresh" : "يېڭىلا", + "Remove" : "چىقىرىۋەت", "Size" : "چوڭلۇقى" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/uk.js b/l10n/uk.js index 2cb1c135..7400609f 100644 --- a/l10n/uk.js +++ b/l10n/uk.js @@ -74,6 +74,7 @@ OC.L10N.register( "Rename person" : "Перейменувати особу", "Update" : "Оновлення", "Refresh" : "Оновити", + "Remove" : "Вилучити", "Delete album" : "Видалити альбом", "Merge with different person" : "Злитися з іншою людиною", "Share folder" : "Спільний доступ для каталогу", diff --git a/l10n/uk.json b/l10n/uk.json index 8f0d101c..71910315 100644 --- a/l10n/uk.json +++ b/l10n/uk.json @@ -72,6 +72,7 @@ "Rename person" : "Перейменувати особу", "Update" : "Оновлення", "Refresh" : "Оновити", + "Remove" : "Вилучити", "Delete album" : "Видалити альбом", "Merge with different person" : "Злитися з іншою людиною", "Share folder" : "Спільний доступ для каталогу", diff --git a/l10n/uz.js b/l10n/uz.js index d4ef44d2..764f1ffb 100644 --- a/l10n/uz.js +++ b/l10n/uz.js @@ -14,6 +14,7 @@ OC.L10N.register( "Name" : "Name", "Update" : "Update", "Refresh" : "Refresh", + "Remove" : "Remove", "Continue" : "Continue", "Size" : "Size" }, diff --git a/l10n/uz.json b/l10n/uz.json index f0ec9181..f756e480 100644 --- a/l10n/uz.json +++ b/l10n/uz.json @@ -12,6 +12,7 @@ "Name" : "Name", "Update" : "Update", "Refresh" : "Refresh", + "Remove" : "Remove", "Continue" : "Continue", "Size" : "Size" },"pluralForm" :"nplurals=1; plural=0;" diff --git a/l10n/vi.js b/l10n/vi.js index 7c72362a..2c7c8a16 100644 --- a/l10n/vi.js +++ b/l10n/vi.js @@ -28,6 +28,7 @@ OC.L10N.register( "Name" : "Tên", "Update" : "Cập nhật", "Refresh" : "Tải mới", + "Remove" : "Xoá", "Reset" : "Đặt lại", "Continue" : "Tiếp tục", "Undo" : "Hoàn tác", diff --git a/l10n/vi.json b/l10n/vi.json index f1d9e2af..36b75fb3 100644 --- a/l10n/vi.json +++ b/l10n/vi.json @@ -26,6 +26,7 @@ "Name" : "Tên", "Update" : "Cập nhật", "Refresh" : "Tải mới", + "Remove" : "Xoá", "Reset" : "Đặt lại", "Continue" : "Tiếp tục", "Undo" : "Hoàn tác", diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js index 6db292b1..7484d9d9 100644 --- a/l10n/zh_CN.js +++ b/l10n/zh_CN.js @@ -65,6 +65,7 @@ OC.L10N.register( "Rename person" : "重命名用户", "Update" : "更新", "Refresh" : "刷新", + "Remove" : "移除", "Delete album" : "删除相册", "Merge with different person" : "与另一个人合并为同一人", "Share folder" : "共享文件夹", diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json index 5c4687c2..322ee301 100644 --- a/l10n/zh_CN.json +++ b/l10n/zh_CN.json @@ -63,6 +63,7 @@ "Rename person" : "重命名用户", "Update" : "更新", "Refresh" : "刷新", + "Remove" : "移除", "Delete album" : "删除相册", "Merge with different person" : "与另一个人合并为同一人", "Share folder" : "共享文件夹", diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js index 89eed547..b850f4ff 100644 --- a/l10n/zh_HK.js +++ b/l10n/zh_HK.js @@ -129,6 +129,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "使用側邊欄以分享此資料夾。", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "刷新", + "Remove" : "移除", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json index e6ba70d5..56cc93cd 100644 --- a/l10n/zh_HK.json +++ b/l10n/zh_HK.json @@ -127,6 +127,7 @@ "Use the sidebar to share this folder." : "使用側邊欄以分享此資料夾。", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "刷新", + "Remove" : "移除", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js index e51a6d19..562e0608 100644 --- a/l10n/zh_TW.js +++ b/l10n/zh_TW.js @@ -129,6 +129,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "使用側邊欄以分享此資料夾。", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "重新整理", + "Remove" : "移除", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json index c7c2c79f..2ae7c667 100644 --- a/l10n/zh_TW.json +++ b/l10n/zh_TW.json @@ -127,6 +127,7 @@ "Use the sidebar to share this folder." : "使用側邊欄以分享此資料夾。", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "重新整理", + "Remove" : "移除", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", From 3179d28dc6aad453e529d0d6efec3c8fe4fd69ac Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Fri, 18 Nov 2022 03:17:01 +0000 Subject: [PATCH 162/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/af.js | 1 + l10n/af.json | 1 + l10n/ar.js | 1 + l10n/ar.json | 1 + l10n/ast.js | 1 + l10n/ast.json | 1 + l10n/az.js | 1 + l10n/az.json | 1 + l10n/bg.js | 1 + l10n/bg.json | 1 + l10n/bn_BD.js | 1 + l10n/bn_BD.json | 1 + l10n/br.js | 1 + l10n/br.json | 1 + l10n/ca.js | 1 + l10n/ca.json | 1 + l10n/cs.js | 1 + l10n/cs.json | 1 + l10n/cy_GB.js | 1 + l10n/cy_GB.json | 1 + l10n/da.js | 1 + l10n/da.json | 1 + l10n/de_DE.js | 4 ++++ l10n/de_DE.json | 4 ++++ l10n/es.js | 6 ++++++ l10n/es.json | 6 ++++++ l10n/tr.js | 3 +++ l10n/tr.json | 3 +++ l10n/zh_HK.js | 3 +++ l10n/zh_HK.json | 3 +++ l10n/zh_TW.js | 3 +++ l10n/zh_TW.json | 3 +++ 32 files changed, 60 insertions(+) diff --git a/l10n/af.js b/l10n/af.js index aab4e7c2..1a1bb496 100644 --- a/l10n/af.js +++ b/l10n/af.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "Naam", "Update" : "Werk by", "Refresh" : "Verfris", + "Remove" : "Verwyder", "Reset" : "Herstel", "Continue" : "Gaan voort", "Original" : "Oorspronklik", diff --git a/l10n/af.json b/l10n/af.json index 75ac7447..9901a9c3 100644 --- a/l10n/af.json +++ b/l10n/af.json @@ -25,6 +25,7 @@ "Name" : "Naam", "Update" : "Werk by", "Refresh" : "Verfris", + "Remove" : "Verwyder", "Reset" : "Herstel", "Continue" : "Gaan voort", "Original" : "Oorspronklik", diff --git a/l10n/ar.js b/l10n/ar.js index d0e5decf..1aaf5102 100644 --- a/l10n/ar.js +++ b/l10n/ar.js @@ -27,6 +27,7 @@ OC.L10N.register( "Name" : "الاسم", "Update" : "تحديث", "Refresh" : "إنعاش", + "Remove" : "حذف", "Reset" : "إعادة الضبط", "Continue" : "متابعة", "Undo" : "تراجع", diff --git a/l10n/ar.json b/l10n/ar.json index 4a0e1703..c637ca8a 100644 --- a/l10n/ar.json +++ b/l10n/ar.json @@ -25,6 +25,7 @@ "Name" : "الاسم", "Update" : "تحديث", "Refresh" : "إنعاش", + "Remove" : "حذف", "Reset" : "إعادة الضبط", "Continue" : "متابعة", "Undo" : "تراجع", diff --git a/l10n/ast.js b/l10n/ast.js index 0349acb1..109535fc 100644 --- a/l10n/ast.js +++ b/l10n/ast.js @@ -25,6 +25,7 @@ OC.L10N.register( "Name" : "Nome", "Update" : "Anovar", "Refresh" : "Refrescar", + "Remove" : "Desaniciar", "Continue" : "Siguir", "Undo" : "Desfacer", "Custom" : "Personalizáu", diff --git a/l10n/ast.json b/l10n/ast.json index e3951694..f3aa9e19 100644 --- a/l10n/ast.json +++ b/l10n/ast.json @@ -23,6 +23,7 @@ "Name" : "Nome", "Update" : "Anovar", "Refresh" : "Refrescar", + "Remove" : "Desaniciar", "Continue" : "Siguir", "Undo" : "Desfacer", "Custom" : "Personalizáu", diff --git a/l10n/az.js b/l10n/az.js index 8624884d..bb1e996f 100644 --- a/l10n/az.js +++ b/l10n/az.js @@ -19,6 +19,7 @@ OC.L10N.register( "Name" : "Ad", "Update" : "Yenilənmə", "Refresh" : "Yenilə", + "Remove" : "Sil", "Reset" : "Sıfırla", "Size" : "Həcm" }, diff --git a/l10n/az.json b/l10n/az.json index eced9701..e1ff1f80 100644 --- a/l10n/az.json +++ b/l10n/az.json @@ -17,6 +17,7 @@ "Name" : "Ad", "Update" : "Yenilənmə", "Refresh" : "Yenilə", + "Remove" : "Sil", "Reset" : "Sıfırla", "Size" : "Həcm" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/l10n/bg.js b/l10n/bg.js index 996ca056..f84ab3c4 100644 --- a/l10n/bg.js +++ b/l10n/bg.js @@ -126,6 +126,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "Използвайне на страничната лента, за споделяне на тази папка.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Ако създадете публично споделяне на връзка, щракнете върху Опресняване и съответна връзка към приложението Спомени ще бъде показана по-долу.", "Refresh" : "Опресняване", + "Remove" : "Премахване", "Share album" : "Споделяне на албум", "Delete album" : "Изтриване на албум", "Merge with different person" : "Обединяване с различно лице", diff --git a/l10n/bg.json b/l10n/bg.json index d97c266f..faf5df29 100644 --- a/l10n/bg.json +++ b/l10n/bg.json @@ -124,6 +124,7 @@ "Use the sidebar to share this folder." : "Използвайне на страничната лента, за споделяне на тази папка.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Ако създадете публично споделяне на връзка, щракнете върху Опресняване и съответна връзка към приложението Спомени ще бъде показана по-долу.", "Refresh" : "Опресняване", + "Remove" : "Премахване", "Share album" : "Споделяне на албум", "Delete album" : "Изтриване на албум", "Merge with different person" : "Обединяване с различно лице", diff --git a/l10n/bn_BD.js b/l10n/bn_BD.js index c1e8e500..ef124955 100644 --- a/l10n/bn_BD.js +++ b/l10n/bn_BD.js @@ -20,6 +20,7 @@ OC.L10N.register( "Name" : "নাম", "Update" : "পরিবর্ধন", "Refresh" : "নবোদ্যম", + "Remove" : "অপসারণ", "Reset" : "পূণঃনির্ধানণ", "Continue" : "চালিয়ে যাও", "Size" : "আকার" diff --git a/l10n/bn_BD.json b/l10n/bn_BD.json index 8adf7493..31348c2f 100644 --- a/l10n/bn_BD.json +++ b/l10n/bn_BD.json @@ -18,6 +18,7 @@ "Name" : "নাম", "Update" : "পরিবর্ধন", "Refresh" : "নবোদ্যম", + "Remove" : "অপসারণ", "Reset" : "পূণঃনির্ধানণ", "Continue" : "চালিয়ে যাও", "Size" : "আকার" diff --git a/l10n/br.js b/l10n/br.js index 754ebb01..2e65aef0 100644 --- a/l10n/br.js +++ b/l10n/br.js @@ -23,6 +23,7 @@ OC.L10N.register( "Name" : "Anv", "Update" : "Hizivaat", "Refresh" : "Freskaat", + "Remove" : "Lemel", "Continue" : "Kendec'hel", "Original" : "Orin", "Size" : "Ment" diff --git a/l10n/br.json b/l10n/br.json index 5e1b8006..838c7f72 100644 --- a/l10n/br.json +++ b/l10n/br.json @@ -21,6 +21,7 @@ "Name" : "Anv", "Update" : "Hizivaat", "Refresh" : "Freskaat", + "Remove" : "Lemel", "Continue" : "Kendec'hel", "Original" : "Orin", "Size" : "Ment" diff --git a/l10n/ca.js b/l10n/ca.js index 65d42078..4ab2afe6 100644 --- a/l10n/ca.js +++ b/l10n/ca.js @@ -37,6 +37,7 @@ OC.L10N.register( "Name" : "Cognom", "Update" : "Actualitzar", "Refresh" : "Actualitza", + "Remove" : "Elimina", "Share folder" : "Comparteix la carpeta", "Save as" : "Anomena i desa", "Reset" : "Restableix", diff --git a/l10n/ca.json b/l10n/ca.json index 6aa4f2c2..2e50b2b7 100644 --- a/l10n/ca.json +++ b/l10n/ca.json @@ -35,6 +35,7 @@ "Name" : "Cognom", "Update" : "Actualitzar", "Refresh" : "Actualitza", + "Remove" : "Elimina", "Share folder" : "Comparteix la carpeta", "Save as" : "Anomena i desa", "Reset" : "Restableix", diff --git a/l10n/cs.js b/l10n/cs.js index 3a6c5c72..daf6ae79 100644 --- a/l10n/cs.js +++ b/l10n/cs.js @@ -129,6 +129,7 @@ OC.L10N.register( "Use the sidebar to share this folder." : "Pokud chcete tuto složku nasdílet, použijte k tomu postranní panel", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Pokud vytváříte odkaz pro veřejné sdílení, klikněte na opětovné načtení a níže se ukáže příslušný odkaz do Vzpomínek.", "Refresh" : "Znovu načíst", + "Remove" : "Odebrat", "Share album" : "Nasdílet album", "Delete album" : "Smazat album", "Merge with different person" : "Sloučit s jinou osobou", diff --git a/l10n/cs.json b/l10n/cs.json index 63794960..09b9102c 100644 --- a/l10n/cs.json +++ b/l10n/cs.json @@ -127,6 +127,7 @@ "Use the sidebar to share this folder." : "Pokud chcete tuto složku nasdílet, použijte k tomu postranní panel", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Pokud vytváříte odkaz pro veřejné sdílení, klikněte na opětovné načtení a níže se ukáže příslušný odkaz do Vzpomínek.", "Refresh" : "Znovu načíst", + "Remove" : "Odebrat", "Share album" : "Nasdílet album", "Delete album" : "Smazat album", "Merge with different person" : "Sloučit s jinou osobou", diff --git a/l10n/cy_GB.js b/l10n/cy_GB.js index 2e81565b..0d3738ec 100644 --- a/l10n/cy_GB.js +++ b/l10n/cy_GB.js @@ -23,6 +23,7 @@ OC.L10N.register( "Name" : "Enw", "Update" : "Diweddaru", "Refresh" : "Ail-lwytho", + "Remove" : "Gwaredu", "Undo" : "Dadwneud", "Custom" : "Cyfaddas", "Size" : "Maint", diff --git a/l10n/cy_GB.json b/l10n/cy_GB.json index 503832cd..5d109733 100644 --- a/l10n/cy_GB.json +++ b/l10n/cy_GB.json @@ -21,6 +21,7 @@ "Name" : "Enw", "Update" : "Diweddaru", "Refresh" : "Ail-lwytho", + "Remove" : "Gwaredu", "Undo" : "Dadwneud", "Custom" : "Cyfaddas", "Size" : "Maint", diff --git a/l10n/da.js b/l10n/da.js index f3a40e01..d4136866 100644 --- a/l10n/da.js +++ b/l10n/da.js @@ -51,6 +51,7 @@ OC.L10N.register( "Name" : "Navn", "Update" : "Opdater", "Refresh" : "Opdater", + "Remove" : "Fjern", "Share folder" : "Del mappe", "Reset" : "Nulstil", "Continue" : "Fortsæt", diff --git a/l10n/da.json b/l10n/da.json index b63c3b91..5919cd1b 100644 --- a/l10n/da.json +++ b/l10n/da.json @@ -49,6 +49,7 @@ "Name" : "Navn", "Update" : "Opdater", "Refresh" : "Opdater", + "Remove" : "Fjern", "Share folder" : "Del mappe", "Reset" : "Nulstil", "Continue" : "Fortsæt", diff --git a/l10n/de_DE.js b/l10n/de_DE.js index 32d6ddca..ada31b8c 100644 --- a/l10n/de_DE.js +++ b/l10n/de_DE.js @@ -54,6 +54,7 @@ OC.L10N.register( "Folders Path" : "Ordnerpfad", "Show hidden folders" : "Zeige versteckte Ordner", "Square grid mode" : "Quadratischer Gittermodus", + "Choose Timeline Paths" : "Pfade der Zeitleiste auswählen", "Choose the root for the folders view" : "Wählen Sie das Stammverzeichnis für die Ordneransicht", "Your Timeline" : "Ihre Zeitleiste", "Failed to load some photos" : "Laden einiger Fotos fehlgeschlagen", @@ -129,6 +130,9 @@ OC.L10N.register( "Use the sidebar to share this folder." : "Verwenden Sie die Seitenleiste, um diesen Ordner zu teilen.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Wenn Sie eine öffentliche Linkfreigabe erstellen, klicken Sie auf Aktualisieren und ein entsprechender Link zu Memories wird unten angezeigt.", "Refresh" : "Aktualisieren", + "Remove" : "Entfernen", + "Add Path" : "Pfad hinzufügen", + "Add a root to your timeline" : "Einen Start Ihrer Zeitleiste hinzufügen", "Share album" : "Album teilen", "Delete album" : "Album löschen", "Merge with different person" : "Mit einer anderen Person zusammenführen", diff --git a/l10n/de_DE.json b/l10n/de_DE.json index e9dfac14..b3470d80 100644 --- a/l10n/de_DE.json +++ b/l10n/de_DE.json @@ -52,6 +52,7 @@ "Folders Path" : "Ordnerpfad", "Show hidden folders" : "Zeige versteckte Ordner", "Square grid mode" : "Quadratischer Gittermodus", + "Choose Timeline Paths" : "Pfade der Zeitleiste auswählen", "Choose the root for the folders view" : "Wählen Sie das Stammverzeichnis für die Ordneransicht", "Your Timeline" : "Ihre Zeitleiste", "Failed to load some photos" : "Laden einiger Fotos fehlgeschlagen", @@ -127,6 +128,9 @@ "Use the sidebar to share this folder." : "Verwenden Sie die Seitenleiste, um diesen Ordner zu teilen.", "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Wenn Sie eine öffentliche Linkfreigabe erstellen, klicken Sie auf Aktualisieren und ein entsprechender Link zu Memories wird unten angezeigt.", "Refresh" : "Aktualisieren", + "Remove" : "Entfernen", + "Add Path" : "Pfad hinzufügen", + "Add a root to your timeline" : "Einen Start Ihrer Zeitleiste hinzufügen", "Share album" : "Album teilen", "Delete album" : "Album löschen", "Merge with different person" : "Mit einer anderen Person zusammenführen", diff --git a/l10n/es.js b/l10n/es.js index 97c2f326..5a61d5e9 100644 --- a/l10n/es.js +++ b/l10n/es.js @@ -26,6 +26,8 @@ OC.L10N.register( "Choose the root of your timeline" : "Seleccione la raíz de su línea de tiempo", "The selected folder does not seem to be valid. Try again." : "La carpeta seleccionada no parece ser válida. Intente de nuevo.", "Found {total} photos in {path}" : "Se encontraron {total} fotos en {path}", + "Failed to get Exif data. Metadata may be lost!" : "Fallo al obtener los datos Exif. ¡Podrían haberse perdido los metadatos!", + "No Exif data found! Continue?" : "¡No se encontraron datos Exif!, ¿Continuar?", "Image saved successfully" : "La imagen se guardó exitósamente", "Error saving image" : "Error guardando imágen", "Unsaved changes" : "Cambios sin guardar", @@ -52,6 +54,7 @@ OC.L10N.register( "Folders Path" : "Ruta a las carpetas", "Show hidden folders" : "Mostrar carpetas ocultas", "Square grid mode" : "Modo de rejilla cuadrada", + "Choose Timeline Paths" : "Escoga las rutas a la línea de tiempo", "Choose the root for the folders view" : "Seleccione la raíz de la vista de carpetas", "Your Timeline" : "Su línea de tiempo", "Failed to load some photos" : "Fallo al cargar algunas fotos", @@ -128,6 +131,8 @@ OC.L10N.register( "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si crea un enlace público de compartición, haga click en refrescar y se mostrará abajo el enlace correspondiente a Memories.", "Refresh" : "Actualizar", "Remove" : "Quitar", + "Add Path" : "Añadir ruta", + "Add a root to your timeline" : "Añadir una raíz a su línea de tiempo", "Share album" : "Compartir álbum", "Delete album" : "Eliminar álbum", "Merge with different person" : "Unir con una persona diferente", @@ -219,6 +224,7 @@ OC.L10N.register( "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Tenga en cuenta que el área a recortar es menor al redimensionamiento aplicado lo que puede causar pérdida de calidad", "Actual size (100%)" : "Tamaño actual (100%)", "Fit size" : "Ajustar tamaño", + "Transcoding failed." : "Falló el transcoding", "Auto" : "Auto", "Shared Folder" : "Carpeta compartida", "Failed to create {albumName}." : "Fallo al crear {albumName}", diff --git a/l10n/es.json b/l10n/es.json index 772b99ac..34202fa7 100644 --- a/l10n/es.json +++ b/l10n/es.json @@ -24,6 +24,8 @@ "Choose the root of your timeline" : "Seleccione la raíz de su línea de tiempo", "The selected folder does not seem to be valid. Try again." : "La carpeta seleccionada no parece ser válida. Intente de nuevo.", "Found {total} photos in {path}" : "Se encontraron {total} fotos en {path}", + "Failed to get Exif data. Metadata may be lost!" : "Fallo al obtener los datos Exif. ¡Podrían haberse perdido los metadatos!", + "No Exif data found! Continue?" : "¡No se encontraron datos Exif!, ¿Continuar?", "Image saved successfully" : "La imagen se guardó exitósamente", "Error saving image" : "Error guardando imágen", "Unsaved changes" : "Cambios sin guardar", @@ -50,6 +52,7 @@ "Folders Path" : "Ruta a las carpetas", "Show hidden folders" : "Mostrar carpetas ocultas", "Square grid mode" : "Modo de rejilla cuadrada", + "Choose Timeline Paths" : "Escoga las rutas a la línea de tiempo", "Choose the root for the folders view" : "Seleccione la raíz de la vista de carpetas", "Your Timeline" : "Su línea de tiempo", "Failed to load some photos" : "Fallo al cargar algunas fotos", @@ -126,6 +129,8 @@ "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Si crea un enlace público de compartición, haga click en refrescar y se mostrará abajo el enlace correspondiente a Memories.", "Refresh" : "Actualizar", "Remove" : "Quitar", + "Add Path" : "Añadir ruta", + "Add a root to your timeline" : "Añadir una raíz a su línea de tiempo", "Share album" : "Compartir álbum", "Delete album" : "Eliminar álbum", "Merge with different person" : "Unir con una persona diferente", @@ -217,6 +222,7 @@ "Note that the selected crop area is lower than the applied resize which might cause quality decrease" : "Tenga en cuenta que el área a recortar es menor al redimensionamiento aplicado lo que puede causar pérdida de calidad", "Actual size (100%)" : "Tamaño actual (100%)", "Fit size" : "Ajustar tamaño", + "Transcoding failed." : "Falló el transcoding", "Auto" : "Auto", "Shared Folder" : "Carpeta compartida", "Failed to create {albumName}." : "Fallo al crear {albumName}", diff --git a/l10n/tr.js b/l10n/tr.js index dc0cdd5b..44772e8a 100644 --- a/l10n/tr.js +++ b/l10n/tr.js @@ -54,6 +54,7 @@ OC.L10N.register( "Folders Path" : "Klasörlerin yolu", "Show hidden folders" : "Gizli klasörleri görüntüle", "Square grid mode" : "Kare tablo kipi", + "Choose Timeline Paths" : "Zaman tüneli yollarını seçin", "Choose the root for the folders view" : "Klasörler görünümünün kök klasörünü seçin", "Your Timeline" : "Zaman tüneliniz", "Failed to load some photos" : "Bazı fotoğraflar yüklenemedi", @@ -130,6 +131,8 @@ OC.L10N.register( "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Herkese açık bir bağlantı paylaşımı oluşturduktan sonra yenile üzerine tıklayın. Anılar için ilgili bağlantı aşağıda görüntülenir.", "Refresh" : "Yenlle", "Remove" : "Kaldır", + "Add Path" : "Yol ekle", + "Add a root to your timeline" : "Zaman tünelinize bir kök klasör ekleyin", "Share album" : "Albümü paylaş", "Delete album" : "Albümü sil", "Merge with different person" : "Başka bir kişi ile birleştir", diff --git a/l10n/tr.json b/l10n/tr.json index fe7db735..55d1540e 100644 --- a/l10n/tr.json +++ b/l10n/tr.json @@ -52,6 +52,7 @@ "Folders Path" : "Klasörlerin yolu", "Show hidden folders" : "Gizli klasörleri görüntüle", "Square grid mode" : "Kare tablo kipi", + "Choose Timeline Paths" : "Zaman tüneli yollarını seçin", "Choose the root for the folders view" : "Klasörler görünümünün kök klasörünü seçin", "Your Timeline" : "Zaman tüneliniz", "Failed to load some photos" : "Bazı fotoğraflar yüklenemedi", @@ -128,6 +129,8 @@ "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Herkese açık bir bağlantı paylaşımı oluşturduktan sonra yenile üzerine tıklayın. Anılar için ilgili bağlantı aşağıda görüntülenir.", "Refresh" : "Yenlle", "Remove" : "Kaldır", + "Add Path" : "Yol ekle", + "Add a root to your timeline" : "Zaman tünelinize bir kök klasör ekleyin", "Share album" : "Albümü paylaş", "Delete album" : "Albümü sil", "Merge with different person" : "Başka bir kişi ile birleştir", diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js index b850f4ff..ab08e3fd 100644 --- a/l10n/zh_HK.js +++ b/l10n/zh_HK.js @@ -54,6 +54,7 @@ OC.L10N.register( "Folders Path" : "資料夾路徑", "Show hidden folders" : "顯示隱藏資料夾", "Square grid mode" : "方形網格模式", + "Choose Timeline Paths" : "選擇時間線途徑", "Choose the root for the folders view" : "選擇資料夾檢視的根", "Your Timeline" : "您的時間線", "Failed to load some photos" : "未能加載一些照片", @@ -130,6 +131,8 @@ OC.L10N.register( "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "刷新", "Remove" : "移除", + "Add Path" : "添加途徑", + "Add a root to your timeline" : "添加您時間線的根", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json index 56cc93cd..35af7619 100644 --- a/l10n/zh_HK.json +++ b/l10n/zh_HK.json @@ -52,6 +52,7 @@ "Folders Path" : "資料夾路徑", "Show hidden folders" : "顯示隱藏資料夾", "Square grid mode" : "方形網格模式", + "Choose Timeline Paths" : "選擇時間線途徑", "Choose the root for the folders view" : "選擇資料夾檢視的根", "Your Timeline" : "您的時間線", "Failed to load some photos" : "未能加載一些照片", @@ -128,6 +129,8 @@ "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "刷新", "Remove" : "移除", + "Add Path" : "添加途徑", + "Add a root to your timeline" : "添加您時間線的根", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js index 562e0608..f64f29a3 100644 --- a/l10n/zh_TW.js +++ b/l10n/zh_TW.js @@ -54,6 +54,7 @@ OC.L10N.register( "Folders Path" : "資料夾路徑", "Show hidden folders" : "顯示隱藏的資料夾", "Square grid mode" : "方形網格模式", + "Choose Timeline Paths" : "選擇時間軸路徑", "Choose the root for the folders view" : "選擇資料夾檢視的根", "Your Timeline" : "您的時間軸", "Failed to load some photos" : "載入部份照片時失敗", @@ -130,6 +131,8 @@ OC.L10N.register( "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "重新整理", "Remove" : "移除", + "Add Path" : "新增路徑", + "Add a root to your timeline" : "新增您時間軸的根", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json index 2ae7c667..08add1fa 100644 --- a/l10n/zh_TW.json +++ b/l10n/zh_TW.json @@ -52,6 +52,7 @@ "Folders Path" : "資料夾路徑", "Show hidden folders" : "顯示隱藏的資料夾", "Square grid mode" : "方形網格模式", + "Choose Timeline Paths" : "選擇時間軸路徑", "Choose the root for the folders view" : "選擇資料夾檢視的根", "Your Timeline" : "您的時間軸", "Failed to load some photos" : "載入部份照片時失敗", @@ -128,6 +129,8 @@ "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "若您建立公開連結分享,請點擊「重新整理」,下方將會顯示對應的 Memories 連結。", "Refresh" : "重新整理", "Remove" : "移除", + "Add Path" : "新增路徑", + "Add a root to your timeline" : "新增您時間軸的根", "Share album" : "分享相簿", "Delete album" : "刪除相簿", "Merge with different person" : "與其他人合併", From e210c323beff144b32211aec59eee7415563843e Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Sat, 19 Nov 2022 03:24:13 +0000 Subject: [PATCH 163/163] [tx-robot] updated from transifex Signed-off-by: Nextcloud bot --- l10n/cs.js | 3 +++ l10n/cs.json | 3 +++ l10n/ru.js | 5 +++++ l10n/ru.json | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/l10n/cs.js b/l10n/cs.js index daf6ae79..75e3c492 100644 --- a/l10n/cs.js +++ b/l10n/cs.js @@ -54,6 +54,7 @@ OC.L10N.register( "Folders Path" : "Popis umístění složek", "Show hidden folders" : "Zobrazit skryté složky", "Square grid mode" : "Režim se čtvercovou mřížkou", + "Choose Timeline Paths" : "Zvolte trasy časovou osou", "Choose the root for the folders view" : "Zvolte kořen pro zobrazení složek", "Your Timeline" : "Vaše časová osa", "Failed to load some photos" : "Některé fotky se nepodařilo načíst", @@ -130,6 +131,8 @@ OC.L10N.register( "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Pokud vytváříte odkaz pro veřejné sdílení, klikněte na opětovné načtení a níže se ukáže příslušný odkaz do Vzpomínek.", "Refresh" : "Znovu načíst", "Remove" : "Odebrat", + "Add Path" : "Přidat trasu", + "Add a root to your timeline" : "Přidat do časové osy kořen", "Share album" : "Nasdílet album", "Delete album" : "Smazat album", "Merge with different person" : "Sloučit s jinou osobou", diff --git a/l10n/cs.json b/l10n/cs.json index 09b9102c..d82d6c1c 100644 --- a/l10n/cs.json +++ b/l10n/cs.json @@ -52,6 +52,7 @@ "Folders Path" : "Popis umístění složek", "Show hidden folders" : "Zobrazit skryté složky", "Square grid mode" : "Režim se čtvercovou mřížkou", + "Choose Timeline Paths" : "Zvolte trasy časovou osou", "Choose the root for the folders view" : "Zvolte kořen pro zobrazení složek", "Your Timeline" : "Vaše časová osa", "Failed to load some photos" : "Některé fotky se nepodařilo načíst", @@ -128,6 +129,8 @@ "If you create a public link share, click on refresh and a corresponding link to Memories will be shown below." : "Pokud vytváříte odkaz pro veřejné sdílení, klikněte na opětovné načtení a níže se ukáže příslušný odkaz do Vzpomínek.", "Refresh" : "Znovu načíst", "Remove" : "Odebrat", + "Add Path" : "Přidat trasu", + "Add a root to your timeline" : "Přidat do časové osy kořen", "Share album" : "Nasdílet album", "Delete album" : "Smazat album", "Merge with different person" : "Sloučit s jinou osobou", diff --git a/l10n/ru.js b/l10n/ru.js index d8d2fb38..da55dfcc 100644 --- a/l10n/ru.js +++ b/l10n/ru.js @@ -34,8 +34,13 @@ OC.L10N.register( "Sidebar" : "Боковая панель", "Copy public link" : "Скопировать общедоступную ссылку", "Public link" : "Общедоступная ссылка", + "Name of the album" : "Название альбома", + "Location of the album" : "Расположение альбома", + "Go back to the previous view." : "Вернуться к предыдущему режиму просмотра.", "Back" : "Назад", + "Add collaborators" : "Добавить соавторов", "Save" : "Сохранить", + "Create album" : "Создать альбом", "Year" : "Год", "Month" : "Месяц", "Day" : "День", diff --git a/l10n/ru.json b/l10n/ru.json index 22c40c28..c9be4563 100644 --- a/l10n/ru.json +++ b/l10n/ru.json @@ -32,8 +32,13 @@ "Sidebar" : "Боковая панель", "Copy public link" : "Скопировать общедоступную ссылку", "Public link" : "Общедоступная ссылка", + "Name of the album" : "Название альбома", + "Location of the album" : "Расположение альбома", + "Go back to the previous view." : "Вернуться к предыдущему режиму просмотра.", "Back" : "Назад", + "Add collaborators" : "Добавить соавторов", "Save" : "Сохранить", + "Create album" : "Создать альбом", "Year" : "Год", "Month" : "Месяц", "Day" : "День",