aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_versions
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_versions')
-rw-r--r--apps/files_versions/.l10nignore2
-rw-r--r--apps/files_versions/appinfo/info.xml14
-rw-r--r--apps/files_versions/appinfo/routes.php42
-rw-r--r--apps/files_versions/composer/autoload.php17
-rw-r--r--apps/files_versions/composer/composer/ClassLoader.php137
-rw-r--r--apps/files_versions/composer/composer/InstalledVersions.php31
-rw-r--r--apps/files_versions/composer/composer/autoload_classmap.php17
-rw-r--r--apps/files_versions/composer/composer/autoload_static.php17
-rw-r--r--apps/files_versions/composer/composer/installed.php6
-rw-r--r--apps/files_versions/img/app-dark.svg1
-rw-r--r--apps/files_versions/img/app.svg2
-rw-r--r--apps/files_versions/l10n/af.js9
-rw-r--r--apps/files_versions/l10n/af.json7
-rw-r--r--apps/files_versions/l10n/ar.js28
-rw-r--r--apps/files_versions/l10n/ar.json28
-rw-r--r--apps/files_versions/l10n/ast.js25
-rw-r--r--apps/files_versions/l10n/ast.json25
-rw-r--r--apps/files_versions/l10n/az.js9
-rw-r--r--apps/files_versions/l10n/az.json7
-rw-r--r--apps/files_versions/l10n/be.js17
-rw-r--r--apps/files_versions/l10n/be.json15
-rw-r--r--apps/files_versions/l10n/bg.js20
-rw-r--r--apps/files_versions/l10n/bg.json20
-rw-r--r--apps/files_versions/l10n/bn_BD.js9
-rw-r--r--apps/files_versions/l10n/bn_BD.json7
-rw-r--r--apps/files_versions/l10n/br.js12
-rw-r--r--apps/files_versions/l10n/br.json10
-rw-r--r--apps/files_versions/l10n/bs.js9
-rw-r--r--apps/files_versions/l10n/bs.json7
-rw-r--r--apps/files_versions/l10n/ca.js26
-rw-r--r--apps/files_versions/l10n/ca.json26
-rw-r--r--apps/files_versions/l10n/cs.js29
-rw-r--r--apps/files_versions/l10n/cs.json29
-rw-r--r--apps/files_versions/l10n/cy_GB.js6
-rw-r--r--apps/files_versions/l10n/cy_GB.json4
-rw-r--r--apps/files_versions/l10n/da.js27
-rw-r--r--apps/files_versions/l10n/da.json27
-rw-r--r--apps/files_versions/l10n/de.js27
-rw-r--r--apps/files_versions/l10n/de.json27
-rw-r--r--apps/files_versions/l10n/de_DE.js27
-rw-r--r--apps/files_versions/l10n/de_DE.json27
-rw-r--r--apps/files_versions/l10n/el.js22
-rw-r--r--apps/files_versions/l10n/el.json22
-rw-r--r--apps/files_versions/l10n/en_GB.js27
-rw-r--r--apps/files_versions/l10n/en_GB.json27
-rw-r--r--apps/files_versions/l10n/eo.js12
-rw-r--r--apps/files_versions/l10n/eo.json10
-rw-r--r--apps/files_versions/l10n/es.js29
-rw-r--r--apps/files_versions/l10n/es.json29
-rw-r--r--apps/files_versions/l10n/es_419.js9
-rw-r--r--apps/files_versions/l10n/es_419.json7
-rw-r--r--apps/files_versions/l10n/es_AR.js10
-rw-r--r--apps/files_versions/l10n/es_AR.json8
-rw-r--r--apps/files_versions/l10n/es_CL.js9
-rw-r--r--apps/files_versions/l10n/es_CL.json7
-rw-r--r--apps/files_versions/l10n/es_CO.js9
-rw-r--r--apps/files_versions/l10n/es_CO.json7
-rw-r--r--apps/files_versions/l10n/es_CR.js9
-rw-r--r--apps/files_versions/l10n/es_CR.json7
-rw-r--r--apps/files_versions/l10n/es_DO.js9
-rw-r--r--apps/files_versions/l10n/es_DO.json7
-rw-r--r--apps/files_versions/l10n/es_EC.js21
-rw-r--r--apps/files_versions/l10n/es_EC.json21
-rw-r--r--apps/files_versions/l10n/es_GT.js9
-rw-r--r--apps/files_versions/l10n/es_GT.json7
-rw-r--r--apps/files_versions/l10n/es_HN.js9
-rw-r--r--apps/files_versions/l10n/es_HN.json7
-rw-r--r--apps/files_versions/l10n/es_MX.js26
-rw-r--r--apps/files_versions/l10n/es_MX.json26
-rw-r--r--apps/files_versions/l10n/es_NI.js9
-rw-r--r--apps/files_versions/l10n/es_NI.json7
-rw-r--r--apps/files_versions/l10n/es_PA.js9
-rw-r--r--apps/files_versions/l10n/es_PA.json7
-rw-r--r--apps/files_versions/l10n/es_PE.js9
-rw-r--r--apps/files_versions/l10n/es_PE.json7
-rw-r--r--apps/files_versions/l10n/es_PR.js9
-rw-r--r--apps/files_versions/l10n/es_PR.json7
-rw-r--r--apps/files_versions/l10n/es_PY.js9
-rw-r--r--apps/files_versions/l10n/es_PY.json7
-rw-r--r--apps/files_versions/l10n/es_SV.js9
-rw-r--r--apps/files_versions/l10n/es_SV.json7
-rw-r--r--apps/files_versions/l10n/es_UY.js9
-rw-r--r--apps/files_versions/l10n/es_UY.json7
-rw-r--r--apps/files_versions/l10n/et_EE.js27
-rw-r--r--apps/files_versions/l10n/et_EE.json27
-rw-r--r--apps/files_versions/l10n/eu.js28
-rw-r--r--apps/files_versions/l10n/eu.json28
-rw-r--r--apps/files_versions/l10n/fa.js22
-rw-r--r--apps/files_versions/l10n/fa.json22
-rw-r--r--apps/files_versions/l10n/fi.js22
-rw-r--r--apps/files_versions/l10n/fi.json22
-rw-r--r--apps/files_versions/l10n/fr.js29
-rw-r--r--apps/files_versions/l10n/fr.json29
-rw-r--r--apps/files_versions/l10n/ga.js29
-rw-r--r--apps/files_versions/l10n/ga.json27
-rw-r--r--apps/files_versions/l10n/gl.js26
-rw-r--r--apps/files_versions/l10n/gl.json26
-rw-r--r--apps/files_versions/l10n/he.js12
-rw-r--r--apps/files_versions/l10n/he.json10
-rw-r--r--apps/files_versions/l10n/hr.js12
-rw-r--r--apps/files_versions/l10n/hr.json10
-rw-r--r--apps/files_versions/l10n/hu.js26
-rw-r--r--apps/files_versions/l10n/hu.json26
-rw-r--r--apps/files_versions/l10n/hy.js8
-rw-r--r--apps/files_versions/l10n/hy.json6
-rw-r--r--apps/files_versions/l10n/ia.js10
-rw-r--r--apps/files_versions/l10n/ia.json8
-rw-r--r--apps/files_versions/l10n/id.js12
-rw-r--r--apps/files_versions/l10n/id.json10
-rw-r--r--apps/files_versions/l10n/is.js24
-rw-r--r--apps/files_versions/l10n/is.json24
-rw-r--r--apps/files_versions/l10n/it.js29
-rw-r--r--apps/files_versions/l10n/it.json29
-rw-r--r--apps/files_versions/l10n/ja.js27
-rw-r--r--apps/files_versions/l10n/ja.json27
-rw-r--r--apps/files_versions/l10n/ka.js25
-rw-r--r--apps/files_versions/l10n/ka.json23
-rw-r--r--apps/files_versions/l10n/ka_GE.js9
-rw-r--r--apps/files_versions/l10n/ka_GE.json7
-rw-r--r--apps/files_versions/l10n/km.js9
-rw-r--r--apps/files_versions/l10n/km.json7
-rw-r--r--apps/files_versions/l10n/kn.js9
-rw-r--r--apps/files_versions/l10n/kn.json7
-rw-r--r--apps/files_versions/l10n/ko.js23
-rw-r--r--apps/files_versions/l10n/ko.json23
-rw-r--r--apps/files_versions/l10n/lb.js10
-rw-r--r--apps/files_versions/l10n/lb.json8
-rw-r--r--apps/files_versions/l10n/lt_LT.js20
-rw-r--r--apps/files_versions/l10n/lt_LT.json20
-rw-r--r--apps/files_versions/l10n/lv.js11
-rw-r--r--apps/files_versions/l10n/lv.json9
-rw-r--r--apps/files_versions/l10n/mk.js27
-rw-r--r--apps/files_versions/l10n/mk.json27
-rw-r--r--apps/files_versions/l10n/ms_MY.js9
-rw-r--r--apps/files_versions/l10n/ms_MY.json7
-rw-r--r--apps/files_versions/l10n/nb.js26
-rw-r--r--apps/files_versions/l10n/nb.json26
-rw-r--r--apps/files_versions/l10n/nl.js27
-rw-r--r--apps/files_versions/l10n/nl.json27
-rw-r--r--apps/files_versions/l10n/nn_NO.js9
-rw-r--r--apps/files_versions/l10n/nn_NO.json7
-rw-r--r--apps/files_versions/l10n/oc.js9
-rw-r--r--apps/files_versions/l10n/oc.json7
-rw-r--r--apps/files_versions/l10n/pl.js27
-rw-r--r--apps/files_versions/l10n/pl.json27
-rw-r--r--apps/files_versions/l10n/pt_BR.js29
-rw-r--r--apps/files_versions/l10n/pt_BR.json29
-rw-r--r--apps/files_versions/l10n/pt_PT.js10
-rw-r--r--apps/files_versions/l10n/pt_PT.json8
-rw-r--r--apps/files_versions/l10n/ro.js12
-rw-r--r--apps/files_versions/l10n/ro.json10
-rw-r--r--apps/files_versions/l10n/ru.js27
-rw-r--r--apps/files_versions/l10n/ru.json27
-rw-r--r--apps/files_versions/l10n/sc.js12
-rw-r--r--apps/files_versions/l10n/sc.json10
-rw-r--r--apps/files_versions/l10n/sk.js27
-rw-r--r--apps/files_versions/l10n/sk.json27
-rw-r--r--apps/files_versions/l10n/sl.js21
-rw-r--r--apps/files_versions/l10n/sl.json21
-rw-r--r--apps/files_versions/l10n/sq.js10
-rw-r--r--apps/files_versions/l10n/sq.json8
-rw-r--r--apps/files_versions/l10n/sr.js27
-rw-r--r--apps/files_versions/l10n/sr.json27
-rw-r--r--apps/files_versions/l10n/sr@latin.js11
-rw-r--r--apps/files_versions/l10n/sr@latin.json9
-rw-r--r--apps/files_versions/l10n/sv.js27
-rw-r--r--apps/files_versions/l10n/sv.json27
-rw-r--r--apps/files_versions/l10n/sw.js29
-rw-r--r--apps/files_versions/l10n/sw.json27
-rw-r--r--apps/files_versions/l10n/th.js10
-rw-r--r--apps/files_versions/l10n/th.json8
-rw-r--r--apps/files_versions/l10n/tr.js27
-rw-r--r--apps/files_versions/l10n/tr.json27
-rw-r--r--apps/files_versions/l10n/ug.js27
-rw-r--r--apps/files_versions/l10n/ug.json27
-rw-r--r--apps/files_versions/l10n/uk.js27
-rw-r--r--apps/files_versions/l10n/uk.json27
-rw-r--r--apps/files_versions/l10n/ur_PK.js6
-rw-r--r--apps/files_versions/l10n/ur_PK.json4
-rw-r--r--apps/files_versions/l10n/vi.js22
-rw-r--r--apps/files_versions/l10n/vi.json22
-rw-r--r--apps/files_versions/l10n/zh_CN.js27
-rw-r--r--apps/files_versions/l10n/zh_CN.json27
-rw-r--r--apps/files_versions/l10n/zh_HK.js27
-rw-r--r--apps/files_versions/l10n/zh_HK.json27
-rw-r--r--apps/files_versions/l10n/zh_TW.js29
-rw-r--r--apps/files_versions/l10n/zh_TW.json29
-rw-r--r--apps/files_versions/lib/AppInfo/Application.php81
-rw-r--r--apps/files_versions/lib/BackgroundJob/ExpireVersions.php64
-rw-r--r--apps/files_versions/lib/Capabilities.php40
-rw-r--r--apps/files_versions/lib/Command/CleanUp.php111
-rw-r--r--apps/files_versions/lib/Command/Expire.php49
-rw-r--r--apps/files_versions/lib/Command/ExpireVersions.php102
-rw-r--r--apps/files_versions/lib/Controller/PreviewController.php93
-rw-r--r--apps/files_versions/lib/Db/VersionEntity.php74
-rw-r--r--apps/files_versions/lib/Db/VersionsMapper.php104
-rw-r--r--apps/files_versions/lib/Events/CreateVersionEvent.php32
-rw-r--r--apps/files_versions/lib/Events/VersionCreatedEvent.php39
-rw-r--r--apps/files_versions/lib/Events/VersionRestoredEvent.php33
-rw-r--r--apps/files_versions/lib/Expiration.php61
-rw-r--r--apps/files_versions/lib/Hooks.php142
-rw-r--r--apps/files_versions/lib/Listener/FileEventsListener.php472
-rw-r--r--apps/files_versions/lib/Listener/LegacyRollbackListener.php35
-rw-r--r--apps/files_versions/lib/Listener/LoadAdditionalListener.php24
-rw-r--r--apps/files_versions/lib/Listener/LoadSidebarListener.php24
-rw-r--r--apps/files_versions/lib/Listener/VersionAuthorListener.php56
-rw-r--r--apps/files_versions/lib/Listener/VersionStorageMoveListener.php140
-rw-r--r--apps/files_versions/lib/Migration/Version1020Date20221114144058.php67
-rw-r--r--apps/files_versions/lib/Sabre/Plugin.php65
-rw-r--r--apps/files_versions/lib/Sabre/RestoreFolder.php22
-rw-r--r--apps/files_versions/lib/Sabre/RootCollection.php48
-rw-r--r--apps/files_versions/lib/Sabre/VersionCollection.php40
-rw-r--r--apps/files_versions/lib/Sabre/VersionFile.php75
-rw-r--r--apps/files_versions/lib/Sabre/VersionHome.php46
-rw-r--r--apps/files_versions/lib/Sabre/VersionRoot.php46
-rw-r--r--apps/files_versions/lib/Storage.php367
-rw-r--r--apps/files_versions/lib/Versions/BackendNotFoundException.php22
-rw-r--r--apps/files_versions/lib/Versions/IDeletableVersionBackend.php21
-rw-r--r--apps/files_versions/lib/Versions/IMetadataVersion.php31
-rw-r--r--apps/files_versions/lib/Versions/IMetadataVersionBackend.php29
-rw-r--r--apps/files_versions/lib/Versions/INameableVersion.php23
-rw-r--r--apps/files_versions/lib/Versions/INameableVersionBackend.php22
-rw-r--r--apps/files_versions/lib/Versions/INeedSyncVersionBackend.php25
-rw-r--r--apps/files_versions/lib/Versions/IVersion.php25
-rw-r--r--apps/files_versions/lib/Versions/IVersionBackend.php32
-rw-r--r--apps/files_versions/lib/Versions/IVersionManager.php29
-rw-r--r--apps/files_versions/lib/Versions/IVersionsImporterBackend.php33
-rw-r--r--apps/files_versions/lib/Versions/LegacyVersionsBackend.php359
-rw-r--r--apps/files_versions/lib/Versions/Version.php88
-rw-r--r--apps/files_versions/lib/Versions/VersionManager.php143
-rw-r--r--apps/files_versions/openapi.json164
-rw-r--r--apps/files_versions/openapi.json.license2
-rw-r--r--apps/files_versions/src/components/Version.vue393
-rw-r--r--apps/files_versions/src/components/VersionLabelDialog.vue123
-rw-r--r--apps/files_versions/src/components/VirtualScrolling.vue346
-rw-r--r--apps/files_versions/src/css/versions.css47
-rw-r--r--apps/files_versions/src/files_versions.js29
-rw-r--r--apps/files_versions/src/files_versions_tab.js62
-rw-r--r--apps/files_versions/src/filesplugin.js46
-rw-r--r--apps/files_versions/src/templates/item.handlebars22
-rw-r--r--apps/files_versions/src/templates/template.handlebars10
-rw-r--r--apps/files_versions/src/utils/davClient.js29
-rw-r--r--apps/files_versions/src/utils/davRequest.js20
-rw-r--r--apps/files_versions/src/utils/logger.js11
-rw-r--r--apps/files_versions/src/utils/versions.ts133
-rw-r--r--apps/files_versions/src/versioncollection.js97
-rw-r--r--apps/files_versions/src/versionmodel.js86
-rw-r--r--apps/files_versions/src/versionstabview.js231
-rw-r--r--apps/files_versions/src/views/VersionTab.vue307
-rw-r--r--apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php54
-rw-r--r--apps/files_versions/tests/Command/CleanupTest.php115
-rw-r--r--apps/files_versions/tests/Command/ExpireTest.php27
-rw-r--r--apps/files_versions/tests/Controller/PreviewControllerTest.php78
-rw-r--r--apps/files_versions/tests/ExpirationTest.php53
-rw-r--r--apps/files_versions/tests/StorageTest.php35
-rw-r--r--apps/files_versions/tests/VersioningTest.php536
-rw-r--r--apps/files_versions/tests/Versions/VersionManagerTest.php112
-rw-r--r--apps/files_versions/tests/js/versioncollectionSpec.js48
-rw-r--r--apps/files_versions/tests/js/versionmodelSpec.js124
-rw-r--r--apps/files_versions/tests/js/versionstabviewSpec.js193
260 files changed, 6521 insertions, 3820 deletions
diff --git a/apps/files_versions/.l10nignore b/apps/files_versions/.l10nignore
index b39bd48a11d..80d07dc83e7 100644
--- a/apps/files_versions/.l10nignore
+++ b/apps/files_versions/.l10nignore
@@ -1,3 +1,5 @@
+# SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+# SPDX-License-Identifier: AGPL-3.0-or-later
# compiled vue templates
js/
src/templates.js
diff --git a/apps/files_versions/appinfo/info.xml b/apps/files_versions/appinfo/info.xml
index 3032d8cc934..7bd11e40cd8 100644
--- a/apps/files_versions/appinfo/info.xml
+++ b/apps/files_versions/appinfo/info.xml
@@ -1,19 +1,23 @@
<?xml version="1.0"?>
+<!--
+ - SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-FileCopyrightText: 2012-2016 owncloud, Inc.
+ - SPDX-License-Identifier: AGPL-3.0-only
+-->
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
<id>files_versions</id>
<name>Versions</name>
<summary>This application automatically maintains older versions of files that are changed.</summary>
<description>
- This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.
- In addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation.
+ This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.
+ In addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation.
</description>
- <version>1.18.0</version>
+ <version>1.25.0</version>
<licence>agpl</licence>
<author>Frank Karlitschek</author>
<author>Bjoern Schiessle</author>
<namespace>Files_Versions</namespace>
- <default_enable/>
<types>
<filesystem/>
<dav/>
@@ -24,7 +28,7 @@
<category>files</category>
<bugs>https://github.com/nextcloud/server/issues</bugs>
<dependencies>
- <nextcloud min-version="25" max-version="25"/>
+ <nextcloud min-version="32" max-version="32"/>
</dependencies>
<background-jobs>
diff --git a/apps/files_versions/appinfo/routes.php b/apps/files_versions/appinfo/routes.php
index b9706554c40..22ded5e8723 100644
--- a/apps/files_versions/appinfo/routes.php
+++ b/apps/files_versions/appinfo/routes.php
@@ -1,35 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tom Needham <tom@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\AppInfo;
-/** @var Application $application */
-$application = \OC::$server->query(Application::class);
-$application->registerRoutes($this, [
+return [
'routes' => [
[
'name' => 'Preview#getPreview',
@@ -37,12 +15,4 @@ $application->registerRoutes($this, [
'verb' => 'GET',
],
],
-]);
-
-/** @var $this \OCP\Route\IRouter */
-$this->create('files_versions_download', 'apps/files_versions/download.php')
- ->actionInclude('files_versions/download.php');
-$this->create('files_versions_ajax_getVersions', 'apps/files_versions/ajax/getVersions.php')
- ->actionInclude('files_versions/ajax/getVersions.php');
-$this->create('files_versions_ajax_rollbackVersion', 'apps/files_versions/ajax/rollbackVersion.php')
- ->actionInclude('files_versions/ajax/rollbackVersion.php');
+];
diff --git a/apps/files_versions/composer/autoload.php b/apps/files_versions/composer/autoload.php
index f75dc09160c..4505dd14227 100644
--- a/apps/files_versions/composer/autoload.php
+++ b/apps/files_versions/composer/autoload.php
@@ -3,8 +3,21 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
- echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
- exit(1);
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, $err);
+ } elseif (!headers_sent()) {
+ echo $err;
+ }
+ }
+ trigger_error(
+ $err,
+ E_USER_ERROR
+ );
}
require_once __DIR__ . '/composer/autoload_real.php';
diff --git a/apps/files_versions/composer/composer/ClassLoader.php b/apps/files_versions/composer/composer/ClassLoader.php
index afef3fa2ad8..7824d8f7eaf 100644
--- a/apps/files_versions/composer/composer/ClassLoader.php
+++ b/apps/files_versions/composer/composer/ClassLoader.php
@@ -42,35 +42,37 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
- /** @var ?string */
+ /** @var \Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
private $vendorDir;
// PSR-4
/**
- * @var array[]
- * @psalm-var array<string, array<string, int>>
+ * @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, array<int, string>>
+ * @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
- * @var array[]
- * @psalm-var array<string, array<string, string[]>>
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -78,8 +80,7 @@ class ClassLoader
private $useIncludePath = false;
/**
- * @var string[]
- * @psalm-var array<string, string>
+ * @var array<string, string>
*/
private $classMap = array();
@@ -87,29 +88,29 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
- * @var bool[]
- * @psalm-var array<string, bool>
+ * @var array<string, bool>
*/
private $missingClasses = array();
- /** @var ?string */
+ /** @var string|null */
private $apcuPrefix;
/**
- * @var self[]
+ * @var array<string, self>
*/
private static $registeredLoaders = array();
/**
- * @param ?string $vendorDir
+ * @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
}
/**
- * @return string[]
+ * @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -121,8 +122,7 @@ class ClassLoader
}
/**
- * @return array[]
- * @psalm-return array<string, array<int, string>>
+ * @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -130,8 +130,7 @@ class ClassLoader
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirs()
{
@@ -139,8 +138,7 @@ class ClassLoader
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -148,8 +146,7 @@ class ClassLoader
}
/**
- * @return string[] Array of classname => path
- * @psalm-return array<string, string>
+ * @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -157,8 +154,7 @@ class ClassLoader
}
/**
- * @param string[] $classMap Class to filename map
- * @psalm-param array<string, string> $classMap
+ * @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -175,24 +171,25 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
- (array) $paths
+ $paths
);
}
@@ -201,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+ $this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -222,9 +219,9 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param string[]|string $paths The PSR-4 base directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list<string>|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
@@ -232,17 +229,18 @@ class ClassLoader
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
- (array) $paths
+ $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -252,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ $this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -272,8 +270,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 base directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -290,8 +288,8 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param string[]|string $paths The PSR-4 base directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -425,7 +423,8 @@ class ClassLoader
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
- includeFile($file);
+ $includeFile = self::$includeFile;
+ $includeFile($file);
return true;
}
@@ -476,9 +475,9 @@ class ClassLoader
}
/**
- * Returns the currently registered loaders indexed by their corresponding vendor directories.
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
*
- * @return self[]
+ * @return array<string, self>
*/
public static function getRegisteredLoaders()
{
@@ -555,18 +554,26 @@ class ClassLoader
return false;
}
-}
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- *
- * @param string $file
- * @return void
- * @private
- */
-function includeFile($file)
-{
- include $file;
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = \Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
}
diff --git a/apps/files_versions/composer/composer/InstalledVersions.php b/apps/files_versions/composer/composer/InstalledVersions.php
index 41bc143c114..51e734a774b 100644
--- a/apps/files_versions/composer/composer/InstalledVersions.php
+++ b/apps/files_versions/composer/composer/InstalledVersions.php
@@ -28,7 +28,7 @@ class InstalledVersions
{
/**
* @var mixed[]|null
- * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
+ * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
@@ -39,7 +39,7 @@ class InstalledVersions
/**
* @var array[]
- * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+ * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
@@ -98,7 +98,7 @@ class InstalledVersions
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
- return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
@@ -119,7 +119,7 @@ class InstalledVersions
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
- $constraint = $parser->parseConstraints($constraint);
+ $constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
@@ -243,7 +243,7 @@ class InstalledVersions
/**
* @return array
- * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
+ * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
@@ -257,7 +257,7 @@ class InstalledVersions
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
- * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
+ * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@@ -280,7 +280,7 @@ class InstalledVersions
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
- * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+ * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
@@ -303,7 +303,7 @@ class InstalledVersions
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
- * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
+ * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
@@ -313,7 +313,7 @@ class InstalledVersions
/**
* @return array[]
- * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+ * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
@@ -328,7 +328,9 @@ class InstalledVersions
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
- $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+ $required = require $vendorDir.'/composer/installed.php';
+ $installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
@@ -340,12 +342,17 @@ class InstalledVersions
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
- self::$installed = require __DIR__ . '/installed.php';
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+ $required = require __DIR__ . '/installed.php';
+ self::$installed = $required;
} else {
self::$installed = array();
}
}
- $installed[] = self::$installed;
+
+ if (self::$installed !== array()) {
+ $installed[] = self::$installed;
+ }
return $installed;
}
diff --git a/apps/files_versions/composer/composer/autoload_classmap.php b/apps/files_versions/composer/composer/autoload_classmap.php
index 43b678ef39c..27e68decdcc 100644
--- a/apps/files_versions/composer/composer/autoload_classmap.php
+++ b/apps/files_versions/composer/composer/autoload_classmap.php
@@ -14,11 +14,19 @@ return array(
'OCA\\Files_Versions\\Command\\Expire' => $baseDir . '/../lib/Command/Expire.php',
'OCA\\Files_Versions\\Command\\ExpireVersions' => $baseDir . '/../lib/Command/ExpireVersions.php',
'OCA\\Files_Versions\\Controller\\PreviewController' => $baseDir . '/../lib/Controller/PreviewController.php',
+ 'OCA\\Files_Versions\\Db\\VersionEntity' => $baseDir . '/../lib/Db/VersionEntity.php',
+ 'OCA\\Files_Versions\\Db\\VersionsMapper' => $baseDir . '/../lib/Db/VersionsMapper.php',
'OCA\\Files_Versions\\Events\\CreateVersionEvent' => $baseDir . '/../lib/Events/CreateVersionEvent.php',
+ 'OCA\\Files_Versions\\Events\\VersionCreatedEvent' => $baseDir . '/../lib/Events/VersionCreatedEvent.php',
+ 'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => $baseDir . '/../lib/Events/VersionRestoredEvent.php',
'OCA\\Files_Versions\\Expiration' => $baseDir . '/../lib/Expiration.php',
- 'OCA\\Files_Versions\\Hooks' => $baseDir . '/../lib/Hooks.php',
+ 'OCA\\Files_Versions\\Listener\\FileEventsListener' => $baseDir . '/../lib/Listener/FileEventsListener.php',
+ 'OCA\\Files_Versions\\Listener\\LegacyRollbackListener' => $baseDir . '/../lib/Listener/LegacyRollbackListener.php',
'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
+ 'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => $baseDir . '/../lib/Listener/VersionAuthorListener.php',
+ 'OCA\\Files_Versions\\Listener\\VersionStorageMoveListener' => $baseDir . '/../lib/Listener/VersionStorageMoveListener.php',
+ 'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => $baseDir . '/../lib/Migration/Version1020Date20221114144058.php',
'OCA\\Files_Versions\\Sabre\\Plugin' => $baseDir . '/../lib/Sabre/Plugin.php',
'OCA\\Files_Versions\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php',
'OCA\\Files_Versions\\Sabre\\RootCollection' => $baseDir . '/../lib/Sabre/RootCollection.php',
@@ -28,9 +36,16 @@ return array(
'OCA\\Files_Versions\\Sabre\\VersionRoot' => $baseDir . '/../lib/Sabre/VersionRoot.php',
'OCA\\Files_Versions\\Storage' => $baseDir . '/../lib/Storage.php',
'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => $baseDir . '/../lib/Versions/BackendNotFoundException.php',
+ 'OCA\\Files_Versions\\Versions\\IDeletableVersionBackend' => $baseDir . '/../lib/Versions/IDeletableVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\IMetadataVersion' => $baseDir . '/../lib/Versions/IMetadataVersion.php',
+ 'OCA\\Files_Versions\\Versions\\IMetadataVersionBackend' => $baseDir . '/../lib/Versions/IMetadataVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\INameableVersion' => $baseDir . '/../lib/Versions/INameableVersion.php',
+ 'OCA\\Files_Versions\\Versions\\INameableVersionBackend' => $baseDir . '/../lib/Versions/INameableVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\INeedSyncVersionBackend' => $baseDir . '/../lib/Versions/INeedSyncVersionBackend.php',
'OCA\\Files_Versions\\Versions\\IVersion' => $baseDir . '/../lib/Versions/IVersion.php',
'OCA\\Files_Versions\\Versions\\IVersionBackend' => $baseDir . '/../lib/Versions/IVersionBackend.php',
'OCA\\Files_Versions\\Versions\\IVersionManager' => $baseDir . '/../lib/Versions/IVersionManager.php',
+ 'OCA\\Files_Versions\\Versions\\IVersionsImporterBackend' => $baseDir . '/../lib/Versions/IVersionsImporterBackend.php',
'OCA\\Files_Versions\\Versions\\LegacyVersionsBackend' => $baseDir . '/../lib/Versions/LegacyVersionsBackend.php',
'OCA\\Files_Versions\\Versions\\Version' => $baseDir . '/../lib/Versions/Version.php',
'OCA\\Files_Versions\\Versions\\VersionManager' => $baseDir . '/../lib/Versions/VersionManager.php',
diff --git a/apps/files_versions/composer/composer/autoload_static.php b/apps/files_versions/composer/composer/autoload_static.php
index 1cbb96bf841..8ecc1cb0137 100644
--- a/apps/files_versions/composer/composer/autoload_static.php
+++ b/apps/files_versions/composer/composer/autoload_static.php
@@ -29,11 +29,19 @@ class ComposerStaticInitFiles_Versions
'OCA\\Files_Versions\\Command\\Expire' => __DIR__ . '/..' . '/../lib/Command/Expire.php',
'OCA\\Files_Versions\\Command\\ExpireVersions' => __DIR__ . '/..' . '/../lib/Command/ExpireVersions.php',
'OCA\\Files_Versions\\Controller\\PreviewController' => __DIR__ . '/..' . '/../lib/Controller/PreviewController.php',
+ 'OCA\\Files_Versions\\Db\\VersionEntity' => __DIR__ . '/..' . '/../lib/Db/VersionEntity.php',
+ 'OCA\\Files_Versions\\Db\\VersionsMapper' => __DIR__ . '/..' . '/../lib/Db/VersionsMapper.php',
'OCA\\Files_Versions\\Events\\CreateVersionEvent' => __DIR__ . '/..' . '/../lib/Events/CreateVersionEvent.php',
+ 'OCA\\Files_Versions\\Events\\VersionCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/VersionCreatedEvent.php',
+ 'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/VersionRestoredEvent.php',
'OCA\\Files_Versions\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php',
- 'OCA\\Files_Versions\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php',
+ 'OCA\\Files_Versions\\Listener\\FileEventsListener' => __DIR__ . '/..' . '/../lib/Listener/FileEventsListener.php',
+ 'OCA\\Files_Versions\\Listener\\LegacyRollbackListener' => __DIR__ . '/..' . '/../lib/Listener/LegacyRollbackListener.php',
'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
+ 'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => __DIR__ . '/..' . '/../lib/Listener/VersionAuthorListener.php',
+ 'OCA\\Files_Versions\\Listener\\VersionStorageMoveListener' => __DIR__ . '/..' . '/../lib/Listener/VersionStorageMoveListener.php',
+ 'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => __DIR__ . '/..' . '/../lib/Migration/Version1020Date20221114144058.php',
'OCA\\Files_Versions\\Sabre\\Plugin' => __DIR__ . '/..' . '/../lib/Sabre/Plugin.php',
'OCA\\Files_Versions\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php',
'OCA\\Files_Versions\\Sabre\\RootCollection' => __DIR__ . '/..' . '/../lib/Sabre/RootCollection.php',
@@ -43,9 +51,16 @@ class ComposerStaticInitFiles_Versions
'OCA\\Files_Versions\\Sabre\\VersionRoot' => __DIR__ . '/..' . '/../lib/Sabre/VersionRoot.php',
'OCA\\Files_Versions\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php',
'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => __DIR__ . '/..' . '/../lib/Versions/BackendNotFoundException.php',
+ 'OCA\\Files_Versions\\Versions\\IDeletableVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IDeletableVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\IMetadataVersion' => __DIR__ . '/..' . '/../lib/Versions/IMetadataVersion.php',
+ 'OCA\\Files_Versions\\Versions\\IMetadataVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IMetadataVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\INameableVersion' => __DIR__ . '/..' . '/../lib/Versions/INameableVersion.php',
+ 'OCA\\Files_Versions\\Versions\\INameableVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/INameableVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\INeedSyncVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/INeedSyncVersionBackend.php',
'OCA\\Files_Versions\\Versions\\IVersion' => __DIR__ . '/..' . '/../lib/Versions/IVersion.php',
'OCA\\Files_Versions\\Versions\\IVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IVersionBackend.php',
'OCA\\Files_Versions\\Versions\\IVersionManager' => __DIR__ . '/..' . '/../lib/Versions/IVersionManager.php',
+ 'OCA\\Files_Versions\\Versions\\IVersionsImporterBackend' => __DIR__ . '/..' . '/../lib/Versions/IVersionsImporterBackend.php',
'OCA\\Files_Versions\\Versions\\LegacyVersionsBackend' => __DIR__ . '/..' . '/../lib/Versions/LegacyVersionsBackend.php',
'OCA\\Files_Versions\\Versions\\Version' => __DIR__ . '/..' . '/../lib/Versions/Version.php',
'OCA\\Files_Versions\\Versions\\VersionManager' => __DIR__ . '/..' . '/../lib/Versions/VersionManager.php',
diff --git a/apps/files_versions/composer/composer/installed.php b/apps/files_versions/composer/composer/installed.php
index 5440719fa40..650df1d51b8 100644
--- a/apps/files_versions/composer/composer/installed.php
+++ b/apps/files_versions/composer/composer/installed.php
@@ -1,22 +1,22 @@
<?php return array(
'root' => array(
+ 'name' => '__root__',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
+ 'reference' => '84930a207a8d5f0ef32320796fe188892b63fa19',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
- 'reference' => 'c6429e6cd19c57582364338362e543580821cf99',
- 'name' => '__root__',
'dev' => false,
),
'versions' => array(
'__root__' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
+ 'reference' => '84930a207a8d5f0ef32320796fe188892b63fa19',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
- 'reference' => 'c6429e6cd19c57582364338362e543580821cf99',
'dev_requirement' => false,
),
),
diff --git a/apps/files_versions/img/app-dark.svg b/apps/files_versions/img/app-dark.svg
new file mode 100644
index 00000000000..ecddb64ce3a
--- /dev/null
+++ b/apps/files_versions/img/app-dark.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px"><path d="M479.79-408Q450-408 429-429.21t-21-51Q408-510 429.21-531t51-21Q510-552 531-530.79t21 51Q552-450 530.79-429t-51 21Zm.21 264q-140 0-238.5-98T144-480h72q2 110 78.5 187T480-216q110.31 0 187.16-76.78 76.84-76.78 76.84-187T667.16-667Q590.31-744 480-744q-59 0-111.5 25.5T277-648h107v72H144v-240h72v130q47.91-62.09 116.95-96.04Q402-816 480-816q70 0 131.13 26.6 61.14 26.6 106.4 71.87 45.27 45.26 71.87 106.4Q816-550 816-480t-26.6 131.13q-26.6 61.14-71.87 106.4-45.26 45.27-106.4 71.87Q550-144 480-144Z"/></svg> \ No newline at end of file
diff --git a/apps/files_versions/img/app.svg b/apps/files_versions/img/app.svg
index e7dba1e9286..651ed400e32 100644
--- a/apps/files_versions/img/app.svg
+++ b/apps/files_versions/img/app.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16" version="1"><rect rx=".5" ry=".5" height="4" width="4" y="1" x="1" fill="#fff"/><rect rx=".5" ry=".5" height="1" width="9" y="2" x="6" fill="#fff"/><rect rx=".5" ry=".5" height="4" width="4" y="6" x="1" fill="#fff"/><rect rx=".5" ry=".5" height="1" width="9" y="7" x="6" fill="#fff"/><rect rx=".5" ry=".5" height="4" width="4" y="11" x="1" fill="#fff"/><rect rx=".5" ry=".5" height="1" width="9" y="12" x="6" fill="#fff"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" fill="#fff"><path d="M479.79-408Q450-408 429-429.21t-21-51Q408-510 429.21-531t51-21Q510-552 531-530.79t21 51Q552-450 530.79-429t-51 21Zm.21 264q-140 0-238.5-98T144-480h72q2 110 78.5 187T480-216q110.31 0 187.16-76.78 76.84-76.78 76.84-187T667.16-667Q590.31-744 480-744q-59 0-111.5 25.5T277-648h107v72H144v-240h72v130q47.91-62.09 116.95-96.04Q402-816 480-816q70 0 131.13 26.6 61.14 26.6 106.4 71.87 45.27 45.26 71.87 106.4Q816-550 816-480t-26.6 131.13q-26.6 61.14-71.87 106.4-45.26 45.27-106.4 71.87Q550-144 480-144Z"/></svg> \ No newline at end of file
diff --git a/apps/files_versions/l10n/af.js b/apps/files_versions/l10n/af.js
deleted file mode 100644
index 7986f018877..00000000000
--- a/apps/files_versions/l10n/af.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Weergawes",
- "Failed to revert {file} to revision {timestamp}." : "Kon nie {file} na {timestamp} se hersiening terugstel nie.",
- "_%n byte_::_%n bytes_" : ["%n greep","%n grepe"],
- "Restore" : "Herstel"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/af.json b/apps/files_versions/l10n/af.json
deleted file mode 100644
index 23f30920b9e..00000000000
--- a/apps/files_versions/l10n/af.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Weergawes",
- "Failed to revert {file} to revision {timestamp}." : "Kon nie {file} na {timestamp} se hersiening terugstel nie.",
- "_%n byte_::_%n bytes_" : ["%n greep","%n grepe"],
- "Restore" : "Herstel"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ar.js b/apps/files_versions/l10n/ar.js
index 81bd0c65269..318ca0dbfe2 100644
--- a/apps/files_versions/l10n/ar.js
+++ b/apps/files_versions/l10n/ar.js
@@ -1,9 +1,29 @@
OC.L10N.register(
"files_versions",
{
- "Versions" : "الإصدارات",
- "Failed to revert {file} to revision {timestamp}." : "فشل في استعادة {ملف} لنتقيح {الطابع الزمني}",
- "Restore" : "استعادة ",
- "No other versions available" : "لا تتوفر هناك نُسخ أخرى"
+ "Versions" : "النسخ",
+ "This application automatically maintains older versions of files that are changed." : "هذا التطبيق يقوم تلقائيا بحفظ النسخ الأقدم من الملفات التي يتم تعديلها.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "يحتفظ هذا التطبيق تلقائيًا بالنُّسخ القديمة من الملفات بعد تعديلها. عند تمكينه، يتم توفير مجلد الإصدارات المخفية في دليل كل مستخدم و يتم استخدامه لتخزين النسخ الأقدم للملفات. يمكن للمستخدم الرجوع إلى نسخة أقدم من خلال واجهة الويب في أي وقت. حيث يصبح الملف المستبدل نسخةً. يقوم التطبيق تلقائيًا بإدارة مجلد النُّسخ لضمان عدم نفاد الحصة النسبية للحساب بسبب النُّسخ. \t\t\nبالإضافة إلى انتهاء صلاحية النُّسخ، يتأكد تطبيق النُّسخ من عدم استخدام أكثر من 50% من المساحة المجانية المتوفرة حاليًا للحساب لغرض الاحتفاظ بالنُّسخ. إذا تجاوزت مساحة تخزين النُّسخ المخزنة هذا الحد، عندها يقوم التطبيق بحذف النُّسخ الأقدم أولاً حتى ترجع مساحة التخزين إلى الحد المسموح به. مزيد من المعلومات في توثيق التطبيق.",
+ "Current version" : "النسخة الحالية",
+ "Initial version" : "النسخة الأساسية",
+ "You" : "أنت",
+ "Actions for version from {versionHumanExplicitDate}" : "إجراءات على النسخة من {versionHumanExplicitDate}",
+ "Name this version" : "أعط اسماً لهذه النسخة",
+ "Edit version name" : "تعديل اسم النسخة",
+ "Compare to current version" : "قارِن مع النسخة الحاليّة",
+ "Restore version" : "استعادة النسخة",
+ "Download version" : "تنزيل النسخة",
+ "Delete version" : "حذف النسخة",
+ "Cancel" : "إلغاء",
+ "Remove version name" : "إلغ اسم النسخة",
+ "Save version name" : "إحفظ اسم النسخة",
+ "Version name" : "اسم النسخة",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "النسخ المسماة محفوظة ومستثناة من التنظيف التلقائي عند امتلاء الحصة التخزينية الخاصة بك.",
+ "Initial version restored" : "استعادة النسخة الأساسية",
+ "Version restored" : "تمّت استعادة النسخة",
+ "Could not restore version" : "تعذّرت استعادة النسخة",
+ "Could not set version label" : "تعذّر تعيين تسمية للنسخة",
+ "Could not delete version" : "تعذّر حذف النسخة",
+ "File versions" : "إصدارات الملف"
},
"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/apps/files_versions/l10n/ar.json b/apps/files_versions/l10n/ar.json
index f68c07fb142..9473ac90f25 100644
--- a/apps/files_versions/l10n/ar.json
+++ b/apps/files_versions/l10n/ar.json
@@ -1,7 +1,27 @@
{ "translations": {
- "Versions" : "الإصدارات",
- "Failed to revert {file} to revision {timestamp}." : "فشل في استعادة {ملف} لنتقيح {الطابع الزمني}",
- "Restore" : "استعادة ",
- "No other versions available" : "لا تتوفر هناك نُسخ أخرى"
+ "Versions" : "النسخ",
+ "This application automatically maintains older versions of files that are changed." : "هذا التطبيق يقوم تلقائيا بحفظ النسخ الأقدم من الملفات التي يتم تعديلها.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "يحتفظ هذا التطبيق تلقائيًا بالنُّسخ القديمة من الملفات بعد تعديلها. عند تمكينه، يتم توفير مجلد الإصدارات المخفية في دليل كل مستخدم و يتم استخدامه لتخزين النسخ الأقدم للملفات. يمكن للمستخدم الرجوع إلى نسخة أقدم من خلال واجهة الويب في أي وقت. حيث يصبح الملف المستبدل نسخةً. يقوم التطبيق تلقائيًا بإدارة مجلد النُّسخ لضمان عدم نفاد الحصة النسبية للحساب بسبب النُّسخ. \t\t\nبالإضافة إلى انتهاء صلاحية النُّسخ، يتأكد تطبيق النُّسخ من عدم استخدام أكثر من 50% من المساحة المجانية المتوفرة حاليًا للحساب لغرض الاحتفاظ بالنُّسخ. إذا تجاوزت مساحة تخزين النُّسخ المخزنة هذا الحد، عندها يقوم التطبيق بحذف النُّسخ الأقدم أولاً حتى ترجع مساحة التخزين إلى الحد المسموح به. مزيد من المعلومات في توثيق التطبيق.",
+ "Current version" : "النسخة الحالية",
+ "Initial version" : "النسخة الأساسية",
+ "You" : "أنت",
+ "Actions for version from {versionHumanExplicitDate}" : "إجراءات على النسخة من {versionHumanExplicitDate}",
+ "Name this version" : "أعط اسماً لهذه النسخة",
+ "Edit version name" : "تعديل اسم النسخة",
+ "Compare to current version" : "قارِن مع النسخة الحاليّة",
+ "Restore version" : "استعادة النسخة",
+ "Download version" : "تنزيل النسخة",
+ "Delete version" : "حذف النسخة",
+ "Cancel" : "إلغاء",
+ "Remove version name" : "إلغ اسم النسخة",
+ "Save version name" : "إحفظ اسم النسخة",
+ "Version name" : "اسم النسخة",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "النسخ المسماة محفوظة ومستثناة من التنظيف التلقائي عند امتلاء الحصة التخزينية الخاصة بك.",
+ "Initial version restored" : "استعادة النسخة الأساسية",
+ "Version restored" : "تمّت استعادة النسخة",
+ "Could not restore version" : "تعذّرت استعادة النسخة",
+ "Could not set version label" : "تعذّر تعيين تسمية للنسخة",
+ "Could not delete version" : "تعذّر حذف النسخة",
+ "File versions" : "إصدارات الملف"
},"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
diff --git a/apps/files_versions/l10n/ast.js b/apps/files_versions/l10n/ast.js
index 41d2799fbfa..4264f046b1f 100644
--- a/apps/files_versions/l10n/ast.js
+++ b/apps/files_versions/l10n/ast.js
@@ -2,9 +2,26 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Fallu al revertir {file} a la revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Nun hai otres versiones disponibles"
+ "This application automatically maintains older versions of files that are changed." : "Esta aplicación caltién automáticamente les versiones antigües de los ficheros que camudaron.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación caltién automáticamente les versiones antigües de los ficheros que camudaron. Cuando s'activa, crease una carpeta de versiones anubrida p'atroxar les versiones antigües de los ficheros. Los usuarios puen recuperar una versión anterior pente la interfaz web en cualesquier momentu y el ficheru trocáu conviértese nun versión. L'aplicación xestiona automáticamente la carpeta de versiones p'asegurar de que la cuenta nun escosa la cuota pola mor de les versiones.\n\t\tAmás de la caducidá de les versiones, l'aplicación Versiones garantiza qu'enxamás nun s'usa más del 50% d'espaciu llibre disponible pa la cuenta. Si les versiones atroxaes superen esta llende, l'aplicación va desaniciar les primeres versiones más antigües hasta que se respete esta llende. Tienes más información disponible na documentación de Versiones.",
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Tu",
+ "Name this version" : "Nomar esta versión",
+ "Edit version name" : "Editar el nome de la versión",
+ "Compare to current version" : "Comparar cola versión actual",
+ "Restore version" : "Restaurar la versión",
+ "Download version" : "Baxar la versión",
+ "Delete version" : "Desaniciar la versión",
+ "Cancel" : "Encaboxar",
+ "Remove version name" : "Quitar el nome de la versión",
+ "Save version name" : "Guardar el nome de la versiones",
+ "Version name" : "Nome de la versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Les versiones con nome caltiénense y esclúinse de los borraos automáticos cuando la cuota del discu ta completa.",
+ "Initial version restored" : "Restauróse la versión inicial",
+ "Version restored" : "Restauróse la versión",
+ "Could not restore version" : "Nun se pudo restaurar la versión",
+ "Could not set version label" : "Nun se pudo afitar la etiqueta de la versión",
+ "Could not delete version" : "Nun se pudo desaniciar la versión"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/ast.json b/apps/files_versions/l10n/ast.json
index c8f27a1456f..27cdb853abc 100644
--- a/apps/files_versions/l10n/ast.json
+++ b/apps/files_versions/l10n/ast.json
@@ -1,8 +1,25 @@
{ "translations": {
"Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Fallu al revertir {file} a la revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Nun hai otres versiones disponibles"
+ "This application automatically maintains older versions of files that are changed." : "Esta aplicación caltién automáticamente les versiones antigües de los ficheros que camudaron.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación caltién automáticamente les versiones antigües de los ficheros que camudaron. Cuando s'activa, crease una carpeta de versiones anubrida p'atroxar les versiones antigües de los ficheros. Los usuarios puen recuperar una versión anterior pente la interfaz web en cualesquier momentu y el ficheru trocáu conviértese nun versión. L'aplicación xestiona automáticamente la carpeta de versiones p'asegurar de que la cuenta nun escosa la cuota pola mor de les versiones.\n\t\tAmás de la caducidá de les versiones, l'aplicación Versiones garantiza qu'enxamás nun s'usa más del 50% d'espaciu llibre disponible pa la cuenta. Si les versiones atroxaes superen esta llende, l'aplicación va desaniciar les primeres versiones más antigües hasta que se respete esta llende. Tienes más información disponible na documentación de Versiones.",
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Tu",
+ "Name this version" : "Nomar esta versión",
+ "Edit version name" : "Editar el nome de la versión",
+ "Compare to current version" : "Comparar cola versión actual",
+ "Restore version" : "Restaurar la versión",
+ "Download version" : "Baxar la versión",
+ "Delete version" : "Desaniciar la versión",
+ "Cancel" : "Encaboxar",
+ "Remove version name" : "Quitar el nome de la versión",
+ "Save version name" : "Guardar el nome de la versiones",
+ "Version name" : "Nome de la versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Les versiones con nome caltiénense y esclúinse de los borraos automáticos cuando la cuota del discu ta completa.",
+ "Initial version restored" : "Restauróse la versión inicial",
+ "Version restored" : "Restauróse la versión",
+ "Could not restore version" : "Nun se pudo restaurar la versión",
+ "Could not set version label" : "Nun se pudo afitar la etiqueta de la versión",
+ "Could not delete version" : "Nun se pudo desaniciar la versión"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/az.js b/apps/files_versions/l10n/az.js
deleted file mode 100644
index 34c9ddf1c9b..00000000000
--- a/apps/files_versions/l10n/az.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiyaları",
- "Failed to revert {file} to revision {timestamp}." : "{timestamp} yenidən baxılması üçün {file} geri qaytarmaq mümkün olmadı.",
- "Restore" : "Geri qaytar",
- "No other versions available" : "Başqa versiyalar mövcud deyil"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/az.json b/apps/files_versions/l10n/az.json
deleted file mode 100644
index dd67d6ca403..00000000000
--- a/apps/files_versions/l10n/az.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiyaları",
- "Failed to revert {file} to revision {timestamp}." : "{timestamp} yenidən baxılması üçün {file} geri qaytarmaq mümkün olmadı.",
- "Restore" : "Geri qaytar",
- "No other versions available" : "Başqa versiyalar mövcud deyil"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/be.js b/apps/files_versions/l10n/be.js
new file mode 100644
index 00000000000..7e5200ecb83
--- /dev/null
+++ b/apps/files_versions/l10n/be.js
@@ -0,0 +1,17 @@
+OC.L10N.register(
+ "files_versions",
+ {
+ "Versions" : "Версіі",
+ "Current version" : "Бягучая версія",
+ "You" : "Вы",
+ "Delete version" : "Выдаліць версію",
+ "Cancel" : "Скасаваць",
+ "Remove version name" : "Выдаліць назву версіі",
+ "Save version name" : "Захаваць назву версіі",
+ "Version name" : "Назва версіі",
+ "Version restored" : "Версія адноўлена",
+ "Could not restore version" : "Не ўдалося аднавіць версію",
+ "Could not delete version" : "Не ўдалося выдаліць версію",
+ "File versions" : "Версіі файла"
+},
+"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");
diff --git a/apps/files_versions/l10n/be.json b/apps/files_versions/l10n/be.json
new file mode 100644
index 00000000000..27e4f646a97
--- /dev/null
+++ b/apps/files_versions/l10n/be.json
@@ -0,0 +1,15 @@
+{ "translations": {
+ "Versions" : "Версіі",
+ "Current version" : "Бягучая версія",
+ "You" : "Вы",
+ "Delete version" : "Выдаліць версію",
+ "Cancel" : "Скасаваць",
+ "Remove version name" : "Выдаліць назву версіі",
+ "Save version name" : "Захаваць назву версіі",
+ "Version name" : "Назва версіі",
+ "Version restored" : "Версія адноўлена",
+ "Could not restore version" : "Не ўдалося аднавіць версію",
+ "Could not delete version" : "Не ўдалося выдаліць версію",
+ "File versions" : "Версіі файла"
+},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
+} \ No newline at end of file
diff --git a/apps/files_versions/l10n/bg.js b/apps/files_versions/l10n/bg.js
index 9b3c19fa403..94fbc38c830 100644
--- a/apps/files_versions/l10n/bg.js
+++ b/apps/files_versions/l10n/bg.js
@@ -3,10 +3,20 @@ OC.L10N.register(
{
"Versions" : "Версии",
"This application automatically maintains older versions of files that are changed." : "Това приложение автоматично поддържа по-стари версии на файлове, които са променени.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Това приложение автоматично поддържа по-стари версии на файлове, които са променени. Когато е активирана, папката със скрити версии се предоставя в директорията на всеки потребител и се използва за съхраняване на стари версии на файлове. Потребителят може да се върне към по-стара версия чрез уеб интерфейса по всяко време, като замененият файл се превръща във версия. Приложението автоматично управлява папката с версии, за да гарантира, че потребителят няма да изчерпи квотата заради версиите.\nВ допълнение към изтичането на версиите, приложението за версии гарантира, че никога няма да използва повече от 50% от наличното в момента свободно пространство на потребителя. Ако съхранените версии надвишават това ограничение, приложението първо ще изтрие най-старите версии, докато не достигне това ограничение. Повече информация можете да намерите в документацията за версиите.",
- "Failed to revert {file} to revision {timestamp}." : "Грешка при връщане на {file} към версия {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n байт","%n байта"],
- "Restore" : "Възтановяване",
- "No other versions available" : "Няма версии"
+ "Current version" : "Текуща версия",
+ "Name this version" : "Наименуване на тази версия",
+ "Edit version name" : "Редактиране на името на версия",
+ "Restore version" : "Възстановяване на версия",
+ "Download version" : "Изтегляне на версия",
+ "Delete version" : "Изтриване на версия",
+ "Cancel" : "Отказ",
+ "Remove version name" : "Премахване на име на версия",
+ "Save version name" : "Записване на име на версия",
+ "Version name" : "Име на версия",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именуваните версии се запазват и се изключват от автоматичните почиствания, когато квотата за хранилище е пълна.",
+ "Initial version restored" : "Възстановяване на първоначалната версия",
+ "Version restored" : "Версията е възстановена",
+ "Could not restore version" : "Версията не можа да се възстанови",
+ "Could not delete version" : "Версията не можа да се изтрие"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/bg.json b/apps/files_versions/l10n/bg.json
index 52c44ccec56..52243426e7d 100644
--- a/apps/files_versions/l10n/bg.json
+++ b/apps/files_versions/l10n/bg.json
@@ -1,10 +1,20 @@
{ "translations": {
"Versions" : "Версии",
"This application automatically maintains older versions of files that are changed." : "Това приложение автоматично поддържа по-стари версии на файлове, които са променени.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Това приложение автоматично поддържа по-стари версии на файлове, които са променени. Когато е активирана, папката със скрити версии се предоставя в директорията на всеки потребител и се използва за съхраняване на стари версии на файлове. Потребителят може да се върне към по-стара версия чрез уеб интерфейса по всяко време, като замененият файл се превръща във версия. Приложението автоматично управлява папката с версии, за да гарантира, че потребителят няма да изчерпи квотата заради версиите.\nВ допълнение към изтичането на версиите, приложението за версии гарантира, че никога няма да използва повече от 50% от наличното в момента свободно пространство на потребителя. Ако съхранените версии надвишават това ограничение, приложението първо ще изтрие най-старите версии, докато не достигне това ограничение. Повече информация можете да намерите в документацията за версиите.",
- "Failed to revert {file} to revision {timestamp}." : "Грешка при връщане на {file} към версия {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n байт","%n байта"],
- "Restore" : "Възтановяване",
- "No other versions available" : "Няма версии"
+ "Current version" : "Текуща версия",
+ "Name this version" : "Наименуване на тази версия",
+ "Edit version name" : "Редактиране на името на версия",
+ "Restore version" : "Възстановяване на версия",
+ "Download version" : "Изтегляне на версия",
+ "Delete version" : "Изтриване на версия",
+ "Cancel" : "Отказ",
+ "Remove version name" : "Премахване на име на версия",
+ "Save version name" : "Записване на име на версия",
+ "Version name" : "Име на версия",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именуваните версии се запазват и се изключват от автоматичните почиствания, когато квотата за хранилище е пълна.",
+ "Initial version restored" : "Възстановяване на първоначалната версия",
+ "Version restored" : "Версията е възстановена",
+ "Could not restore version" : "Версията не можа да се възстанови",
+ "Could not delete version" : "Версията не можа да се изтрие"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/bn_BD.js b/apps/files_versions/l10n/bn_BD.js
deleted file mode 100644
index 4466198c4f3..00000000000
--- a/apps/files_versions/l10n/bn_BD.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "সংষ্করন",
- "Failed to revert {file} to revision {timestamp}." : " {file} সংশোধিত {timestamp} এ ফিরে যেতে ব্যার্থ হলো।",
- "Restore" : "ফিরিয়ে দাও",
- "No other versions available" : "আর কোন সংষ্করণ প্রাপ্তব্য নয়"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/bn_BD.json b/apps/files_versions/l10n/bn_BD.json
deleted file mode 100644
index 09ac6eae066..00000000000
--- a/apps/files_versions/l10n/bn_BD.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "সংষ্করন",
- "Failed to revert {file} to revision {timestamp}." : " {file} সংশোধিত {timestamp} এ ফিরে যেতে ব্যার্থ হলো।",
- "Restore" : "ফিরিয়ে দাও",
- "No other versions available" : "আর কোন সংষ্করণ প্রাপ্তব্য নয়"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/br.js b/apps/files_versions/l10n/br.js
deleted file mode 100644
index 900f9b21e8b..00000000000
--- a/apps/files_versions/l10n/br.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Stumm",
- "This application automatically maintains older versions of files that are changed." : "Ar meziant-man a laosk en un doare otomatek stumm ar resrtoù kozh a vez cheñchet",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ar meziant a dalc'h en un doare otomatek stummoù kozh ar restroù cheñchet. P'az eo aotreet, un teuliad koachet a vez roet e pep teuliad an implijour evit gwarn stummoù kozh ar restr. An implijer a c'hel adkemer ur stumm kozh n'eus forz peseurt amzer dre an etrefas web. Ar meziant a ra war dro teuliad ar stummoù evit bezhañ sur ez eus traouac'h a cQuota gant an implijer.\n\t\tOuzhpenn ar stumm diskarzed, stumm ar meziant a ra ma ne vefe ket implijet muioc'h eget 50% eus a plass vak an implijer. M'a vez dibaset e vo lemmet gant ar meziant ar stumm kozhañ da gentañ. Muioc'h titouriù en dielvadur Versions. ",
- "Failed to revert {file} to revision {timestamp}." : "C'hwitet m ar mon en dro {file} evit adober {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n okted","%n okted","%n okted","%n okted","%n octed"],
- "Restore" : "Adkrouiñ",
- "No other versions available" : "Stumm all ebet kavet"
-},
-"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);");
diff --git a/apps/files_versions/l10n/br.json b/apps/files_versions/l10n/br.json
deleted file mode 100644
index 601457f88e4..00000000000
--- a/apps/files_versions/l10n/br.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "Stumm",
- "This application automatically maintains older versions of files that are changed." : "Ar meziant-man a laosk en un doare otomatek stumm ar resrtoù kozh a vez cheñchet",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ar meziant a dalc'h en un doare otomatek stummoù kozh ar restroù cheñchet. P'az eo aotreet, un teuliad koachet a vez roet e pep teuliad an implijour evit gwarn stummoù kozh ar restr. An implijer a c'hel adkemer ur stumm kozh n'eus forz peseurt amzer dre an etrefas web. Ar meziant a ra war dro teuliad ar stummoù evit bezhañ sur ez eus traouac'h a cQuota gant an implijer.\n\t\tOuzhpenn ar stumm diskarzed, stumm ar meziant a ra ma ne vefe ket implijet muioc'h eget 50% eus a plass vak an implijer. M'a vez dibaset e vo lemmet gant ar meziant ar stumm kozhañ da gentañ. Muioc'h titouriù en dielvadur Versions. ",
- "Failed to revert {file} to revision {timestamp}." : "C'hwitet m ar mon en dro {file} evit adober {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n okted","%n okted","%n okted","%n okted","%n octed"],
- "Restore" : "Adkrouiñ",
- "No other versions available" : "Stumm all ebet kavet"
-},"pluralForm" :"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/bs.js b/apps/files_versions/l10n/bs.js
deleted file mode 100644
index 2a971f48b21..00000000000
--- a/apps/files_versions/l10n/bs.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Verzije",
- "Failed to revert {file} to revision {timestamp}." : "Nije uspelo vraćanje {file} na reviziju {timestamp}.",
- "Restore" : "Obnovi",
- "No other versions available" : "Druge verzije su nedostupne"
-},
-"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/apps/files_versions/l10n/bs.json b/apps/files_versions/l10n/bs.json
deleted file mode 100644
index c4c20540e14..00000000000
--- a/apps/files_versions/l10n/bs.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Verzije",
- "Failed to revert {file} to revision {timestamp}." : "Nije uspelo vraćanje {file} na reviziju {timestamp}.",
- "Restore" : "Obnovi",
- "No other versions available" : "Druge verzije su nedostupne"
-},"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/apps/files_versions/l10n/ca.js b/apps/files_versions/l10n/ca.js
index 10f00407005..104759c334a 100644
--- a/apps/files_versions/l10n/ca.js
+++ b/apps/files_versions/l10n/ca.js
@@ -3,10 +3,26 @@ OC.L10N.register(
{
"Versions" : "Versions",
"This application automatically maintains older versions of files that are changed." : "Aquesta aplicació conserva automàticament les versions antigues dels fitxers modificats.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aquesta aplicació conserva automàticament les versions antigues dels fitxers modificats. Si s'activa, es crearà una carpeta de versions oculta a cada carpeta dels usuaris i s'utilitzarà per a emmagatzemar les versions antigues dels fitxers. Els usuaris poden recuperar una versió anterior a través de la interfície web en qualsevol moment i el fitxer substituït es converteix en una versió. L'aplicació administra automàticament la carpeta de versions per a assegurar-se que l'usuari no es quedi sense espai per culpa de les versions.\n\t\tA més del venciment de les versions, l'aplicació Versions garanteix que no s'utilitzarà mai més del 50% de l'espai lliure disponible actualment per a l'usuari. Si les versions emmagatzemades superen aquest límit, l'aplicació suprimirà primer les versions més antigues fins que es respecti aquest límit. Podeu trobar més informació a la documentació de Versions.",
- "Failed to revert {file} to revision {timestamp}." : "No s'ha pogut recuperar la revisió {timestamp} del fitxer {file}. ",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Recupera",
- "No other versions available" : "No hi ha cap altra versió disponible"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aquesta aplicació conserva automàticament les versions antigues dels fitxers modificats. Si s'habilita, es crearà una carpeta de versions oculta a cada carpeta del compte i s'utilitzarà per a emmagatzemar les versions antigues dels fitxers. Els usuaris poden recuperar una versió anterior a través de la interfície web en qualsevol moment i el fitxer substituït es converteix en una versió. L'aplicació administra automàticament la carpeta de versions per a assegurar-se que l'usuari no es quedi sense espai per culpa de les versions.\n\t\tA més del venciment de les versions, l'aplicació Versions garanteix que no s'utilitzarà mai més del 50% de l'espai lliure disponible actualment per al compte. Si les versions emmagatzemades superen aquest límit, l'aplicació suprimirà primer les versions més antigues fins que es respecti aquest límit. Podeu trobar més informació a la documentació de Versions.",
+ "Current version" : "Versió actual",
+ "Initial version" : "Versió inicial",
+ "You" : "Vós",
+ "Actions for version from {versionHumanExplicitDate}" : "Accions per a la versió a partir de {versionHumanExplicitDate}",
+ "Name this version" : "Anomena aquesta versió",
+ "Edit version name" : "Edita el nom de la versió",
+ "Compare to current version" : "Compara amb la versió actual",
+ "Restore version" : "Recupera la versió",
+ "Download version" : "Baixa la versió",
+ "Delete version" : "Suprimeix la versió",
+ "Cancel" : "Cancel·la",
+ "Remove version name" : "Suprimeix el nom de la versió",
+ "Save version name" : "Desa el nom de la versió",
+ "Version name" : "Nom de la versió",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Les versions amb nom es conserven i s'exclouen de les neteges automàtiques quan teniu l'emmagatzematge ple.",
+ "Initial version restored" : "S'ha recuperat la versió inicial",
+ "Version restored" : "S'ha recuperat la versió",
+ "Could not restore version" : "No s'ha pogut recuperar la versió",
+ "Could not set version label" : "No s'ha pogut definir l'etiqueta de la versió",
+ "Could not delete version" : "No s'ha pogut suprimir la versió"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/ca.json b/apps/files_versions/l10n/ca.json
index 684b5faa1af..f4818d3c7ad 100644
--- a/apps/files_versions/l10n/ca.json
+++ b/apps/files_versions/l10n/ca.json
@@ -1,10 +1,26 @@
{ "translations": {
"Versions" : "Versions",
"This application automatically maintains older versions of files that are changed." : "Aquesta aplicació conserva automàticament les versions antigues dels fitxers modificats.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aquesta aplicació conserva automàticament les versions antigues dels fitxers modificats. Si s'activa, es crearà una carpeta de versions oculta a cada carpeta dels usuaris i s'utilitzarà per a emmagatzemar les versions antigues dels fitxers. Els usuaris poden recuperar una versió anterior a través de la interfície web en qualsevol moment i el fitxer substituït es converteix en una versió. L'aplicació administra automàticament la carpeta de versions per a assegurar-se que l'usuari no es quedi sense espai per culpa de les versions.\n\t\tA més del venciment de les versions, l'aplicació Versions garanteix que no s'utilitzarà mai més del 50% de l'espai lliure disponible actualment per a l'usuari. Si les versions emmagatzemades superen aquest límit, l'aplicació suprimirà primer les versions més antigues fins que es respecti aquest límit. Podeu trobar més informació a la documentació de Versions.",
- "Failed to revert {file} to revision {timestamp}." : "No s'ha pogut recuperar la revisió {timestamp} del fitxer {file}. ",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Recupera",
- "No other versions available" : "No hi ha cap altra versió disponible"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aquesta aplicació conserva automàticament les versions antigues dels fitxers modificats. Si s'habilita, es crearà una carpeta de versions oculta a cada carpeta del compte i s'utilitzarà per a emmagatzemar les versions antigues dels fitxers. Els usuaris poden recuperar una versió anterior a través de la interfície web en qualsevol moment i el fitxer substituït es converteix en una versió. L'aplicació administra automàticament la carpeta de versions per a assegurar-se que l'usuari no es quedi sense espai per culpa de les versions.\n\t\tA més del venciment de les versions, l'aplicació Versions garanteix que no s'utilitzarà mai més del 50% de l'espai lliure disponible actualment per al compte. Si les versions emmagatzemades superen aquest límit, l'aplicació suprimirà primer les versions més antigues fins que es respecti aquest límit. Podeu trobar més informació a la documentació de Versions.",
+ "Current version" : "Versió actual",
+ "Initial version" : "Versió inicial",
+ "You" : "Vós",
+ "Actions for version from {versionHumanExplicitDate}" : "Accions per a la versió a partir de {versionHumanExplicitDate}",
+ "Name this version" : "Anomena aquesta versió",
+ "Edit version name" : "Edita el nom de la versió",
+ "Compare to current version" : "Compara amb la versió actual",
+ "Restore version" : "Recupera la versió",
+ "Download version" : "Baixa la versió",
+ "Delete version" : "Suprimeix la versió",
+ "Cancel" : "Cancel·la",
+ "Remove version name" : "Suprimeix el nom de la versió",
+ "Save version name" : "Desa el nom de la versió",
+ "Version name" : "Nom de la versió",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Les versions amb nom es conserven i s'exclouen de les neteges automàtiques quan teniu l'emmagatzematge ple.",
+ "Initial version restored" : "S'ha recuperat la versió inicial",
+ "Version restored" : "S'ha recuperat la versió",
+ "Could not restore version" : "No s'ha pogut recuperar la versió",
+ "Could not set version label" : "No s'ha pogut definir l'etiqueta de la versió",
+ "Could not delete version" : "No s'ha pogut suprimir la versió"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/cs.js b/apps/files_versions/l10n/cs.js
index 1abedcecc0a..b9192c54cf5 100644
--- a/apps/files_versions/l10n/cs.js
+++ b/apps/files_versions/l10n/cs.js
@@ -2,11 +2,28 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "Verze",
- "This application automatically maintains older versions of files that are changed." : "Tato aplikace automaticky uchovává starší verze souborů, které se mění.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Tato aplikace automaticky uchovává starší verze souborů, které se mění. Když je zapnutá, je ve složce každého uživatele vytvořena skrytá složka pro verze a do ní jsou ukládány staré verze souborů. Uživatel se (prostřednictvím webového rozhraní) kdykoli může vrátit ke starším verzím s tím, že sám nahrazovaný nejnovější soubor se tak stane verzí. Aplikace automaticky spravuje složku s verzemi tak, aby bylo zajištěno, že uživatel kvůli starým verzím nevyčerpá přidělenou kvótu.\n\t\tKrom konců platností verzí, aplikace Verze zajišťuje, že nikdy nepoužije více než 50% volného prostoru, který má uživatel k dispozici. Pokud uložené verze přesáhnou tento limit, aplikace smaže ty nejstarší, aby se do tohoto limitu vešla. Podrobnosti nalezenete v dokumentaci k aplikaci Verze.",
- "Failed to revert {file} to revision {timestamp}." : "Nepodařilo se vrátit {file} do stavu k {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajty","%n bajtů","%n bajty"],
- "Restore" : "Obnovit",
- "No other versions available" : "Nejsou k dispozici žádné jiné verze"
+ "This application automatically maintains older versions of files that are changed." : "Tato aplikace automaticky uchovává starší verze souborů, které se změnily.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Tato aplikace automaticky uchovává starší verze souborů, které se změnily. Když je zapnutá, je ve složce každého uživatele vytvořena skrytá složka pro verze a do ní jsou ukládány staré verze souborů. Uživatel se (prostřednictvím webového rozhraní) kdykoli může vrátit ke starší verzi s tím, že sám nahrazovaný nejnovější soubor se tak stane verzí. Aplikace automaticky spravuje složku s verzemi tak, aby bylo zajištěno, že účet kvůli starým verzím nevyčerpá přidělenou kvótu.\n\t\tKrom konců platností verzí, aplikace Verze zajišťuje, že nikdy nepoužije více než 50% právě dostupného volného prostoru, který má účet k dispozici. Pokud uložené verze přesáhnou tento limit, aplikace smaže ty nejstarší, aby se do tohoto limitu vešla. Podrobnosti naleznete v dokumentaci k aplikaci Verze.",
+ "Current version" : "Stávající verze",
+ "Initial version" : "Počáteční verze",
+ "You" : "Vy",
+ "Actions for version from {versionHumanExplicitDate}" : "Akce pro verzi od {versionHumanExplicitDate}",
+ "Name this version" : "Nazvat tuto verzi",
+ "Edit version name" : "Upravit název verze",
+ "Compare to current version" : "Porovnat se stávající verzí",
+ "Restore version" : "Obnovit verzi",
+ "Download version" : "Stáhnout verzi",
+ "Delete version" : "Smazat verzi",
+ "Cancel" : "Storno",
+ "Remove version name" : "Odebrat název verze",
+ "Save version name" : "Uložit název verze",
+ "Version name" : "Název verze",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Výslovně verze jsou trvalé a vynechány z automatického čištění při vyčerpání vaší kvóty na úložišti.",
+ "Initial version restored" : "Počáteční verze obnovena",
+ "Version restored" : "Verze obnovena",
+ "Could not restore version" : "Verzi se nedaří obnovit",
+ "Could not set version label" : "Nepodařilo se nastavit štítek verze",
+ "Could not delete version" : "Nedaří se smazat verzi",
+ "File versions" : "Verze souborů"
},
"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;");
diff --git a/apps/files_versions/l10n/cs.json b/apps/files_versions/l10n/cs.json
index f03ffc9b1f7..1d47a9c69dc 100644
--- a/apps/files_versions/l10n/cs.json
+++ b/apps/files_versions/l10n/cs.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Verze",
- "This application automatically maintains older versions of files that are changed." : "Tato aplikace automaticky uchovává starší verze souborů, které se mění.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Tato aplikace automaticky uchovává starší verze souborů, které se mění. Když je zapnutá, je ve složce každého uživatele vytvořena skrytá složka pro verze a do ní jsou ukládány staré verze souborů. Uživatel se (prostřednictvím webového rozhraní) kdykoli může vrátit ke starším verzím s tím, že sám nahrazovaný nejnovější soubor se tak stane verzí. Aplikace automaticky spravuje složku s verzemi tak, aby bylo zajištěno, že uživatel kvůli starým verzím nevyčerpá přidělenou kvótu.\n\t\tKrom konců platností verzí, aplikace Verze zajišťuje, že nikdy nepoužije více než 50% volného prostoru, který má uživatel k dispozici. Pokud uložené verze přesáhnou tento limit, aplikace smaže ty nejstarší, aby se do tohoto limitu vešla. Podrobnosti nalezenete v dokumentaci k aplikaci Verze.",
- "Failed to revert {file} to revision {timestamp}." : "Nepodařilo se vrátit {file} do stavu k {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajty","%n bajtů","%n bajty"],
- "Restore" : "Obnovit",
- "No other versions available" : "Nejsou k dispozici žádné jiné verze"
+ "This application automatically maintains older versions of files that are changed." : "Tato aplikace automaticky uchovává starší verze souborů, které se změnily.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Tato aplikace automaticky uchovává starší verze souborů, které se změnily. Když je zapnutá, je ve složce každého uživatele vytvořena skrytá složka pro verze a do ní jsou ukládány staré verze souborů. Uživatel se (prostřednictvím webového rozhraní) kdykoli může vrátit ke starší verzi s tím, že sám nahrazovaný nejnovější soubor se tak stane verzí. Aplikace automaticky spravuje složku s verzemi tak, aby bylo zajištěno, že účet kvůli starým verzím nevyčerpá přidělenou kvótu.\n\t\tKrom konců platností verzí, aplikace Verze zajišťuje, že nikdy nepoužije více než 50% právě dostupného volného prostoru, který má účet k dispozici. Pokud uložené verze přesáhnou tento limit, aplikace smaže ty nejstarší, aby se do tohoto limitu vešla. Podrobnosti naleznete v dokumentaci k aplikaci Verze.",
+ "Current version" : "Stávající verze",
+ "Initial version" : "Počáteční verze",
+ "You" : "Vy",
+ "Actions for version from {versionHumanExplicitDate}" : "Akce pro verzi od {versionHumanExplicitDate}",
+ "Name this version" : "Nazvat tuto verzi",
+ "Edit version name" : "Upravit název verze",
+ "Compare to current version" : "Porovnat se stávající verzí",
+ "Restore version" : "Obnovit verzi",
+ "Download version" : "Stáhnout verzi",
+ "Delete version" : "Smazat verzi",
+ "Cancel" : "Storno",
+ "Remove version name" : "Odebrat název verze",
+ "Save version name" : "Uložit název verze",
+ "Version name" : "Název verze",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Výslovně verze jsou trvalé a vynechány z automatického čištění při vyčerpání vaší kvóty na úložišti.",
+ "Initial version restored" : "Počáteční verze obnovena",
+ "Version restored" : "Verze obnovena",
+ "Could not restore version" : "Verzi se nedaří obnovit",
+ "Could not set version label" : "Nepodařilo se nastavit štítek verze",
+ "Could not delete version" : "Nedaří se smazat verzi",
+ "File versions" : "Verze souborů"
},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/cy_GB.js b/apps/files_versions/l10n/cy_GB.js
deleted file mode 100644
index e5285e2e157..00000000000
--- a/apps/files_versions/l10n/cy_GB.js
+++ /dev/null
@@ -1,6 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Restore" : "Adfer"
-},
-"nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;");
diff --git a/apps/files_versions/l10n/cy_GB.json b/apps/files_versions/l10n/cy_GB.json
deleted file mode 100644
index 5ad23a5ac6f..00000000000
--- a/apps/files_versions/l10n/cy_GB.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{ "translations": {
- "Restore" : "Adfer"
-},"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/apps/files_versions/l10n/da.js b/apps/files_versions/l10n/da.js
index 871cdd31df7..7898c6c27b6 100644
--- a/apps/files_versions/l10n/da.js
+++ b/apps/files_versions/l10n/da.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versioner",
"This application automatically maintains older versions of files that are changed." : "Denne applikation styrer automatisk tidligere versioner af ændrede filer.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denne applikation beholder automatisk ældre versioner af ændrede filer. Når aktiveret, oprettes en skjult mappe i hver brugers folder og bruges til at gemme ældre filversioner. En bruger kan gå tilbage til en ældre version via web brugerfladen til enhver tid. Derved bliver den erstattede fil også en version. Applikationen holder styr på versionsmappen for at sikre at brugeren ikke opbruger sin kvota med versioner.\n\t\tUdover at ugyldiggøre versioner, kontrollerer applikationen også at versioner aldrig optager mere en 50% af brugerens ledige plads. Hvis gemte versioner overskrider denne grænse vil applikationen slette de ældste versioner til den er tilbage under grænsen. Mere information tilgængelig i Versions dokumentationen. ",
- "Failed to revert {file} to revision {timestamp}." : "Kunne ikke tilbagerulle {file} til den tidligere udgave: {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Gendan",
- "No other versions available" : "Ingen andre versioner tilgængelige"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denne applikation vedligeholder automatisk ældre versioner af filer, der ændres. Når den er aktiveret, er der klargjort en skjult versionsmappe i hver brugers mappe, som anvendes til at gemme gamle filversioner. En bruger kan til enhver tid vende tilbage til en ældre version via webgrænsefladen, hvor den erstattede fil bliver til en version. App'en administrerer automatisk versionsmappen for at sikre, at kontoen ikke løber tør for kvote på grund af versioner..\n\t\tUd over udløbet af versioner sørger versionsappen for aldrig at bruge mere end 50 % af kontoens aktuelt ledige plads. Hvis lagrede versioner overskrider denne grænse, så vil app'en først slette de ældste versioner, indtil den når denne grænse. Mere information er tilgængelig i versionsdokumentationen.",
+ "Current version" : "Nuværende version",
+ "Initial version" : "Oprindelig version",
+ "You" : "Dig",
+ "Actions for version from {versionHumanExplicitDate}" : "Handlinger for version fra {versionHumanExplicitDate}",
+ "Name this version" : "Navngiv denne version",
+ "Edit version name" : "Rediger versionsnavn",
+ "Compare to current version" : "Sammenlign med den aktuelle version",
+ "Restore version" : "Gendan version",
+ "Download version" : "Download version",
+ "Delete version" : "Slet version",
+ "Cancel" : "Annuller",
+ "Remove version name" : "Fjern versionsnavn",
+ "Save version name" : "Gem versionsnavn",
+ "Version name" : "Versionsnavn",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Navngivne versioner bevares og udelukkes fra automatiske oprydninger, når din lagerkvote er fuld.",
+ "Initial version restored" : "Første version genoprettet",
+ "Version restored" : "Version genoprettet",
+ "Could not restore version" : "Kunne ikke genoprette version",
+ "Could not set version label" : "Kunne ikke indstille versionslabel",
+ "Could not delete version" : "Kunne ikke slette version",
+ "File versions" : "Fil versioner"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/da.json b/apps/files_versions/l10n/da.json
index 7d4fd8c8131..7da65d1ee3f 100644
--- a/apps/files_versions/l10n/da.json
+++ b/apps/files_versions/l10n/da.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versioner",
"This application automatically maintains older versions of files that are changed." : "Denne applikation styrer automatisk tidligere versioner af ændrede filer.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denne applikation beholder automatisk ældre versioner af ændrede filer. Når aktiveret, oprettes en skjult mappe i hver brugers folder og bruges til at gemme ældre filversioner. En bruger kan gå tilbage til en ældre version via web brugerfladen til enhver tid. Derved bliver den erstattede fil også en version. Applikationen holder styr på versionsmappen for at sikre at brugeren ikke opbruger sin kvota med versioner.\n\t\tUdover at ugyldiggøre versioner, kontrollerer applikationen også at versioner aldrig optager mere en 50% af brugerens ledige plads. Hvis gemte versioner overskrider denne grænse vil applikationen slette de ældste versioner til den er tilbage under grænsen. Mere information tilgængelig i Versions dokumentationen. ",
- "Failed to revert {file} to revision {timestamp}." : "Kunne ikke tilbagerulle {file} til den tidligere udgave: {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Gendan",
- "No other versions available" : "Ingen andre versioner tilgængelige"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denne applikation vedligeholder automatisk ældre versioner af filer, der ændres. Når den er aktiveret, er der klargjort en skjult versionsmappe i hver brugers mappe, som anvendes til at gemme gamle filversioner. En bruger kan til enhver tid vende tilbage til en ældre version via webgrænsefladen, hvor den erstattede fil bliver til en version. App'en administrerer automatisk versionsmappen for at sikre, at kontoen ikke løber tør for kvote på grund af versioner..\n\t\tUd over udløbet af versioner sørger versionsappen for aldrig at bruge mere end 50 % af kontoens aktuelt ledige plads. Hvis lagrede versioner overskrider denne grænse, så vil app'en først slette de ældste versioner, indtil den når denne grænse. Mere information er tilgængelig i versionsdokumentationen.",
+ "Current version" : "Nuværende version",
+ "Initial version" : "Oprindelig version",
+ "You" : "Dig",
+ "Actions for version from {versionHumanExplicitDate}" : "Handlinger for version fra {versionHumanExplicitDate}",
+ "Name this version" : "Navngiv denne version",
+ "Edit version name" : "Rediger versionsnavn",
+ "Compare to current version" : "Sammenlign med den aktuelle version",
+ "Restore version" : "Gendan version",
+ "Download version" : "Download version",
+ "Delete version" : "Slet version",
+ "Cancel" : "Annuller",
+ "Remove version name" : "Fjern versionsnavn",
+ "Save version name" : "Gem versionsnavn",
+ "Version name" : "Versionsnavn",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Navngivne versioner bevares og udelukkes fra automatiske oprydninger, når din lagerkvote er fuld.",
+ "Initial version restored" : "Første version genoprettet",
+ "Version restored" : "Version genoprettet",
+ "Could not restore version" : "Kunne ikke genoprette version",
+ "Could not set version label" : "Kunne ikke indstille versionslabel",
+ "Could not delete version" : "Kunne ikke slette version",
+ "File versions" : "Fil versioner"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/de.js b/apps/files_versions/l10n/de.js
index 3a17d1a6b85..95d5da11277 100644
--- a/apps/files_versions/l10n/de.js
+++ b/apps/files_versions/l10n/de.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versionen",
"This application automatically maintains older versions of files that are changed." : "Diese App verwaltet automatisch ältere Versionen geänderter Dateien.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert werden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Benutzer nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\n\t\tZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Benutzers für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen findest Du in der Versionsdokumentation.",
- "Failed to revert {file} to revision {timestamp}." : "Konnte {file} nicht auf Revision {timestamp} zurücksetzen.",
- "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"],
- "Restore" : "Wiederherstellen",
- "No other versions available" : "Keine anderen Versionen verfügbar"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert wurden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Konto nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\nZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Kontos für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen findest du in der Versionsdokumentation.",
+ "Current version" : "Aktuelle Version",
+ "Initial version" : "Initiale Version",
+ "You" : "Du",
+ "Actions for version from {versionHumanExplicitDate}" : "Aktionen für Version vom {versionHumanExplicitDate}",
+ "Name this version" : "Diese Version benennen",
+ "Edit version name" : "Versionsnamen bearbeiten",
+ "Compare to current version" : "Mit aktueller Version vergleichen",
+ "Restore version" : "Version wiederherstellen",
+ "Download version" : "Version herunterladen",
+ "Delete version" : "Version löschen",
+ "Cancel" : "Abbrechen",
+ "Remove version name" : "Versionsnamen entfernen",
+ "Save version name" : "Versionsnamen speichern",
+ "Version name" : "Versionsname",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Benannte Versionen werden beibehalten und von automatischen Bereinigungen ausgeschlossen, wenn dein Speicherkontingent voll ist.",
+ "Initial version restored" : "Ursprüngliche Version wiederhergestellt",
+ "Version restored" : "Version wiederhergestellt",
+ "Could not restore version" : "Version konnte nicht wiederhergestellt werden",
+ "Could not set version label" : "Der Versionsname konnte nicht festgelegt werden",
+ "Could not delete version" : "Version konnte nicht gelöscht werden",
+ "File versions" : "Dateiversionen"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/de.json b/apps/files_versions/l10n/de.json
index ac5691a9869..28becae635c 100644
--- a/apps/files_versions/l10n/de.json
+++ b/apps/files_versions/l10n/de.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versionen",
"This application automatically maintains older versions of files that are changed." : "Diese App verwaltet automatisch ältere Versionen geänderter Dateien.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert werden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Benutzer nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\n\t\tZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Benutzers für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen findest Du in der Versionsdokumentation.",
- "Failed to revert {file} to revision {timestamp}." : "Konnte {file} nicht auf Revision {timestamp} zurücksetzen.",
- "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"],
- "Restore" : "Wiederherstellen",
- "No other versions available" : "Keine anderen Versionen verfügbar"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert wurden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Konto nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\nZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Kontos für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen findest du in der Versionsdokumentation.",
+ "Current version" : "Aktuelle Version",
+ "Initial version" : "Initiale Version",
+ "You" : "Du",
+ "Actions for version from {versionHumanExplicitDate}" : "Aktionen für Version vom {versionHumanExplicitDate}",
+ "Name this version" : "Diese Version benennen",
+ "Edit version name" : "Versionsnamen bearbeiten",
+ "Compare to current version" : "Mit aktueller Version vergleichen",
+ "Restore version" : "Version wiederherstellen",
+ "Download version" : "Version herunterladen",
+ "Delete version" : "Version löschen",
+ "Cancel" : "Abbrechen",
+ "Remove version name" : "Versionsnamen entfernen",
+ "Save version name" : "Versionsnamen speichern",
+ "Version name" : "Versionsname",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Benannte Versionen werden beibehalten und von automatischen Bereinigungen ausgeschlossen, wenn dein Speicherkontingent voll ist.",
+ "Initial version restored" : "Ursprüngliche Version wiederhergestellt",
+ "Version restored" : "Version wiederhergestellt",
+ "Could not restore version" : "Version konnte nicht wiederhergestellt werden",
+ "Could not set version label" : "Der Versionsname konnte nicht festgelegt werden",
+ "Could not delete version" : "Version konnte nicht gelöscht werden",
+ "File versions" : "Dateiversionen"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/de_DE.js b/apps/files_versions/l10n/de_DE.js
index fae5219acfe..7b290d51b25 100644
--- a/apps/files_versions/l10n/de_DE.js
+++ b/apps/files_versions/l10n/de_DE.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versionen",
"This application automatically maintains older versions of files that are changed." : "Diese App verwaltet automatisch ältere Versionen geänderter Dateien.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert werden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Benutzer nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\nZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Benutzers für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen finden Sie in der Versionsdokumentation.",
- "Failed to revert {file} to revision {timestamp}." : "Konnte {file} nicht auf Revision {timestamp} zurücksetzen.",
- "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"],
- "Restore" : "Wiederherstellen",
- "No other versions available" : "Keine anderen Versionen verfügbar"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert wurden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Konto nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\nZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Kontos für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen finden Sie in der Versionsdokumentation.",
+ "Current version" : "Aktuelle Version",
+ "Initial version" : "Initiale Version",
+ "You" : "Sie",
+ "Actions for version from {versionHumanExplicitDate}" : "Aktionen für Version von {versionHumanExplicitDate}",
+ "Name this version" : "Diese Version benennen",
+ "Edit version name" : "Versionsnamen bearbeiten",
+ "Compare to current version" : "Mit aktueller Version vergleichen",
+ "Restore version" : "Version wiederherstellen",
+ "Download version" : "Version herunterladen",
+ "Delete version" : "Version löschen",
+ "Cancel" : "Abbrechen",
+ "Remove version name" : "Versionsnamen entfernen",
+ "Save version name" : "Versionsnamen speichern",
+ "Version name" : "Versionsname",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Benannte Versionen werden beibehalten und von automatischen Bereinigungen ausgeschlossen, wenn Ihr Speicherkontingent voll ist.",
+ "Initial version restored" : "Ursprüngliche Version wiederhergestellt",
+ "Version restored" : "Version wiederhergestellt",
+ "Could not restore version" : "Version konnte nicht wiederhergestellt werden",
+ "Could not set version label" : "Der Versionsname konnte nicht festgelegt werden",
+ "Could not delete version" : "Version konnte nicht gelöscht werden",
+ "File versions" : "Dateiversionen"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/de_DE.json b/apps/files_versions/l10n/de_DE.json
index fce2d2f5591..e08cc07dfc4 100644
--- a/apps/files_versions/l10n/de_DE.json
+++ b/apps/files_versions/l10n/de_DE.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versionen",
"This application automatically maintains older versions of files that are changed." : "Diese App verwaltet automatisch ältere Versionen geänderter Dateien.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert werden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Benutzer nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\nZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Benutzers für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen finden Sie in der Versionsdokumentation.",
- "Failed to revert {file} to revision {timestamp}." : "Konnte {file} nicht auf Revision {timestamp} zurücksetzen.",
- "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"],
- "Restore" : "Wiederherstellen",
- "No other versions available" : "Keine anderen Versionen verfügbar"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Diese Anwendung verwaltet automatisch ältere Versionen von Dateien, die geändert wurden. Wenn aktiviert, wird ein Ordner mit versteckten Versionen im Verzeichnis jedes Benutzers bereitgestellt und wird zum Speichern alter Dateiversionen verwendet. Ein Benutzer kann jederzeit über die Web-Oberfläche auf eine ältere Version zurückgreifen, wobei die ersetzte Datei dann eine Version wird. Die App verwaltet automatisch den Versionsordner, um sicherzustellen, dass dem Konto nicht der Speicherplatz aufgrund von zu vielen Versionen ausgeht.\nZusätzlich zum Ablauf der Versionen stellt die Versions-App sicher, dass nie mehr als 50% des derzeit verfügbaren freien Speicherplatzes des Kontos für die Versionierung genutzt werden. Wenn gespeicherte Versionen diese Grenze überschreiten, löscht die App zuerst die ältesten Versionen, bis sie die 50% Grenze erreicht hat. Weitere Informationen finden Sie in der Versionsdokumentation.",
+ "Current version" : "Aktuelle Version",
+ "Initial version" : "Initiale Version",
+ "You" : "Sie",
+ "Actions for version from {versionHumanExplicitDate}" : "Aktionen für Version von {versionHumanExplicitDate}",
+ "Name this version" : "Diese Version benennen",
+ "Edit version name" : "Versionsnamen bearbeiten",
+ "Compare to current version" : "Mit aktueller Version vergleichen",
+ "Restore version" : "Version wiederherstellen",
+ "Download version" : "Version herunterladen",
+ "Delete version" : "Version löschen",
+ "Cancel" : "Abbrechen",
+ "Remove version name" : "Versionsnamen entfernen",
+ "Save version name" : "Versionsnamen speichern",
+ "Version name" : "Versionsname",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Benannte Versionen werden beibehalten und von automatischen Bereinigungen ausgeschlossen, wenn Ihr Speicherkontingent voll ist.",
+ "Initial version restored" : "Ursprüngliche Version wiederhergestellt",
+ "Version restored" : "Version wiederhergestellt",
+ "Could not restore version" : "Version konnte nicht wiederhergestellt werden",
+ "Could not set version label" : "Der Versionsname konnte nicht festgelegt werden",
+ "Could not delete version" : "Version konnte nicht gelöscht werden",
+ "File versions" : "Dateiversionen"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/el.js b/apps/files_versions/l10n/el.js
index 64ff4ca86c0..fbe5807376b 100644
--- a/apps/files_versions/l10n/el.js
+++ b/apps/files_versions/l10n/el.js
@@ -3,10 +3,22 @@ OC.L10N.register(
{
"Versions" : "Εκδόσεις",
"This application automatically maintains older versions of files that are changed." : "Η εφαρμογή διατηρεί αυτόματα παλαιότερες εκδόσεις των αρχείων που έχουν αλλάξει.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Αυτή η εφαρμογή διατηρεί αυτόματα παλαιότερες εκδόσεις αρχείων που έχουν αλλάξει. Όταν είναι ενεργοποιημένη, ένας κρυφός φάκελος παλιών εκδόσεων δημιουργείται στον κατάλογο όλων των χρηστών και χρησιμοποιείται για την αποθήκευση παλιών εκδόσεων αρχείων. Ένας χρήστης μπορεί να επαναφέρει παλαιότερη έκδοση μέσω περιηγητή ανά πάσα στιγμή, με το αρχείο αντικατάστασης να γίνει μια έκδοση. Η εφαρμογή διαχειρίζεται αυτόματα τον φάκελο για να διασφαλίσει ότι ο χρήστης δεν εξαντλεί το όριο του λόγω των εκδόσεων.\n\t\tΕκτός από τη λήξη των εκδόσεων, η εφαρμογή για εκδόσεις δεν χρησιμοποιεί ποτέ περισσότερο από το 50% του ελεύθερου χώρου που διαθέτει ο χρήστης. Εάν υπερβεί αυτό το όριο, θα διαγράψει πρώτα τις παλαιότερες εκδόσεις έως ότου ικανοποιήσει το όριο. Περισσότερες πληροφορίες διατίθενται στην τεκμηρίωση εκδόσεων.",
- "Failed to revert {file} to revision {timestamp}." : "Αποτυχία επαναφοράς του {file} στην αναθεώρηση {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bytes","%n bytes"],
- "Restore" : "Επαναφορά",
- "No other versions available" : "Δεν υπάρχουν άλλες εκδόσεις διαθέσιμες"
+ "Current version" : "Τρέχουσα έκδοση",
+ "Initial version" : "Αρχική έκδοση",
+ "You" : "Εσύ",
+ "Name this version" : "Ονομασία αυτής της έκδοσης",
+ "Edit version name" : "Επεξεργασία ονόματος έκδοσης",
+ "Compare to current version" : "Σύγκριση με την τρέχουσα έκδοση",
+ "Restore version" : "Επαναφορά έκδοσης",
+ "Download version" : "Λήψη έκδοσης",
+ "Delete version" : "Διαγραφή έκδοσης",
+ "Cancel" : "Ακύρωση",
+ "Remove version name" : "Αφαίρεση ονόματος έκδοσης",
+ "Save version name" : "Αποθήκευση ονόματος έκδοσης",
+ "Version name" : "Όνομα έκδοσης",
+ "Initial version restored" : "Η αρχική έκδοση επαναφέρθηκε",
+ "Version restored" : "Η έκδοση επαναφέρθηκε",
+ "Could not restore version" : "Δεν ήταν δυνατή η επαναφορά της έκδοσης",
+ "Could not delete version" : "Δεν ήταν δυνατή η διαγραφή της έκδοσης"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/el.json b/apps/files_versions/l10n/el.json
index ecd44b3d73d..490b5b52899 100644
--- a/apps/files_versions/l10n/el.json
+++ b/apps/files_versions/l10n/el.json
@@ -1,10 +1,22 @@
{ "translations": {
"Versions" : "Εκδόσεις",
"This application automatically maintains older versions of files that are changed." : "Η εφαρμογή διατηρεί αυτόματα παλαιότερες εκδόσεις των αρχείων που έχουν αλλάξει.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Αυτή η εφαρμογή διατηρεί αυτόματα παλαιότερες εκδόσεις αρχείων που έχουν αλλάξει. Όταν είναι ενεργοποιημένη, ένας κρυφός φάκελος παλιών εκδόσεων δημιουργείται στον κατάλογο όλων των χρηστών και χρησιμοποιείται για την αποθήκευση παλιών εκδόσεων αρχείων. Ένας χρήστης μπορεί να επαναφέρει παλαιότερη έκδοση μέσω περιηγητή ανά πάσα στιγμή, με το αρχείο αντικατάστασης να γίνει μια έκδοση. Η εφαρμογή διαχειρίζεται αυτόματα τον φάκελο για να διασφαλίσει ότι ο χρήστης δεν εξαντλεί το όριο του λόγω των εκδόσεων.\n\t\tΕκτός από τη λήξη των εκδόσεων, η εφαρμογή για εκδόσεις δεν χρησιμοποιεί ποτέ περισσότερο από το 50% του ελεύθερου χώρου που διαθέτει ο χρήστης. Εάν υπερβεί αυτό το όριο, θα διαγράψει πρώτα τις παλαιότερες εκδόσεις έως ότου ικανοποιήσει το όριο. Περισσότερες πληροφορίες διατίθενται στην τεκμηρίωση εκδόσεων.",
- "Failed to revert {file} to revision {timestamp}." : "Αποτυχία επαναφοράς του {file} στην αναθεώρηση {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bytes","%n bytes"],
- "Restore" : "Επαναφορά",
- "No other versions available" : "Δεν υπάρχουν άλλες εκδόσεις διαθέσιμες"
+ "Current version" : "Τρέχουσα έκδοση",
+ "Initial version" : "Αρχική έκδοση",
+ "You" : "Εσύ",
+ "Name this version" : "Ονομασία αυτής της έκδοσης",
+ "Edit version name" : "Επεξεργασία ονόματος έκδοσης",
+ "Compare to current version" : "Σύγκριση με την τρέχουσα έκδοση",
+ "Restore version" : "Επαναφορά έκδοσης",
+ "Download version" : "Λήψη έκδοσης",
+ "Delete version" : "Διαγραφή έκδοσης",
+ "Cancel" : "Ακύρωση",
+ "Remove version name" : "Αφαίρεση ονόματος έκδοσης",
+ "Save version name" : "Αποθήκευση ονόματος έκδοσης",
+ "Version name" : "Όνομα έκδοσης",
+ "Initial version restored" : "Η αρχική έκδοση επαναφέρθηκε",
+ "Version restored" : "Η έκδοση επαναφέρθηκε",
+ "Could not restore version" : "Δεν ήταν δυνατή η επαναφορά της έκδοσης",
+ "Could not delete version" : "Δεν ήταν δυνατή η διαγραφή της έκδοσης"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/en_GB.js b/apps/files_versions/l10n/en_GB.js
index 9eb863d9d3b..4b5161e3889 100644
--- a/apps/files_versions/l10n/en_GB.js
+++ b/apps/files_versions/l10n/en_GB.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versions",
"This application automatically maintains older versions of files that are changed." : "This application automatically maintains older versions of files that are changed.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation.",
- "Failed to revert {file} to revision {timestamp}." : "Failed to revert {file} to revision {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restore",
- "No other versions available" : "No other versions available"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation.",
+ "Current version" : "Current version",
+ "Initial version" : "Initial version",
+ "You" : "You",
+ "Actions for version from {versionHumanExplicitDate}" : "Actions for version from {versionHumanExplicitDate}",
+ "Name this version" : "Name this version",
+ "Edit version name" : "Edit version name",
+ "Compare to current version" : "Compare to current version",
+ "Restore version" : "Restore version",
+ "Download version" : "Download version",
+ "Delete version" : "Delete version",
+ "Cancel" : "Cancel",
+ "Remove version name" : "Remove version name",
+ "Save version name" : "Save version name",
+ "Version name" : "Version name",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.",
+ "Initial version restored" : "Initial version restored",
+ "Version restored" : "Version restored",
+ "Could not restore version" : "Could not restore version",
+ "Could not set version label" : "Could not set version label",
+ "Could not delete version" : "Could not delete version",
+ "File versions" : "File versions"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/en_GB.json b/apps/files_versions/l10n/en_GB.json
index 9fea2372413..6daff63aade 100644
--- a/apps/files_versions/l10n/en_GB.json
+++ b/apps/files_versions/l10n/en_GB.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versions",
"This application automatically maintains older versions of files that are changed." : "This application automatically maintains older versions of files that are changed.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation.",
- "Failed to revert {file} to revision {timestamp}." : "Failed to revert {file} to revision {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restore",
- "No other versions available" : "No other versions available"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation.",
+ "Current version" : "Current version",
+ "Initial version" : "Initial version",
+ "You" : "You",
+ "Actions for version from {versionHumanExplicitDate}" : "Actions for version from {versionHumanExplicitDate}",
+ "Name this version" : "Name this version",
+ "Edit version name" : "Edit version name",
+ "Compare to current version" : "Compare to current version",
+ "Restore version" : "Restore version",
+ "Download version" : "Download version",
+ "Delete version" : "Delete version",
+ "Cancel" : "Cancel",
+ "Remove version name" : "Remove version name",
+ "Save version name" : "Save version name",
+ "Version name" : "Version name",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.",
+ "Initial version restored" : "Initial version restored",
+ "Version restored" : "Version restored",
+ "Could not restore version" : "Could not restore version",
+ "Could not set version label" : "Could not set version label",
+ "Could not delete version" : "Could not delete version",
+ "File versions" : "File versions"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/eo.js b/apps/files_versions/l10n/eo.js
deleted file mode 100644
index a73c8d577a9..00000000000
--- a/apps/files_versions/l10n/eo.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versioj",
- "This application automatically maintains older versions of files that are changed." : "Tiu ĉi aplikaĵo aŭtomate konservas antaŭajn versiojn de dosieroj, kiuj ŝanĝiĝis.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Tiu ĉi aplikaĵo aŭtomate konservas antaŭajn versiojn de dosieroj, kiuj ŝanĝiĝis. Kiam ĝi estas ebligita, kaŝita dosierujo por enteni versiojn kreiĝas en ĉiu uzantodosierujo kaj uziĝas por konservi la antaŭajn versiojn de dosieroj. Uzanto povas reveni al antaŭa versio pere de la TTT-a fasado iam ajn, kaj la anstataŭigita dosiero iĝas versio. La aplikaĵo aŭtomate observas la versian dosierujon por garantii, ke la uzanto ne transpasu sian kvoton pro troaj versioj.\n\t\tKrom la eksvalidiĝo de versioj, la aplikaĵo neniam uzas pli ol 50 % de la aktuala libera spaco de la uzanto. Se la konservitaj versioj transpasos tiun limon, la aplikaĵo forigos la plej antaŭajn versiojn ĝis atingo de la limo. Pliaj informoj disponeblas en la dokumentaro pri Versioj.",
- "Failed to revert {file} to revision {timestamp}." : "Malsukcesis remeti {file} al la revizio {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajto","%n bajtoj"],
- "Restore" : "Restaŭri",
- "No other versions available" : "Neniu alia versio disponeblas"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/eo.json b/apps/files_versions/l10n/eo.json
deleted file mode 100644
index 40e6345766e..00000000000
--- a/apps/files_versions/l10n/eo.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "Versioj",
- "This application automatically maintains older versions of files that are changed." : "Tiu ĉi aplikaĵo aŭtomate konservas antaŭajn versiojn de dosieroj, kiuj ŝanĝiĝis.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Tiu ĉi aplikaĵo aŭtomate konservas antaŭajn versiojn de dosieroj, kiuj ŝanĝiĝis. Kiam ĝi estas ebligita, kaŝita dosierujo por enteni versiojn kreiĝas en ĉiu uzantodosierujo kaj uziĝas por konservi la antaŭajn versiojn de dosieroj. Uzanto povas reveni al antaŭa versio pere de la TTT-a fasado iam ajn, kaj la anstataŭigita dosiero iĝas versio. La aplikaĵo aŭtomate observas la versian dosierujon por garantii, ke la uzanto ne transpasu sian kvoton pro troaj versioj.\n\t\tKrom la eksvalidiĝo de versioj, la aplikaĵo neniam uzas pli ol 50 % de la aktuala libera spaco de la uzanto. Se la konservitaj versioj transpasos tiun limon, la aplikaĵo forigos la plej antaŭajn versiojn ĝis atingo de la limo. Pliaj informoj disponeblas en la dokumentaro pri Versioj.",
- "Failed to revert {file} to revision {timestamp}." : "Malsukcesis remeti {file} al la revizio {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajto","%n bajtoj"],
- "Restore" : "Restaŭri",
- "No other versions available" : "Neniu alia versio disponeblas"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es.js b/apps/files_versions/l10n/es.js
index 50de64a4e2d..0daaa820510 100644
--- a/apps/files_versions/l10n/es.js
+++ b/apps/files_versions/l10n/es.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versiones",
"This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\n\n\t\tAdemás de la caducidad de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.",
- "Failed to revert {file} to revision {timestamp}." : "No se ha podido restaurar {file} a versión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Recuperar",
- "No other versions available" : "No hay más versiones disponibles"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Cuando se activa, una carpeta escondida de versiones aparece en cada directorio del usuario y se usa para almacenar los archivos de versiones antiguas. Un usuario puede volver a una versión más antigua a través de la interfaz web en cualquier momento, convirtiéndose el archivo reemplazado en una versión. La app controla automáticamente la carpeta de versiones para asegurarse de que la cuenta no se queda sin cuota de disco por las versiones.\n\t\tAdemás de administrar la caducidad de las versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para el usuario. Si las versiones almacenadas exceden este límite, la app borrará primero las versiones más viejas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.",
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Usted",
+ "Actions for version from {versionHumanExplicitDate}" : "Acciones para la versión de {versionHumanExplicitDate}",
+ "Name this version" : "Nombrar esta versión",
+ "Edit version name" : "Editar nombre de versión",
+ "Compare to current version" : "Comparar con la versión actual",
+ "Restore version" : "Restaurar versión",
+ "Download version" : "Descargar versión",
+ "Delete version" : "Eliminar versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Quitar nombre de versión",
+ "Save version name" : "Guardar nombre de versión",
+ "Version name" : "Nombre de versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Las versiones nombradas son persistidas, y, son excluidas de las limpiezas automáticas cuando su cuota de almacenamiento está al límite.",
+ "Initial version restored" : "Versión inicial restaurada",
+ "Version restored" : "Versión restaurada",
+ "Could not restore version" : "No se ha podido restaurar la versión",
+ "Could not set version label" : "No se pudo establecer la etiqueta de la versión",
+ "Could not delete version" : "No se ha podido eliminar la versión",
+ "File versions" : "Versiones de archivo"
},
-"nplurals=2; plural=(n != 1);");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/files_versions/l10n/es.json b/apps/files_versions/l10n/es.json
index 21403922f96..28ab4a7611c 100644
--- a/apps/files_versions/l10n/es.json
+++ b/apps/files_versions/l10n/es.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versiones",
"This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Al activarse, se crea una carpeta oculta de versiones que se usa para almacenar versiones antiguas de archivos. Un usuario puede volver a una versión anterior a través de la interfaz web en cualquier momento, con el archivo reemplazado convirtiéndose en una versión. La app maneja automáticamente la carpeta de versiones para asegurarse de que el usuario no se queda sin espacio debido a las versiones.\n\n\t\tAdemás de la caducidad de versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para un usuario. Si las versiones almacenadas exceden este límite, la app borrará las versiones más antiguas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.",
- "Failed to revert {file} to revision {timestamp}." : "No se ha podido restaurar {file} a versión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Recuperar",
- "No other versions available" : "No hay más versiones disponibles"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones antiguas de los archivos que cambian. Cuando se activa, una carpeta escondida de versiones aparece en cada directorio del usuario y se usa para almacenar los archivos de versiones antiguas. Un usuario puede volver a una versión más antigua a través de la interfaz web en cualquier momento, convirtiéndose el archivo reemplazado en una versión. La app controla automáticamente la carpeta de versiones para asegurarse de que la cuenta no se queda sin cuota de disco por las versiones.\n\t\tAdemás de administrar la caducidad de las versiones, la app de versiones se asegura de no usar nunca más del 50% del espacio libre actualmente disponible para el usuario. Si las versiones almacenadas exceden este límite, la app borrará primero las versiones más viejas hasta alcanzar este límite. Más información disponible en la documentación de Versiones.",
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Usted",
+ "Actions for version from {versionHumanExplicitDate}" : "Acciones para la versión de {versionHumanExplicitDate}",
+ "Name this version" : "Nombrar esta versión",
+ "Edit version name" : "Editar nombre de versión",
+ "Compare to current version" : "Comparar con la versión actual",
+ "Restore version" : "Restaurar versión",
+ "Download version" : "Descargar versión",
+ "Delete version" : "Eliminar versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Quitar nombre de versión",
+ "Save version name" : "Guardar nombre de versión",
+ "Version name" : "Nombre de versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Las versiones nombradas son persistidas, y, son excluidas de las limpiezas automáticas cuando su cuota de almacenamiento está al límite.",
+ "Initial version restored" : "Versión inicial restaurada",
+ "Version restored" : "Versión restaurada",
+ "Could not restore version" : "No se ha podido restaurar la versión",
+ "Could not set version label" : "No se pudo establecer la etiqueta de la versión",
+ "Could not delete version" : "No se ha podido eliminar la versión",
+ "File versions" : "Versiones de archivo"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_419.js b/apps/files_versions/l10n/es_419.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_419.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_419.json b/apps/files_versions/l10n/es_419.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_419.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_AR.js b/apps/files_versions/l10n/es_AR.js
deleted file mode 100644
index 0bc990ac761..00000000000
--- a/apps/files_versions/l10n/es_AR.js
+++ /dev/null
@@ -1,10 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {archivo} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "No hay más versiones disponibles"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_AR.json b/apps/files_versions/l10n/es_AR.json
deleted file mode 100644
index 5b43b502dbe..00000000000
--- a/apps/files_versions/l10n/es_AR.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {archivo} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "No hay más versiones disponibles"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_CL.js b/apps/files_versions/l10n/es_CL.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_CL.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_CL.json b/apps/files_versions/l10n/es_CL.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_CL.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_CO.js b/apps/files_versions/l10n/es_CO.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_CO.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_CO.json b/apps/files_versions/l10n/es_CO.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_CO.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_CR.js b/apps/files_versions/l10n/es_CR.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_CR.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_CR.json b/apps/files_versions/l10n/es_CR.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_CR.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_DO.js b/apps/files_versions/l10n/es_DO.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_DO.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_DO.json b/apps/files_versions/l10n/es_DO.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_DO.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_EC.js b/apps/files_versions/l10n/es_EC.js
index 666456535e9..bcca68dd065 100644
--- a/apps/files_versions/l10n/es_EC.js
+++ b/apps/files_versions/l10n/es_EC.js
@@ -2,8 +2,21 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
+ "This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones anteriores de los archivos que son modificados.",
+ "Current version" : "Versión actual",
+ "Name this version" : "Nombrar esta versión",
+ "Edit version name" : "Editar nombre de versión",
+ "Restore version" : "Restaurar versión",
+ "Download version" : "Descargar versión",
+ "Delete version" : "Eliminar versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Eliminar nombre de versión",
+ "Save version name" : "Guardar nombre de versión",
+ "Version name" : "Nombre de la versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Las versiones con nombre se conservan y se excluyen de las limpiezas automáticas cuando tu cuota de almacenamiento está llena.",
+ "Initial version restored" : "Versión inicial restaurada",
+ "Version restored" : "Versión restaurada",
+ "Could not restore version" : "No se pudo restaurar la versión",
+ "Could not delete version" : "No se pudo eliminar la versión"
},
-"nplurals=2; plural=(n != 1);");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/files_versions/l10n/es_EC.json b/apps/files_versions/l10n/es_EC.json
index 35cc22a46e3..46097bb89d6 100644
--- a/apps/files_versions/l10n/es_EC.json
+++ b/apps/files_versions/l10n/es_EC.json
@@ -1,7 +1,20 @@
{ "translations": {
"Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
+ "This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones anteriores de los archivos que son modificados.",
+ "Current version" : "Versión actual",
+ "Name this version" : "Nombrar esta versión",
+ "Edit version name" : "Editar nombre de versión",
+ "Restore version" : "Restaurar versión",
+ "Download version" : "Descargar versión",
+ "Delete version" : "Eliminar versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Eliminar nombre de versión",
+ "Save version name" : "Guardar nombre de versión",
+ "Version name" : "Nombre de la versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Las versiones con nombre se conservan y se excluyen de las limpiezas automáticas cuando tu cuota de almacenamiento está llena.",
+ "Initial version restored" : "Versión inicial restaurada",
+ "Version restored" : "Versión restaurada",
+ "Could not restore version" : "No se pudo restaurar la versión",
+ "Could not delete version" : "No se pudo eliminar la versión"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_GT.js b/apps/files_versions/l10n/es_GT.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_GT.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_GT.json b/apps/files_versions/l10n/es_GT.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_GT.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_HN.js b/apps/files_versions/l10n/es_HN.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_HN.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_HN.json b/apps/files_versions/l10n/es_HN.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_HN.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_MX.js b/apps/files_versions/l10n/es_MX.js
index 37c011ddfd2..67683cc4967 100644
--- a/apps/files_versions/l10n/es_MX.js
+++ b/apps/files_versions/l10n/es_MX.js
@@ -3,10 +3,24 @@ OC.L10N.register(
{
"Versions" : "Versiones",
"This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones anteriores de archivos que fueron cambiados. ",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones anteriores de los archivos que se cambian. Al habilitarse, una carpeta oculata de versiones de archivos se aprovisiona en cada directorio del usuario y se usa para almacenar las versiones anteriores de los archivos. Un usuario puede regresar a una versión anterior mediante al interfaz web en cualquier momento, el archivo reemplazado se convierte en una versión. La aplicación administra automáticamente la carpeta de versiones para asegurar que el usuario no agote su Cuota con estas versiones. \n\t\tAdicionalmente a la expiración de las versiones, la aplicación de versiones se asegura de nunca usar mas del 50% del espacio actualmente disponible del usuario. Si las versiones almacenadas exceden este límite, la aplicación borrará las versiones más antiguas hasta que se llegue dentro de este límite. Más información está disponible en la documentacion de Versiones. ",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "No hay otras versiones disponibles"
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Usted",
+ "Name this version" : "Nombrar esta versión",
+ "Edit version name" : "Editar el nombre de la versión",
+ "Compare to current version" : "Comparar con la versión actual",
+ "Restore version" : "Restaurar versión",
+ "Download version" : "Descargar versión",
+ "Delete version" : "Eliminar versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Eliminar el nombre de la versión",
+ "Save version name" : "Guardar el nombre de la versión",
+ "Version name" : "Nombre de la versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Las versiones con nombre se conservan y se excluyen de las limpiezas automáticas cuando su cuota de almacenamiento alcanzó el límite.",
+ "Initial version restored" : "Versión inicial restaurada",
+ "Version restored" : "Versión restaurada",
+ "Could not restore version" : "No se pudo restaurar la versión",
+ "Could not set version label" : "No se pudo establecer la etiqueta de la versión",
+ "Could not delete version" : "No se pudo eliminar la versión"
},
-"nplurals=2; plural=(n != 1);");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/files_versions/l10n/es_MX.json b/apps/files_versions/l10n/es_MX.json
index 841c01df4ca..403db393aaf 100644
--- a/apps/files_versions/l10n/es_MX.json
+++ b/apps/files_versions/l10n/es_MX.json
@@ -1,10 +1,24 @@
{ "translations": {
"Versions" : "Versiones",
"This application automatically maintains older versions of files that are changed." : "Esta aplicación mantiene automáticamente versiones anteriores de archivos que fueron cambiados. ",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantiene automáticamente versiones anteriores de los archivos que se cambian. Al habilitarse, una carpeta oculata de versiones de archivos se aprovisiona en cada directorio del usuario y se usa para almacenar las versiones anteriores de los archivos. Un usuario puede regresar a una versión anterior mediante al interfaz web en cualquier momento, el archivo reemplazado se convierte en una versión. La aplicación administra automáticamente la carpeta de versiones para asegurar que el usuario no agote su Cuota con estas versiones. \n\t\tAdicionalmente a la expiración de las versiones, la aplicación de versiones se asegura de nunca usar mas del 50% del espacio actualmente disponible del usuario. Si las versiones almacenadas exceden este límite, la aplicación borrará las versiones más antiguas hasta que se llegue dentro de este límite. Más información está disponible en la documentacion de Versiones. ",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "No hay otras versiones disponibles"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Usted",
+ "Name this version" : "Nombrar esta versión",
+ "Edit version name" : "Editar el nombre de la versión",
+ "Compare to current version" : "Comparar con la versión actual",
+ "Restore version" : "Restaurar versión",
+ "Download version" : "Descargar versión",
+ "Delete version" : "Eliminar versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Eliminar el nombre de la versión",
+ "Save version name" : "Guardar el nombre de la versión",
+ "Version name" : "Nombre de la versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Las versiones con nombre se conservan y se excluyen de las limpiezas automáticas cuando su cuota de almacenamiento alcanzó el límite.",
+ "Initial version restored" : "Versión inicial restaurada",
+ "Version restored" : "Versión restaurada",
+ "Could not restore version" : "No se pudo restaurar la versión",
+ "Could not set version label" : "No se pudo establecer la etiqueta de la versión",
+ "Could not delete version" : "No se pudo eliminar la versión"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_NI.js b/apps/files_versions/l10n/es_NI.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_NI.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_NI.json b/apps/files_versions/l10n/es_NI.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_NI.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_PA.js b/apps/files_versions/l10n/es_PA.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_PA.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_PA.json b/apps/files_versions/l10n/es_PA.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_PA.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_PE.js b/apps/files_versions/l10n/es_PE.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_PE.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_PE.json b/apps/files_versions/l10n/es_PE.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_PE.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_PR.js b/apps/files_versions/l10n/es_PR.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_PR.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_PR.json b/apps/files_versions/l10n/es_PR.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_PR.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_PY.js b/apps/files_versions/l10n/es_PY.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_PY.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_PY.json b/apps/files_versions/l10n/es_PY.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_PY.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_SV.js b/apps/files_versions/l10n/es_SV.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_SV.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_SV.json b/apps/files_versions/l10n/es_SV.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_SV.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/es_UY.js b/apps/files_versions/l10n/es_UY.js
deleted file mode 100644
index 666456535e9..00000000000
--- a/apps/files_versions/l10n/es_UY.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/es_UY.json b/apps/files_versions/l10n/es_UY.json
deleted file mode 100644
index 35cc22a46e3..00000000000
--- a/apps/files_versions/l10n/es_UY.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Falla al revertir {file} a revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/et_EE.js b/apps/files_versions/l10n/et_EE.js
index cd319314826..dadd03d14dc 100644
--- a/apps/files_versions/l10n/et_EE.js
+++ b/apps/files_versions/l10n/et_EE.js
@@ -2,9 +2,28 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "Versioonid",
- "Failed to revert {file} to revision {timestamp}." : "Ebaõnnestus faili {file} taastamine revisjonile {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n bait","%n baiti"],
- "Restore" : "Taasta",
- "No other versions available" : "Muid versioone pole saadaval"
+ "This application automatically maintains older versions of files that are changed." : "See rakendus haldab automaatselt muudetud failide vanemaid versioone.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "See rakendus säilitab automaatselt muudetud failide vanemaid versioone. Kui see on lubatud, luuakse iga kasutaja kataloogis peidetud versioonide kaust ja seda kasutatakse vanade failiversioonide salvestamiseks. Kasutaja saab veebiliidese kaudu igal ajal naasta vanemale versioonile, kusjuures asendatud failist saab versioon. Rakendus haldab automaatselt versioonide kausta, et kontol kvoot versioonide tõttu otsa ei saaks.\nLisaks versioonide aegumisele tagab versioonirakendus, et ei kasutataks kunagi rohkem kui 50% konto hetkel saadaolevast vabast ruumist. Kui salvestatud versioonid ületavad selle limiidi, kustutab rakendus kõigepealt vanimad versioonid, kuni see limiit jõuab. Lisateavet leiate versioonide dokumentatsioonist.",
+ "Current version" : "Hetkeversioon",
+ "Initial version" : "Algversioon",
+ "You" : "Sina",
+ "Actions for version from {versionHumanExplicitDate}" : "Tegevused versiooniga {versionHumanExplicitDate}-st",
+ "Name this version" : "Nimeta see versioon",
+ "Edit version name" : "Muuda versiooni nime",
+ "Compare to current version" : "Võrdle hetkeversiooniga",
+ "Restore version" : "Taasta versioon",
+ "Download version" : "Laadi versioon alla",
+ "Delete version" : "Kustuta versioon",
+ "Cancel" : "Tühista",
+ "Remove version name" : "Eemalda versiooni nimi",
+ "Save version name" : "Salvesta versiooni nimi",
+ "Version name" : "Versiooni nimi",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Nimelised versioonid hoitakse alles ja ei kustutata automaatselt, kui salvestusruum on täis.",
+ "Initial version restored" : "Algne versioon taastatud",
+ "Version restored" : "Versioon taastatud",
+ "Could not restore version" : "Versiooni taastamine ebaõnnestus",
+ "Could not set version label" : "Ei saanud määrata versiooni märget",
+ "Could not delete version" : "Versiooni kustutamine ebaõnnestus",
+ "File versions" : "Faili versioonid"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/et_EE.json b/apps/files_versions/l10n/et_EE.json
index 720b062759a..d2b4f6170f7 100644
--- a/apps/files_versions/l10n/et_EE.json
+++ b/apps/files_versions/l10n/et_EE.json
@@ -1,8 +1,27 @@
{ "translations": {
"Versions" : "Versioonid",
- "Failed to revert {file} to revision {timestamp}." : "Ebaõnnestus faili {file} taastamine revisjonile {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n bait","%n baiti"],
- "Restore" : "Taasta",
- "No other versions available" : "Muid versioone pole saadaval"
+ "This application automatically maintains older versions of files that are changed." : "See rakendus haldab automaatselt muudetud failide vanemaid versioone.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "See rakendus säilitab automaatselt muudetud failide vanemaid versioone. Kui see on lubatud, luuakse iga kasutaja kataloogis peidetud versioonide kaust ja seda kasutatakse vanade failiversioonide salvestamiseks. Kasutaja saab veebiliidese kaudu igal ajal naasta vanemale versioonile, kusjuures asendatud failist saab versioon. Rakendus haldab automaatselt versioonide kausta, et kontol kvoot versioonide tõttu otsa ei saaks.\nLisaks versioonide aegumisele tagab versioonirakendus, et ei kasutataks kunagi rohkem kui 50% konto hetkel saadaolevast vabast ruumist. Kui salvestatud versioonid ületavad selle limiidi, kustutab rakendus kõigepealt vanimad versioonid, kuni see limiit jõuab. Lisateavet leiate versioonide dokumentatsioonist.",
+ "Current version" : "Hetkeversioon",
+ "Initial version" : "Algversioon",
+ "You" : "Sina",
+ "Actions for version from {versionHumanExplicitDate}" : "Tegevused versiooniga {versionHumanExplicitDate}-st",
+ "Name this version" : "Nimeta see versioon",
+ "Edit version name" : "Muuda versiooni nime",
+ "Compare to current version" : "Võrdle hetkeversiooniga",
+ "Restore version" : "Taasta versioon",
+ "Download version" : "Laadi versioon alla",
+ "Delete version" : "Kustuta versioon",
+ "Cancel" : "Tühista",
+ "Remove version name" : "Eemalda versiooni nimi",
+ "Save version name" : "Salvesta versiooni nimi",
+ "Version name" : "Versiooni nimi",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Nimelised versioonid hoitakse alles ja ei kustutata automaatselt, kui salvestusruum on täis.",
+ "Initial version restored" : "Algne versioon taastatud",
+ "Version restored" : "Versioon taastatud",
+ "Could not restore version" : "Versiooni taastamine ebaõnnestus",
+ "Could not set version label" : "Ei saanud määrata versiooni märget",
+ "Could not delete version" : "Versiooni kustutamine ebaõnnestus",
+ "File versions" : "Faili versioonid"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/eu.js b/apps/files_versions/l10n/eu.js
index 20592d858b7..76e0383e4c8 100644
--- a/apps/files_versions/l10n/eu.js
+++ b/apps/files_versions/l10n/eu.js
@@ -2,11 +2,27 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "Bertsioak",
- "This application automatically maintains older versions of files that are changed." : "Aplikazio honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Fitxategi honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu. Aktibatzen denean, bertsioen karpeta ezkutu bat sortzen da erabiltzailearen karpeta barruan eta bertan gordetzen dira bertsio zaharrak. Erabiltzailek edozein bertsio zaharrera itzultzea erabaki dezake web interfazea erabiliz eta ordezkatutako fitxategiak ere beste bertsio bat sortuko du. Aplikazio honek bertsioen karpeta automatikoki kudeatzen du erabiltzaileak bertsioengatik mugarik gainditu ez dezan.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazio honek erabiltzailearen toki libre guztiaren %50 baino gehiago ez erabiltzea bermatzen du. Gordetako bertsioek muga hori gainditzen badut, aplikazioak bertsio zaharrenak ezabatuko ditu muga bete arte. Informazio gehiago lortzeko aplikazioaren dokumentazioa irakurri dezakezu.",
- "Failed to revert {file} to revision {timestamp}." : "Errore bat izan da {fitxategia} {timestamp} bertsiora leheneratzean.",
- "_%n byte_::_%n bytes_" : ["%nbyte","%n bytes"],
- "Restore" : "Berrezarri",
- "No other versions available" : "Ez dago bertsio gehiago eskuragarri"
+ "This application automatically maintains older versions of files that are changed." : "Aplikazio honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu automatikoki.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikazio honek automatikoki mantentzen ditu aldatzen diren fitxategien bertsio zaharragoak. Gaituta dagoenean, ezkutuko bertsioen karpeta batez hornitzen da erabiltzaile bakoitzaren direktorioa, fitxategien bertsio zaharrak gordetzeko. Erabiltzaileak edozein unetan bertsio zaharrago batera leheneratu dezake web interfazearen bidez, ordeztutako fitxategia bertsio bihurtuz. Aplikazioak automatikoki kudeatzen du bertsioen karpeta, erabiltzailea bertsioak direla eta kuotarik gabe geratuko ez dela ziurtatzeko.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazioak ziurtatzen du ez dela inoiz erabiliko kontuaren uneko espazio librearen %50 baino gehiago. Biltegiratutako bertsioek muga hori gainditzen badute, aplikazioak bertsio zaharrenak ezabatuko ditu, mugara jaitsi arte. Informazio gehiago dago eskuragarri bertsioen dokumentazioan.",
+ "Current version" : "Uneko bertsioa",
+ "Initial version" : "Hasierako bertsioa",
+ "You" : "Zu ",
+ "Actions for version from {versionHumanExplicitDate}" : "Bertsiorako ekintzak {versionHumanExplicitDate}(e)tik",
+ "Name this version" : "Eman izena bertsio honi",
+ "Edit version name" : "Editatu bertsioaren izena",
+ "Compare to current version" : "Konparatu uneko bertsioarekin",
+ "Restore version" : "Leheneratu bertsioa",
+ "Download version" : "Deskargatu bertsioa",
+ "Delete version" : "Ezabatu bertsioa",
+ "Cancel" : "Utzi",
+ "Remove version name" : "Kendu bertsioaren izena",
+ "Save version name" : "Gorde bertsioaren izena",
+ "Version name" : "Bertsioaren izena",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Izendatutako bertsioak mantentzen dira eta garbiketa automatikoetatik kanpo geratzen dira biltegiratze-kuota beteta dagoenean.",
+ "Initial version restored" : "Hasierako bertsioa ondo leheneratu da",
+ "Version restored" : "Bertsioa leheneratu da",
+ "Could not restore version" : "Ezin izan da bertsioa leheneratu",
+ "Could not set version label" : "Ezin izan da bertsio etiketa ezarri",
+ "Could not delete version" : "Ezin izan da bertsioa ezabatu"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/eu.json b/apps/files_versions/l10n/eu.json
index 03afaa4ca64..59421f36b36 100644
--- a/apps/files_versions/l10n/eu.json
+++ b/apps/files_versions/l10n/eu.json
@@ -1,10 +1,26 @@
{ "translations": {
"Versions" : "Bertsioak",
- "This application automatically maintains older versions of files that are changed." : "Aplikazio honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Fitxategi honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu. Aktibatzen denean, bertsioen karpeta ezkutu bat sortzen da erabiltzailearen karpeta barruan eta bertan gordetzen dira bertsio zaharrak. Erabiltzailek edozein bertsio zaharrera itzultzea erabaki dezake web interfazea erabiliz eta ordezkatutako fitxategiak ere beste bertsio bat sortuko du. Aplikazio honek bertsioen karpeta automatikoki kudeatzen du erabiltzaileak bertsioengatik mugarik gainditu ez dezan.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazio honek erabiltzailearen toki libre guztiaren %50 baino gehiago ez erabiltzea bermatzen du. Gordetako bertsioek muga hori gainditzen badut, aplikazioak bertsio zaharrenak ezabatuko ditu muga bete arte. Informazio gehiago lortzeko aplikazioaren dokumentazioa irakurri dezakezu.",
- "Failed to revert {file} to revision {timestamp}." : "Errore bat izan da {fitxategia} {timestamp} bertsiora leheneratzean.",
- "_%n byte_::_%n bytes_" : ["%nbyte","%n bytes"],
- "Restore" : "Berrezarri",
- "No other versions available" : "Ez dago bertsio gehiago eskuragarri"
+ "This application automatically maintains older versions of files that are changed." : "Aplikazio honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu automatikoki.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikazio honek automatikoki mantentzen ditu aldatzen diren fitxategien bertsio zaharragoak. Gaituta dagoenean, ezkutuko bertsioen karpeta batez hornitzen da erabiltzaile bakoitzaren direktorioa, fitxategien bertsio zaharrak gordetzeko. Erabiltzaileak edozein unetan bertsio zaharrago batera leheneratu dezake web interfazearen bidez, ordeztutako fitxategia bertsio bihurtuz. Aplikazioak automatikoki kudeatzen du bertsioen karpeta, erabiltzailea bertsioak direla eta kuotarik gabe geratuko ez dela ziurtatzeko.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazioak ziurtatzen du ez dela inoiz erabiliko kontuaren uneko espazio librearen %50 baino gehiago. Biltegiratutako bertsioek muga hori gainditzen badute, aplikazioak bertsio zaharrenak ezabatuko ditu, mugara jaitsi arte. Informazio gehiago dago eskuragarri bertsioen dokumentazioan.",
+ "Current version" : "Uneko bertsioa",
+ "Initial version" : "Hasierako bertsioa",
+ "You" : "Zu ",
+ "Actions for version from {versionHumanExplicitDate}" : "Bertsiorako ekintzak {versionHumanExplicitDate}(e)tik",
+ "Name this version" : "Eman izena bertsio honi",
+ "Edit version name" : "Editatu bertsioaren izena",
+ "Compare to current version" : "Konparatu uneko bertsioarekin",
+ "Restore version" : "Leheneratu bertsioa",
+ "Download version" : "Deskargatu bertsioa",
+ "Delete version" : "Ezabatu bertsioa",
+ "Cancel" : "Utzi",
+ "Remove version name" : "Kendu bertsioaren izena",
+ "Save version name" : "Gorde bertsioaren izena",
+ "Version name" : "Bertsioaren izena",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Izendatutako bertsioak mantentzen dira eta garbiketa automatikoetatik kanpo geratzen dira biltegiratze-kuota beteta dagoenean.",
+ "Initial version restored" : "Hasierako bertsioa ondo leheneratu da",
+ "Version restored" : "Bertsioa leheneratu da",
+ "Could not restore version" : "Ezin izan da bertsioa leheneratu",
+ "Could not set version label" : "Ezin izan da bertsio etiketa ezarri",
+ "Could not delete version" : "Ezin izan da bertsioa ezabatu"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/fa.js b/apps/files_versions/l10n/fa.js
index 99f208407cd..6f50077efdc 100644
--- a/apps/files_versions/l10n/fa.js
+++ b/apps/files_versions/l10n/fa.js
@@ -3,10 +3,22 @@ OC.L10N.register(
{
"Versions" : "نسخه ها",
"This application automatically maintains older versions of files that are changed." : "این برنامه به طور خودکار نسخه های قدیمی تر پرونده های تغییر یافته را حفظ می کند.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "این برنامه به طور خودکار نسخه های قدیمی تر پرونده های تغییر یافته را حفظ می کند. با فعال کردن ، یک پوشه نسخه پنهان در فهرست کاربر هر کاربر ارائه می شود و از آن برای ذخیره نسخه های قدیمی فایل استفاده می شود. کاربر می تواند در هر زمان به نسخه قدیمی تر از طریق رابط وب برگردد ، با این که پرونده جایگزین به نسخه تبدیل شود. این برنامه به طور خودکار پوشه نسخه ها را کنترل می کند تا اطمینان حاصل کند کاربر به دلیل نسخه ها از Quota تمام نمی شود.\nعلاوه بر انقضاء نسخه ها ، برنامه نسخه ها باعث می شود که هرگز از بیش از 50٪ از فضای رایگان فعلی کاربر استفاده نکنید. اگر نسخه های ذخیره شده از این حد فراتر رود ، برنامه ابتدا قدیمی ترین نسخه ها را حذف می کند تا اینکه این حد را برآورده کند. اطلاعات بیشتر در مستندات Versions موجود است.",
- "Failed to revert {file} to revision {timestamp}." : "برگرداندن {file} به نسخه {timestamp} با شکست روبرو شد",
- "_%n byte_::_%n bytes_" : ["%n بایت","%n بایت"],
- "Restore" : "بازیابی",
- "No other versions available" : "نسخه ی دیگری در دسترس نیست"
+ "Current version" : "نسخه فعلی",
+ "You" : "You",
+ "Name this version" : "Name this version",
+ "Edit version name" : "Edit version name",
+ "Compare to current version" : "Compare to current version",
+ "Restore version" : "Restore version",
+ "Download version" : "Download version",
+ "Delete version" : "Delete version",
+ "Cancel" : "منصرف شدن",
+ "Remove version name" : "Remove version name",
+ "Save version name" : "Save version name",
+ "Version name" : "Version name",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.",
+ "Initial version restored" : "Initial version restored",
+ "Version restored" : "Version restored",
+ "Could not restore version" : "Could not restore version",
+ "Could not delete version" : "Could not delete version"
},
"nplurals=2; plural=(n > 1);");
diff --git a/apps/files_versions/l10n/fa.json b/apps/files_versions/l10n/fa.json
index 1f9943ae85a..a96d8d4cd31 100644
--- a/apps/files_versions/l10n/fa.json
+++ b/apps/files_versions/l10n/fa.json
@@ -1,10 +1,22 @@
{ "translations": {
"Versions" : "نسخه ها",
"This application automatically maintains older versions of files that are changed." : "این برنامه به طور خودکار نسخه های قدیمی تر پرونده های تغییر یافته را حفظ می کند.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "این برنامه به طور خودکار نسخه های قدیمی تر پرونده های تغییر یافته را حفظ می کند. با فعال کردن ، یک پوشه نسخه پنهان در فهرست کاربر هر کاربر ارائه می شود و از آن برای ذخیره نسخه های قدیمی فایل استفاده می شود. کاربر می تواند در هر زمان به نسخه قدیمی تر از طریق رابط وب برگردد ، با این که پرونده جایگزین به نسخه تبدیل شود. این برنامه به طور خودکار پوشه نسخه ها را کنترل می کند تا اطمینان حاصل کند کاربر به دلیل نسخه ها از Quota تمام نمی شود.\nعلاوه بر انقضاء نسخه ها ، برنامه نسخه ها باعث می شود که هرگز از بیش از 50٪ از فضای رایگان فعلی کاربر استفاده نکنید. اگر نسخه های ذخیره شده از این حد فراتر رود ، برنامه ابتدا قدیمی ترین نسخه ها را حذف می کند تا اینکه این حد را برآورده کند. اطلاعات بیشتر در مستندات Versions موجود است.",
- "Failed to revert {file} to revision {timestamp}." : "برگرداندن {file} به نسخه {timestamp} با شکست روبرو شد",
- "_%n byte_::_%n bytes_" : ["%n بایت","%n بایت"],
- "Restore" : "بازیابی",
- "No other versions available" : "نسخه ی دیگری در دسترس نیست"
+ "Current version" : "نسخه فعلی",
+ "You" : "You",
+ "Name this version" : "Name this version",
+ "Edit version name" : "Edit version name",
+ "Compare to current version" : "Compare to current version",
+ "Restore version" : "Restore version",
+ "Download version" : "Download version",
+ "Delete version" : "Delete version",
+ "Cancel" : "منصرف شدن",
+ "Remove version name" : "Remove version name",
+ "Save version name" : "Save version name",
+ "Version name" : "Version name",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.",
+ "Initial version restored" : "Initial version restored",
+ "Version restored" : "Version restored",
+ "Could not restore version" : "Could not restore version",
+ "Could not delete version" : "Could not delete version"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/fi.js b/apps/files_versions/l10n/fi.js
index 36fa9a660dc..62682858796 100644
--- a/apps/files_versions/l10n/fi.js
+++ b/apps/files_versions/l10n/fi.js
@@ -3,9 +3,23 @@ OC.L10N.register(
{
"Versions" : "Versiot",
"This application automatically maintains older versions of files that are changed." : "Tämä sovellus säilyttää automaattisesti vanhempia versioita muuttuneista tiedostoista.",
- "Failed to revert {file} to revision {timestamp}." : "Tiedoston {file} palautus versioon {timestamp} epäonnistui.",
- "_%n byte_::_%n bytes_" : ["%n tavu","%n tavua"],
- "Restore" : "Palauta",
- "No other versions available" : "Ei muita versioita saatavilla"
+ "Current version" : "Nykyinen versio",
+ "Initial version" : "Ensimmäinen versio",
+ "You" : "Sinä",
+ "Name this version" : "Nimeä tämä versio",
+ "Edit version name" : "Muokkaa version nimeä",
+ "Compare to current version" : "Vertaa nykyiseen versioon",
+ "Restore version" : "Palauta versio",
+ "Download version" : "Lataa versio",
+ "Delete version" : "Poista versio",
+ "Cancel" : "Peruuta",
+ "Remove version name" : "Poista version nimi",
+ "Save version name" : "Tallenna version nimi",
+ "Version name" : "Version nimi",
+ "Initial version restored" : "Ensimmäinen versio palautettu",
+ "Version restored" : "Versio palautettu",
+ "Could not restore version" : "Versiota ei voitu palauttaa",
+ "Could not delete version" : "Versiota ei voitu poistaa",
+ "File versions" : "Tiedoston versiot"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/fi.json b/apps/files_versions/l10n/fi.json
index cb094998f4f..492facfe430 100644
--- a/apps/files_versions/l10n/fi.json
+++ b/apps/files_versions/l10n/fi.json
@@ -1,9 +1,23 @@
{ "translations": {
"Versions" : "Versiot",
"This application automatically maintains older versions of files that are changed." : "Tämä sovellus säilyttää automaattisesti vanhempia versioita muuttuneista tiedostoista.",
- "Failed to revert {file} to revision {timestamp}." : "Tiedoston {file} palautus versioon {timestamp} epäonnistui.",
- "_%n byte_::_%n bytes_" : ["%n tavu","%n tavua"],
- "Restore" : "Palauta",
- "No other versions available" : "Ei muita versioita saatavilla"
+ "Current version" : "Nykyinen versio",
+ "Initial version" : "Ensimmäinen versio",
+ "You" : "Sinä",
+ "Name this version" : "Nimeä tämä versio",
+ "Edit version name" : "Muokkaa version nimeä",
+ "Compare to current version" : "Vertaa nykyiseen versioon",
+ "Restore version" : "Palauta versio",
+ "Download version" : "Lataa versio",
+ "Delete version" : "Poista versio",
+ "Cancel" : "Peruuta",
+ "Remove version name" : "Poista version nimi",
+ "Save version name" : "Tallenna version nimi",
+ "Version name" : "Version nimi",
+ "Initial version restored" : "Ensimmäinen versio palautettu",
+ "Version restored" : "Versio palautettu",
+ "Could not restore version" : "Versiota ei voitu palauttaa",
+ "Could not delete version" : "Versiota ei voitu poistaa",
+ "File versions" : "Tiedoston versiot"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/fr.js b/apps/files_versions/l10n/fr.js
index 4f42ff26e91..88e5299734e 100644
--- a/apps/files_versions/l10n/fr.js
+++ b/apps/files_versions/l10n/fr.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versions",
"This application automatically maintains older versions of files that are changed." : "Cette application conserve automatiquement des anciennes versions de fichiers qui ont été modifiés.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Cette application maintient automatiquement les anciennes versions des fichiers qui sont modifiés. Lorsqu'elle est activée, un dossier de versions cachées est provisionné dans le répertoire de chaque utilisateur et est utilisé pour stocker les anciennes versions de fichiers. Un utilisateur peut à tout moment revenir à une ancienne version via l'interface Web, le fichier remplacé devenant une version. L'application gère automatiquement le dossier des versions pour s'assurer que l'utilisateur ne manque pas de place à cause des versions stockées.\nEn plus de l'expiration des versions, l'application veille à ne jamais utiliser plus de 50% de l'espace libre actuellement disponible pour l'utilisateur. Si les versions stockées dépassent cette limite, l'application supprime les versions les plus anciennes en premier jusqu'à ce qu'elle atteigne cette limite. Plus d'informations sont disponibles dans la documentation Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Échec de la restauration du fichier {file} à la révision {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n octet","%n octets"],
- "Restore" : "Restaurer",
- "No other versions available" : "Aucune autre version n'est disponible"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Cette application maintient automatiquement les anciennes versions des fichiers qui sont modifiés. Lorsqu'elle est activée, un dossier de versions cachées est provisionné dans le répertoire de chaque utilisateur et est utilisé pour stocker les anciennes versions de fichiers. Un utilisateur peut à tout moment revenir à une ancienne version via l'interface Web, le fichier remplacé devenant à son tour une version. L'application gère automatiquement le dossier des versions pour s'assurer que le compte ne manque pas de place à cause des versions stockées.\n\t\tEn plus de l'expiration des versions, l'application veille à ne jamais utiliser plus de 50% de l'espace libre actuellement disponible pour le compte. Si les versions stockées dépassent cette limite, l'application supprime les versions les plus anciennes en premier jusqu'à ce qu'elle atteigne cette limite. Plus d'informations sont disponibles dans la documentation Versions.",
+ "Current version" : "Version actuelle",
+ "Initial version" : "Version initiale",
+ "You" : "Vous",
+ "Actions for version from {versionHumanExplicitDate}" : "Actions pour la version du {versionHumanExplicitDate}",
+ "Name this version" : "Nommer cette version",
+ "Edit version name" : "Modifier le nom de version",
+ "Compare to current version" : "Comparer avec la version actuelle",
+ "Restore version" : "Restaurer la version",
+ "Download version" : "Télécharger la version",
+ "Delete version" : "Supprimer la version",
+ "Cancel" : "Annuler",
+ "Remove version name" : "Retirer le nom de version",
+ "Save version name" : "Sauvegarder le nom de version",
+ "Version name" : "Nom de la version",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Les versions nommées sont conservées, et exclues des nettoyages automatiques lorsque vos quotas de stockage sont atteints.",
+ "Initial version restored" : "Version initiale restaurée",
+ "Version restored" : "Version restaurée",
+ "Could not restore version" : "Impossible de restaurer la version",
+ "Could not set version label" : "Impossible de définir l'étiquette de version",
+ "Could not delete version" : "Impossible de supprimer la version",
+ "File versions" : "Versions des fichiers"
},
-"nplurals=2; plural=(n > 1);");
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/files_versions/l10n/fr.json b/apps/files_versions/l10n/fr.json
index aa138df6cc4..e59d1f3e59c 100644
--- a/apps/files_versions/l10n/fr.json
+++ b/apps/files_versions/l10n/fr.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versions",
"This application automatically maintains older versions of files that are changed." : "Cette application conserve automatiquement des anciennes versions de fichiers qui ont été modifiés.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Cette application maintient automatiquement les anciennes versions des fichiers qui sont modifiés. Lorsqu'elle est activée, un dossier de versions cachées est provisionné dans le répertoire de chaque utilisateur et est utilisé pour stocker les anciennes versions de fichiers. Un utilisateur peut à tout moment revenir à une ancienne version via l'interface Web, le fichier remplacé devenant une version. L'application gère automatiquement le dossier des versions pour s'assurer que l'utilisateur ne manque pas de place à cause des versions stockées.\nEn plus de l'expiration des versions, l'application veille à ne jamais utiliser plus de 50% de l'espace libre actuellement disponible pour l'utilisateur. Si les versions stockées dépassent cette limite, l'application supprime les versions les plus anciennes en premier jusqu'à ce qu'elle atteigne cette limite. Plus d'informations sont disponibles dans la documentation Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Échec de la restauration du fichier {file} à la révision {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n octet","%n octets"],
- "Restore" : "Restaurer",
- "No other versions available" : "Aucune autre version n'est disponible"
-},"pluralForm" :"nplurals=2; plural=(n > 1);"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Cette application maintient automatiquement les anciennes versions des fichiers qui sont modifiés. Lorsqu'elle est activée, un dossier de versions cachées est provisionné dans le répertoire de chaque utilisateur et est utilisé pour stocker les anciennes versions de fichiers. Un utilisateur peut à tout moment revenir à une ancienne version via l'interface Web, le fichier remplacé devenant à son tour une version. L'application gère automatiquement le dossier des versions pour s'assurer que le compte ne manque pas de place à cause des versions stockées.\n\t\tEn plus de l'expiration des versions, l'application veille à ne jamais utiliser plus de 50% de l'espace libre actuellement disponible pour le compte. Si les versions stockées dépassent cette limite, l'application supprime les versions les plus anciennes en premier jusqu'à ce qu'elle atteigne cette limite. Plus d'informations sont disponibles dans la documentation Versions.",
+ "Current version" : "Version actuelle",
+ "Initial version" : "Version initiale",
+ "You" : "Vous",
+ "Actions for version from {versionHumanExplicitDate}" : "Actions pour la version du {versionHumanExplicitDate}",
+ "Name this version" : "Nommer cette version",
+ "Edit version name" : "Modifier le nom de version",
+ "Compare to current version" : "Comparer avec la version actuelle",
+ "Restore version" : "Restaurer la version",
+ "Download version" : "Télécharger la version",
+ "Delete version" : "Supprimer la version",
+ "Cancel" : "Annuler",
+ "Remove version name" : "Retirer le nom de version",
+ "Save version name" : "Sauvegarder le nom de version",
+ "Version name" : "Nom de la version",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Les versions nommées sont conservées, et exclues des nettoyages automatiques lorsque vos quotas de stockage sont atteints.",
+ "Initial version restored" : "Version initiale restaurée",
+ "Version restored" : "Version restaurée",
+ "Could not restore version" : "Impossible de restaurer la version",
+ "Could not set version label" : "Impossible de définir l'étiquette de version",
+ "Could not delete version" : "Impossible de supprimer la version",
+ "File versions" : "Versions des fichiers"
+},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ga.js b/apps/files_versions/l10n/ga.js
new file mode 100644
index 00000000000..f9bbe03d5fe
--- /dev/null
+++ b/apps/files_versions/l10n/ga.js
@@ -0,0 +1,29 @@
+OC.L10N.register(
+ "files_versions",
+ {
+ "Versions" : "Leaganacha",
+ "This application automatically maintains older versions of files that are changed." : "Coinníonn an feidhmchlár seo leaganacha níos sine de chomhaid a athraítear go huathoibríoch.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Coinníonn an feidhmchlár seo leaganacha níos sine de chomhaid a athraítear go huathoibríoch. Nuair atá sé cumasaithe, cuirtear fillteán leaganacha ceilte ar fáil i gcomhadlann gach úsáideora agus úsáidtear é chun seanleaganacha comhaid a stóráil. Is féidir le húsáideoir filleadh ar leagan níos sine tríd an gcomhéadan gréasáin am ar bith, agus an comhad a athsholáthar ina leagan. Bainistíonn an aip fillteán na leaganacha go huathoibríoch lena chinntiú nach n-éireoidh an cuntas as Cuóta mar gheall ar leaganacha.\n\t\t Chomh maith le dul in éag na leaganacha, cinntíonn an aip leaganacha nach n-úsáidfidh siad riamh níos mó ná 50% den spás saor in aisce atá ar fáil sa chuntas faoi láthair. Má sháraíonn na leaganacha stóráilte an teorainn seo, scriosfaidh an aip na leaganacha is sine ar dtús go dtí go gcomhlíonann sé an teorainn seo. Tá tuilleadh eolais ar fáil sna doiciméid Leaganacha.",
+ "Current version" : "Leagan reatha",
+ "Initial version" : "Leagan tosaigh",
+ "You" : "tú",
+ "Actions for version from {versionHumanExplicitDate}" : "Gníomhartha don leagan ó {versionHumanExplicitDate}",
+ "Name this version" : "Ainmnigh an leagan seo",
+ "Edit version name" : "Cuir ainm an leagain in eagar",
+ "Compare to current version" : "Cuir i gcomparáid leis an leagan reatha",
+ "Restore version" : "Athchóirigh leagan",
+ "Download version" : "Íoslódáil leagan",
+ "Delete version" : "Scrios leagan",
+ "Cancel" : "Cealaigh",
+ "Remove version name" : "Bain ainm an leagain",
+ "Save version name" : "Sábháil ainm an leagain",
+ "Version name" : "Ainm an leagain",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Leantar de leaganacha ainmnithe, agus fágtar iad as an áireamh ó ghlanadh uathoibríoch nuair a bhíonn do chuóta stórála lán.",
+ "Initial version restored" : "Athchóiríodh an leagan tosaigh",
+ "Version restored" : "Leagan athchóirithe",
+ "Could not restore version" : "Níorbh fhéidir an leagan a chur ar ais",
+ "Could not set version label" : "Níorbh fhéidir lipéad an leagain a shocrú",
+ "Could not delete version" : "Níorbh fhéidir an leagan a scriosadh",
+ "File versions" : "Leaganacha comhaid"
+},
+"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);");
diff --git a/apps/files_versions/l10n/ga.json b/apps/files_versions/l10n/ga.json
new file mode 100644
index 00000000000..38098d13973
--- /dev/null
+++ b/apps/files_versions/l10n/ga.json
@@ -0,0 +1,27 @@
+{ "translations": {
+ "Versions" : "Leaganacha",
+ "This application automatically maintains older versions of files that are changed." : "Coinníonn an feidhmchlár seo leaganacha níos sine de chomhaid a athraítear go huathoibríoch.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Coinníonn an feidhmchlár seo leaganacha níos sine de chomhaid a athraítear go huathoibríoch. Nuair atá sé cumasaithe, cuirtear fillteán leaganacha ceilte ar fáil i gcomhadlann gach úsáideora agus úsáidtear é chun seanleaganacha comhaid a stóráil. Is féidir le húsáideoir filleadh ar leagan níos sine tríd an gcomhéadan gréasáin am ar bith, agus an comhad a athsholáthar ina leagan. Bainistíonn an aip fillteán na leaganacha go huathoibríoch lena chinntiú nach n-éireoidh an cuntas as Cuóta mar gheall ar leaganacha.\n\t\t Chomh maith le dul in éag na leaganacha, cinntíonn an aip leaganacha nach n-úsáidfidh siad riamh níos mó ná 50% den spás saor in aisce atá ar fáil sa chuntas faoi láthair. Má sháraíonn na leaganacha stóráilte an teorainn seo, scriosfaidh an aip na leaganacha is sine ar dtús go dtí go gcomhlíonann sé an teorainn seo. Tá tuilleadh eolais ar fáil sna doiciméid Leaganacha.",
+ "Current version" : "Leagan reatha",
+ "Initial version" : "Leagan tosaigh",
+ "You" : "tú",
+ "Actions for version from {versionHumanExplicitDate}" : "Gníomhartha don leagan ó {versionHumanExplicitDate}",
+ "Name this version" : "Ainmnigh an leagan seo",
+ "Edit version name" : "Cuir ainm an leagain in eagar",
+ "Compare to current version" : "Cuir i gcomparáid leis an leagan reatha",
+ "Restore version" : "Athchóirigh leagan",
+ "Download version" : "Íoslódáil leagan",
+ "Delete version" : "Scrios leagan",
+ "Cancel" : "Cealaigh",
+ "Remove version name" : "Bain ainm an leagain",
+ "Save version name" : "Sábháil ainm an leagain",
+ "Version name" : "Ainm an leagain",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Leantar de leaganacha ainmnithe, agus fágtar iad as an áireamh ó ghlanadh uathoibríoch nuair a bhíonn do chuóta stórála lán.",
+ "Initial version restored" : "Athchóiríodh an leagan tosaigh",
+ "Version restored" : "Leagan athchóirithe",
+ "Could not restore version" : "Níorbh fhéidir an leagan a chur ar ais",
+ "Could not set version label" : "Níorbh fhéidir lipéad an leagain a shocrú",
+ "Could not delete version" : "Níorbh fhéidir an leagan a scriosadh",
+ "File versions" : "Leaganacha comhaid"
+},"pluralForm" :"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);"
+} \ No newline at end of file
diff --git a/apps/files_versions/l10n/gl.js b/apps/files_versions/l10n/gl.js
index 44e89166b8f..c9ab468c4c0 100644
--- a/apps/files_versions/l10n/gl.js
+++ b/apps/files_versions/l10n/gl.js
@@ -3,10 +3,26 @@ OC.L10N.register(
{
"Versions" : "Versións",
"This application automatically maintains older versions of files that are changed." : "Esta aplicación mantén automaticamente versións antigas dos ficheiros que cambian.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantén automaticamente versións antigas dos ficheiros que cambian. Ao activarse, crease un cartafol agochado de versións que se emprega para almacenar versións antigas de ficheiros. Un usuario pode reverter cara a unha versión anterior a través da interface web en calquera momento, co ficheiro substituído converténdose nunha versión. A aplicación xestiona automaticamente o cartafol de versións para asegurarse de que o usuario non queda sen espazo por mor das versións.\n\t\tAdemais da caducidade de versións, a aplicación de versións asegurase de non empregar nunca máis do 50% do espazo libre actualmente dispoñíbel para un usuario. Se as versións almacenadas exceden este límite, a aplicación eliminará as versións máis antigas ata acadar este límite. Hai máis información dispoñíbel na documentación de Versións.",
- "Failed to revert {file} to revision {timestamp}." : "Non foi posíbel reverter {file} á revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Non hai outras versións dispoñíbeis"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantén automaticamente as versións anteriores dos ficheiros que se modifican. Ao activarse, crease un cartafol agochado de versións que se emprega para almacenar versións antigas de ficheiros. Un usuario pode reverter cara a unha versión anterior a través da interface web en calquera momento, e o ficheiro substituído pasa a ser unha versión. A aplicación xestiona automaticamente o cartafol de versións para garantir que a conta non esgota a cota de espazo por mor das versións.\n\t\tAdemais da caducidade de versións, a aplicación de versións asegurase de non empregar nunca máis do 50% do espazo libre dispoñíbel actualmente para unha conta. Se as versións almacenadas superan este límite, a aplicación eliminará primeiro as versións máis antigas ata acadar este límite. Hai máis información dispoñíbel na documentación de Versións.",
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Vde.",
+ "Actions for version from {versionHumanExplicitDate}" : "Accións para a versión a partir de {versionHumanExplicitDate}",
+ "Name this version" : "Nomear esta versión",
+ "Edit version name" : "Editar o nome da versión",
+ "Compare to current version" : "Comparar coa versión actual",
+ "Restore version" : "Restaurar a versión",
+ "Download version" : "Descargar a versión",
+ "Delete version" : "Eliminar a versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Retirar o nome da versión",
+ "Save version name" : "Gardar o nome da versión",
+ "Version name" : "Nome da versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "As versións con nome mantéñense e exclúense das limpezas automáticas cando a súa cota de almacenamento estea completa.",
+ "Initial version restored" : "A versión inicial foi restaurada",
+ "Version restored" : "A versión foi restaurada",
+ "Could not restore version" : "Non foi posíbel restaurar a versión",
+ "Could not set version label" : "Non foi posíbel definir a etiqueta de versión",
+ "Could not delete version" : "Non foi posíbel eliminar a versión"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/gl.json b/apps/files_versions/l10n/gl.json
index f09d74f4e25..ec5a2856615 100644
--- a/apps/files_versions/l10n/gl.json
+++ b/apps/files_versions/l10n/gl.json
@@ -1,10 +1,26 @@
{ "translations": {
"Versions" : "Versións",
"This application automatically maintains older versions of files that are changed." : "Esta aplicación mantén automaticamente versións antigas dos ficheiros que cambian.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantén automaticamente versións antigas dos ficheiros que cambian. Ao activarse, crease un cartafol agochado de versións que se emprega para almacenar versións antigas de ficheiros. Un usuario pode reverter cara a unha versión anterior a través da interface web en calquera momento, co ficheiro substituído converténdose nunha versión. A aplicación xestiona automaticamente o cartafol de versións para asegurarse de que o usuario non queda sen espazo por mor das versións.\n\t\tAdemais da caducidade de versións, a aplicación de versións asegurase de non empregar nunca máis do 50% do espazo libre actualmente dispoñíbel para un usuario. Se as versións almacenadas exceden este límite, a aplicación eliminará as versións máis antigas ata acadar este límite. Hai máis información dispoñíbel na documentación de Versións.",
- "Failed to revert {file} to revision {timestamp}." : "Non foi posíbel reverter {file} á revisión {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Non hai outras versións dispoñíbeis"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Esta aplicación mantén automaticamente as versións anteriores dos ficheiros que se modifican. Ao activarse, crease un cartafol agochado de versións que se emprega para almacenar versións antigas de ficheiros. Un usuario pode reverter cara a unha versión anterior a través da interface web en calquera momento, e o ficheiro substituído pasa a ser unha versión. A aplicación xestiona automaticamente o cartafol de versións para garantir que a conta non esgota a cota de espazo por mor das versións.\n\t\tAdemais da caducidade de versións, a aplicación de versións asegurase de non empregar nunca máis do 50% do espazo libre dispoñíbel actualmente para unha conta. Se as versións almacenadas superan este límite, a aplicación eliminará primeiro as versións máis antigas ata acadar este límite. Hai máis información dispoñíbel na documentación de Versións.",
+ "Current version" : "Versión actual",
+ "Initial version" : "Versión inicial",
+ "You" : "Vde.",
+ "Actions for version from {versionHumanExplicitDate}" : "Accións para a versión a partir de {versionHumanExplicitDate}",
+ "Name this version" : "Nomear esta versión",
+ "Edit version name" : "Editar o nome da versión",
+ "Compare to current version" : "Comparar coa versión actual",
+ "Restore version" : "Restaurar a versión",
+ "Download version" : "Descargar a versión",
+ "Delete version" : "Eliminar a versión",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Retirar o nome da versión",
+ "Save version name" : "Gardar o nome da versión",
+ "Version name" : "Nome da versión",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "As versións con nome mantéñense e exclúense das limpezas automáticas cando a súa cota de almacenamento estea completa.",
+ "Initial version restored" : "A versión inicial foi restaurada",
+ "Version restored" : "A versión foi restaurada",
+ "Could not restore version" : "Non foi posíbel restaurar a versión",
+ "Could not set version label" : "Non foi posíbel definir a etiqueta de versión",
+ "Could not delete version" : "Non foi posíbel eliminar a versión"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/he.js b/apps/files_versions/l10n/he.js
deleted file mode 100644
index c2c8b35e109..00000000000
--- a/apps/files_versions/l10n/he.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "גרסאות",
- "This application automatically maintains older versions of files that are changed." : "יישומון זה שומר אוטומטית על גרסאות קודמות של קבצים שהשתנו.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "יישום זה מתחזק באופן אוטומטי גרסאות ישנות יותר של קבצים שמשתנים. כאשר היא מופעלת, תיקייה של גרסאות נסתרות מסופקת בספריה של כל משתמש, ומשמשת לאחסן גרסאות קבצים ישנות. משתמש יכול לחזור לגרסה ישנה יותר באמצעות ממשק האינטרנט בכל עת, כאשר הקובץ שהוחלף יהפוך לגרסה. האפליקציה מנהלת באופן אוטומטי את תיקיית הגרסאות כדי להבטיח שלמשתמש לא נגמר המכסה בגלל גרסאות.\nבנוסף לתום תפוגת הגרסאות, אפליקציית הגרסאות מקפידה שלא להשתמש ביותר מ -50% מהשטח הפנוי של המשתמש הזמין כרגע. אם גרסאות מאוחסנות חורגות ממגבלה זו, האפליקציה תמחק תחילה את הגרסאות העתיקות ביותר, עד שתעמוד במגבלה זו. מידע נוסף זמין בתיעוד ה-Versions.",
- "Failed to revert {file} to revision {timestamp}." : "נכשל אחזור {file} לגרסה {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n בייט","%n בייטים","%n בייטים","%n בייטים"],
- "Restore" : "שחזור",
- "No other versions available" : "אין גרסאות אחרות זמינות"
-},
-"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/apps/files_versions/l10n/he.json b/apps/files_versions/l10n/he.json
deleted file mode 100644
index 9ed5b497d1f..00000000000
--- a/apps/files_versions/l10n/he.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "גרסאות",
- "This application automatically maintains older versions of files that are changed." : "יישומון זה שומר אוטומטית על גרסאות קודמות של קבצים שהשתנו.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "יישום זה מתחזק באופן אוטומטי גרסאות ישנות יותר של קבצים שמשתנים. כאשר היא מופעלת, תיקייה של גרסאות נסתרות מסופקת בספריה של כל משתמש, ומשמשת לאחסן גרסאות קבצים ישנות. משתמש יכול לחזור לגרסה ישנה יותר באמצעות ממשק האינטרנט בכל עת, כאשר הקובץ שהוחלף יהפוך לגרסה. האפליקציה מנהלת באופן אוטומטי את תיקיית הגרסאות כדי להבטיח שלמשתמש לא נגמר המכסה בגלל גרסאות.\nבנוסף לתום תפוגת הגרסאות, אפליקציית הגרסאות מקפידה שלא להשתמש ביותר מ -50% מהשטח הפנוי של המשתמש הזמין כרגע. אם גרסאות מאוחסנות חורגות ממגבלה זו, האפליקציה תמחק תחילה את הגרסאות העתיקות ביותר, עד שתעמוד במגבלה זו. מידע נוסף זמין בתיעוד ה-Versions.",
- "Failed to revert {file} to revision {timestamp}." : "נכשל אחזור {file} לגרסה {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n בייט","%n בייטים","%n בייטים","%n בייטים"],
- "Restore" : "שחזור",
- "No other versions available" : "אין גרסאות אחרות זמינות"
-},"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/apps/files_versions/l10n/hr.js b/apps/files_versions/l10n/hr.js
deleted file mode 100644
index de73e04656c..00000000000
--- a/apps/files_versions/l10n/hr.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Inačice",
- "This application automatically maintains older versions of files that are changed." : "Ova aplikacija automatski održava starije inačice datoteka koje su promijenjene.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ova aplikacija automatski održava starije inačice datoteka koje su promijenjene. Kad se omogući, u direktoriju svakog korisnika stvori se skrivena mapa s inačicama i koristi za pohranu starih inačica datoteka. Korisnik se u bilo kojem trenutku može vratiti na stariju inačicu putem web sučelja, a zamijenjena datoteka postaje inačica. Aplikacija automatski upravlja mapom s inačicama kako bi se osiguralo da korisnik ne ostane bez prostora zbog brojnih inačica.\n\t\tOsim isteka inačica, aplikacija za inačice pazi da nikada ne iskoristite više od 50 % trenutno dostupnog slobodnog prostora. Ako pohranjene inačice premaše ovo ograničenje, aplikacija će najprije izbrisati najstarije inačice tako da dosegne navedeno ograničenje. Više informacija dostupno je u dokumentaciji Inačice.",
- "Failed to revert {file} to revision {timestamp}." : "Neuspješno vraćanje {file} na reviziju {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajtova","%n bajtova"],
- "Restore" : "Vrati",
- "No other versions available" : "Nema drugih inačica"
-},
-"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/apps/files_versions/l10n/hr.json b/apps/files_versions/l10n/hr.json
deleted file mode 100644
index c1839e64749..00000000000
--- a/apps/files_versions/l10n/hr.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "Inačice",
- "This application automatically maintains older versions of files that are changed." : "Ova aplikacija automatski održava starije inačice datoteka koje su promijenjene.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ova aplikacija automatski održava starije inačice datoteka koje su promijenjene. Kad se omogući, u direktoriju svakog korisnika stvori se skrivena mapa s inačicama i koristi za pohranu starih inačica datoteka. Korisnik se u bilo kojem trenutku može vratiti na stariju inačicu putem web sučelja, a zamijenjena datoteka postaje inačica. Aplikacija automatski upravlja mapom s inačicama kako bi se osiguralo da korisnik ne ostane bez prostora zbog brojnih inačica.\n\t\tOsim isteka inačica, aplikacija za inačice pazi da nikada ne iskoristite više od 50 % trenutno dostupnog slobodnog prostora. Ako pohranjene inačice premaše ovo ograničenje, aplikacija će najprije izbrisati najstarije inačice tako da dosegne navedeno ograničenje. Više informacija dostupno je u dokumentaciji Inačice.",
- "Failed to revert {file} to revision {timestamp}." : "Neuspješno vraćanje {file} na reviziju {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajtova","%n bajtova"],
- "Restore" : "Vrati",
- "No other versions available" : "Nema drugih inačica"
-},"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/apps/files_versions/l10n/hu.js b/apps/files_versions/l10n/hu.js
index aa491714a86..d8c34d9aa53 100644
--- a/apps/files_versions/l10n/hu.js
+++ b/apps/files_versions/l10n/hu.js
@@ -3,10 +3,26 @@ OC.L10N.register(
{
"Versions" : "Verziók",
"This application automatically maintains older versions of files that are changed." : "Ez az alkalmazás automatikusan karbantartja a változtatott fájlok régebbi verzióit.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ez az alkalmazás automatikusan karbantartja a változtatott fájlok régebbi verzióit. Amikor be van kapcsolva, egy rejtett verziómappa jön létre minden felhasználó tárhelyén, amit a korábbi verziók tárolására használ a rendszer. Egy felhasználó bármikor visszatérhet egy korábbi verzióhoz a webes felületen keresztül, és a lecserélt fájl maga is előzménnyé válik. Az alkalmazás automatikusan kezeli a verziómappát, biztosítva, hogy a felhasználó ne fusson ki a tárterületéből az előzmények miatt.\n\t\tA fájlelőzmények lejárati dátumán kívül az alkalmazás sose használ az elérhető szabad terület 50%-ánál többet. Ha a tárolt előzmények túllépik ezt a korlátot, az alkalmazás addig törli a legrégebbi verziókat, amíg nem felel meg a korlátozásnak. További információ érhető el a Verziók dokumentációjában.",
- "Failed to revert {file} to revision {timestamp}." : "A(z) {file} fájlt nem sikerült erre visszaállítani: {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bájt","%n bájt"],
- "Restore" : "Visszaállítás",
- "No other versions available" : "Nincs másik elérhető verzió"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ez az alkalmazás automatikusan karbantartja a változtatott fájlok régebbi verzióit. Amikor be van kapcsolva, egy rejtett verziómappa jön létre minden felhasználó tárhelyén, amit a korábbi verziók tárolására használ a rendszer. Egy felhasználó bármikor visszatérhet egy korábbi verzióhoz a webes felületen keresztül, és a lecserélt fájl maga is előzménnyé válik. Az alkalmazás automatikusan kezeli a verziómappát, biztosítva, hogy a fiók ne fusson ki a tárterületéből az előzmények miatt.\n\t\tA fájlelőzmények lejárati dátumán kívül az alkalmazás sose használ az elérhető szabad terület 50%-ánál többet. Ha a tárolt előzmények túllépik ezt a korlátot, az alkalmazás addig törli a legrégebbi verziókat, amíg nem felel meg a korlátozásnak. További információ érhető el a Verziók dokumentációjában.",
+ "Current version" : "Jelenlegi verzió",
+ "Initial version" : "Kezdeti verzió",
+ "You" : "Ön",
+ "Actions for version from {versionHumanExplicitDate}" : "A verzióra vonatkozó műveletek: {versionHumanExplicitDate}",
+ "Name this version" : "Verzió elnevezése",
+ "Edit version name" : "Verziónév szerkesztése",
+ "Compare to current version" : "Összehasonlítás a jelenlegi verzióval",
+ "Restore version" : "Verzió helyreállítása",
+ "Download version" : "Verzió letöltése",
+ "Delete version" : "Verzió törlése",
+ "Cancel" : "Mégse",
+ "Remove version name" : "Verziónév eltávolítása",
+ "Save version name" : "Verziónév mentése",
+ "Version name" : "Verziónév",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "A nevesített verziók meg lesznek őrizve, és ki lesznek zárva az automatikus takarítás alól, ha a tárkvóta betelik.",
+ "Initial version restored" : "Kezdeti verzió helyreállítva",
+ "Version restored" : "Verzió helyreállítva",
+ "Could not restore version" : "Nem sikerült helyreállítani a verziót",
+ "Could not set version label" : "Nem sikerült beállítani a verziócímkét",
+ "Could not delete version" : "Nem sikerült törölni a verziót"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/hu.json b/apps/files_versions/l10n/hu.json
index 31853e18114..1f4f2a3b26e 100644
--- a/apps/files_versions/l10n/hu.json
+++ b/apps/files_versions/l10n/hu.json
@@ -1,10 +1,26 @@
{ "translations": {
"Versions" : "Verziók",
"This application automatically maintains older versions of files that are changed." : "Ez az alkalmazás automatikusan karbantartja a változtatott fájlok régebbi verzióit.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ez az alkalmazás automatikusan karbantartja a változtatott fájlok régebbi verzióit. Amikor be van kapcsolva, egy rejtett verziómappa jön létre minden felhasználó tárhelyén, amit a korábbi verziók tárolására használ a rendszer. Egy felhasználó bármikor visszatérhet egy korábbi verzióhoz a webes felületen keresztül, és a lecserélt fájl maga is előzménnyé válik. Az alkalmazás automatikusan kezeli a verziómappát, biztosítva, hogy a felhasználó ne fusson ki a tárterületéből az előzmények miatt.\n\t\tA fájlelőzmények lejárati dátumán kívül az alkalmazás sose használ az elérhető szabad terület 50%-ánál többet. Ha a tárolt előzmények túllépik ezt a korlátot, az alkalmazás addig törli a legrégebbi verziókat, amíg nem felel meg a korlátozásnak. További információ érhető el a Verziók dokumentációjában.",
- "Failed to revert {file} to revision {timestamp}." : "A(z) {file} fájlt nem sikerült erre visszaállítani: {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bájt","%n bájt"],
- "Restore" : "Visszaállítás",
- "No other versions available" : "Nincs másik elérhető verzió"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ez az alkalmazás automatikusan karbantartja a változtatott fájlok régebbi verzióit. Amikor be van kapcsolva, egy rejtett verziómappa jön létre minden felhasználó tárhelyén, amit a korábbi verziók tárolására használ a rendszer. Egy felhasználó bármikor visszatérhet egy korábbi verzióhoz a webes felületen keresztül, és a lecserélt fájl maga is előzménnyé válik. Az alkalmazás automatikusan kezeli a verziómappát, biztosítva, hogy a fiók ne fusson ki a tárterületéből az előzmények miatt.\n\t\tA fájlelőzmények lejárati dátumán kívül az alkalmazás sose használ az elérhető szabad terület 50%-ánál többet. Ha a tárolt előzmények túllépik ezt a korlátot, az alkalmazás addig törli a legrégebbi verziókat, amíg nem felel meg a korlátozásnak. További információ érhető el a Verziók dokumentációjában.",
+ "Current version" : "Jelenlegi verzió",
+ "Initial version" : "Kezdeti verzió",
+ "You" : "Ön",
+ "Actions for version from {versionHumanExplicitDate}" : "A verzióra vonatkozó műveletek: {versionHumanExplicitDate}",
+ "Name this version" : "Verzió elnevezése",
+ "Edit version name" : "Verziónév szerkesztése",
+ "Compare to current version" : "Összehasonlítás a jelenlegi verzióval",
+ "Restore version" : "Verzió helyreállítása",
+ "Download version" : "Verzió letöltése",
+ "Delete version" : "Verzió törlése",
+ "Cancel" : "Mégse",
+ "Remove version name" : "Verziónév eltávolítása",
+ "Save version name" : "Verziónév mentése",
+ "Version name" : "Verziónév",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "A nevesített verziók meg lesznek őrizve, és ki lesznek zárva az automatikus takarítás alól, ha a tárkvóta betelik.",
+ "Initial version restored" : "Kezdeti verzió helyreállítva",
+ "Version restored" : "Verzió helyreállítva",
+ "Could not restore version" : "Nem sikerült helyreállítani a verziót",
+ "Could not set version label" : "Nem sikerült beállítani a verziócímkét",
+ "Could not delete version" : "Nem sikerült törölni a verziót"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/hy.js b/apps/files_versions/l10n/hy.js
deleted file mode 100644
index d48487a9a84..00000000000
--- a/apps/files_versions/l10n/hy.js
+++ /dev/null
@@ -1,8 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Տարբերակներ",
- "Restore" : "Վերականգնել",
- "No other versions available" : "Այլ տարբերակներ չկան"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/hy.json b/apps/files_versions/l10n/hy.json
deleted file mode 100644
index 579b9240310..00000000000
--- a/apps/files_versions/l10n/hy.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{ "translations": {
- "Versions" : "Տարբերակներ",
- "Restore" : "Վերականգնել",
- "No other versions available" : "Այլ տարբերակներ չկան"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ia.js b/apps/files_versions/l10n/ia.js
deleted file mode 100644
index 46aa143e4a7..00000000000
--- a/apps/files_versions/l10n/ia.js
+++ /dev/null
@@ -1,10 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Il falleva a reverter {file} a revision {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Nulle altere versiones disponibile"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/ia.json b/apps/files_versions/l10n/ia.json
deleted file mode 100644
index 10c18bab080..00000000000
--- a/apps/files_versions/l10n/ia.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "Failed to revert {file} to revision {timestamp}." : "Il falleva a reverter {file} a revision {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Nulle altere versiones disponibile"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/id.js b/apps/files_versions/l10n/id.js
deleted file mode 100644
index f52699b48f0..00000000000
--- a/apps/files_versions/l10n/id.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versi",
- "This application automatically maintains older versions of files that are changed." : "Aplikasi ini secara otomatis memelihara versi-versi sebelumnya dari berkas yang telah diubah.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikasi ini secara otomatis memelihara versi-versi sebelumnya dari berkas yang telah diubah. Saat diaktifkan, suatu folder tersembunyi akan dibuat pada semua direktori pengguna, dan digunakan sebagai wadah penyimpanan versi-versi berkas. Secara otomatis akan mengelola folder versi-versi untuk memastikan pengguna tidak kehabisan kuota dikarenakan versi yang ada.\n\t\tSebagai tambahan dari kedaluwarsa suatu versi, aplikasi ini memastikan tidak akan menggunakan kuota 50% lebih dari sisa kapasitas yang dimiliki oleh pengguna. Jika versi yang tersimpan melampaui batasan, maka versi tertua akan dihapus lebih dahulu sampai batasan kembali sesuai ketentuan. Informasi lebih lanjut mengenai Versi dapat dilihat pada dokumentasi",
- "Failed to revert {file} to revision {timestamp}." : "Gagal mengembalikan {file} ke revisi {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bytes"],
- "Restore" : "Pulihkan",
- "No other versions available" : "Tidak ada versi lain yang tersedia"
-},
-"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/id.json b/apps/files_versions/l10n/id.json
deleted file mode 100644
index b5c606a8ec6..00000000000
--- a/apps/files_versions/l10n/id.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "Versi",
- "This application automatically maintains older versions of files that are changed." : "Aplikasi ini secara otomatis memelihara versi-versi sebelumnya dari berkas yang telah diubah.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikasi ini secara otomatis memelihara versi-versi sebelumnya dari berkas yang telah diubah. Saat diaktifkan, suatu folder tersembunyi akan dibuat pada semua direktori pengguna, dan digunakan sebagai wadah penyimpanan versi-versi berkas. Secara otomatis akan mengelola folder versi-versi untuk memastikan pengguna tidak kehabisan kuota dikarenakan versi yang ada.\n\t\tSebagai tambahan dari kedaluwarsa suatu versi, aplikasi ini memastikan tidak akan menggunakan kuota 50% lebih dari sisa kapasitas yang dimiliki oleh pengguna. Jika versi yang tersimpan melampaui batasan, maka versi tertua akan dihapus lebih dahulu sampai batasan kembali sesuai ketentuan. Informasi lebih lanjut mengenai Versi dapat dilihat pada dokumentasi",
- "Failed to revert {file} to revision {timestamp}." : "Gagal mengembalikan {file} ke revisi {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bytes"],
- "Restore" : "Pulihkan",
- "No other versions available" : "Tidak ada versi lain yang tersedia"
-},"pluralForm" :"nplurals=1; plural=0;"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/is.js b/apps/files_versions/l10n/is.js
index e18151f5836..5f995d19f2f 100644
--- a/apps/files_versions/l10n/is.js
+++ b/apps/files_versions/l10n/is.js
@@ -3,9 +3,25 @@ OC.L10N.register(
{
"Versions" : "Útgáfur",
"This application automatically maintains older versions of files that are changed." : "Þetta forrit viðheldur sjálfvirkt eldri útgáfum skráa sem er breytt.",
- "Failed to revert {file} to revision {timestamp}." : "Mistókst að endurheimta {file} útgáfu {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bæti","%n bæti"],
- "Restore" : "Endurheimta",
- "No other versions available" : "Engar aðrar útgáfur í boði"
+ "Current version" : "Fyrirliggjandi útgáfa",
+ "Initial version" : "Upprunaleg útgáfa",
+ "You" : "Þú",
+ "Actions for version from {versionHumanExplicitDate}" : "Aðgerðir fyrir útgáfu frá {versionHumanExplicitDate}",
+ "Name this version" : "Settu heiti á þessa útgáfu",
+ "Edit version name" : "Breyta heiti útgáfunnar",
+ "Compare to current version" : "Bera saman við fyrirliggjandi útgáfu",
+ "Restore version" : "Endurheimta útgáfu",
+ "Download version" : "Sækja útgáfu",
+ "Delete version" : "Eyða útgáfu",
+ "Cancel" : "Hætta við",
+ "Remove version name" : "Fjarlægja heiti útgáfu",
+ "Save version name" : "Vista heiti útgáfu",
+ "Version name" : "Heiti útgáfu",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Nefndar útgáfur eru varanlegar og er undanþegnar við sjálfvirkar tiltektir þegar geymslukvóti fyllist.",
+ "Initial version restored" : "Upprunaleg útgáfa endurheimt",
+ "Version restored" : "Útgáfa endurheimt",
+ "Could not restore version" : "Gat ekki endurheimt útgáfu",
+ "Could not set version label" : "Gat ekki sett merkingu á útgáfu",
+ "Could not delete version" : "Gat ekki eytt útgáfu"
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");
diff --git a/apps/files_versions/l10n/is.json b/apps/files_versions/l10n/is.json
index 60a3bdd0fa8..368351cdac7 100644
--- a/apps/files_versions/l10n/is.json
+++ b/apps/files_versions/l10n/is.json
@@ -1,9 +1,25 @@
{ "translations": {
"Versions" : "Útgáfur",
"This application automatically maintains older versions of files that are changed." : "Þetta forrit viðheldur sjálfvirkt eldri útgáfum skráa sem er breytt.",
- "Failed to revert {file} to revision {timestamp}." : "Mistókst að endurheimta {file} útgáfu {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bæti","%n bæti"],
- "Restore" : "Endurheimta",
- "No other versions available" : "Engar aðrar útgáfur í boði"
+ "Current version" : "Fyrirliggjandi útgáfa",
+ "Initial version" : "Upprunaleg útgáfa",
+ "You" : "Þú",
+ "Actions for version from {versionHumanExplicitDate}" : "Aðgerðir fyrir útgáfu frá {versionHumanExplicitDate}",
+ "Name this version" : "Settu heiti á þessa útgáfu",
+ "Edit version name" : "Breyta heiti útgáfunnar",
+ "Compare to current version" : "Bera saman við fyrirliggjandi útgáfu",
+ "Restore version" : "Endurheimta útgáfu",
+ "Download version" : "Sækja útgáfu",
+ "Delete version" : "Eyða útgáfu",
+ "Cancel" : "Hætta við",
+ "Remove version name" : "Fjarlægja heiti útgáfu",
+ "Save version name" : "Vista heiti útgáfu",
+ "Version name" : "Heiti útgáfu",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Nefndar útgáfur eru varanlegar og er undanþegnar við sjálfvirkar tiltektir þegar geymslukvóti fyllist.",
+ "Initial version restored" : "Upprunaleg útgáfa endurheimt",
+ "Version restored" : "Útgáfa endurheimt",
+ "Could not restore version" : "Gat ekki endurheimt útgáfu",
+ "Could not set version label" : "Gat ekki sett merkingu á útgáfu",
+ "Could not delete version" : "Gat ekki eytt útgáfu"
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/it.js b/apps/files_versions/l10n/it.js
index 8fc123d0e97..2e782c6d327 100644
--- a/apps/files_versions/l10n/it.js
+++ b/apps/files_versions/l10n/it.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versioni",
"This application automatically maintains older versions of files that are changed." : "Questa applicazione mantiene automaticamente versioni più datate dei file modificati.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Questa applicazione conserva automaticamente versioni più datate dei file che sono stati modificati. Se abilitata, una cartella nascosta delle versioni è generata in ogni cartella degli utenti ed è utilizzata per archiviare le versioni datate dei file. Un utente può tornare a una versione più datata tramite l'interfaccia web in qualsiasi momento, con il file sostituito che diventa una versione. L'applicazione gestisce automaticamente la cartella delle versioni per assicurare che l'utente non esaurisca mai la quota a causa delle versioni.\n\t\tIn aggiunta alla scadenza delle versioni, l'applicazione delle versioni si accerta che non sia utilizzato mai più del 50% dello spazio disponibile attualmente all'utente. Se le versioni archiviate eccedono questo limite, l'applicazione eliminerà prima le versioni più vecchie, fino a raggiungere questo limite. Altre informazioni sono disponibili nella documentazione di Versioni.",
- "Failed to revert {file} to revision {timestamp}." : "Ripristino di {file} alla revisione {timestamp} non riuscito.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n byte"],
- "Restore" : "Ripristina",
- "No other versions available" : "Non sono disponibili altre versioni"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Questa applicazione conserva automaticamente le versioni più datate dei file che sono stati modificati. Se attivata, una cartella nascosta delle versioni viene generata in ogni cartella degli utenti ed è usata per archiviare le versioni datate dei file. Un utente può tornare a una versione più datata tramite l'interfaccia web in qualsiasi momento, con il file sostituito che diventa una versione. L'applicazione gestisce automaticamente la cartella delle versioni per assicurare che l'account non esaurisca mai la quota a causa delle versioni.\n\t\tIn aggiunta alla scadenza delle versioni, l'applicazione delle versioni si accerta che non sia utilizzato mai più del 50% dello spazio disponibile attualmente all'account. Se le versioni archiviate eccedono questo limite, l'applicazione eliminerà prima le versioni più vecchie, fino a raggiungere questo limite. Altre informazioni sono disponibili nella documentazione di Versioni.",
+ "Current version" : "Versione corrente",
+ "Initial version" : "Versione iniziale",
+ "You" : "Tu",
+ "Actions for version from {versionHumanExplicitDate}" : "Azioni per la versione da {versionHumanExplicitDate}",
+ "Name this version" : "Nome di questa versione",
+ "Edit version name" : "Modifica nome versione",
+ "Compare to current version" : "Confronta con la versione attuale",
+ "Restore version" : "Ripristina versione",
+ "Download version" : "Scarica versione",
+ "Delete version" : "Elimina versione",
+ "Cancel" : "Annulla",
+ "Remove version name" : "Rimuovi nome versione",
+ "Save version name" : "Salva nome versione",
+ "Version name" : "Nome versione",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Le versioni con nome sono persistenti ed escluse dalle pulizie automatiche quando lo spazio è pieno.",
+ "Initial version restored" : "Versione iniziale ripristinata",
+ "Version restored" : "Versione ripristinata",
+ "Could not restore version" : "Impossibile ripristinare la versione",
+ "Could not set version label" : "Impossibile impostare l'etichetta della versione",
+ "Could not delete version" : "Impossibile eliminare la versione",
+ "File versions" : "Versioni dei file"
},
-"nplurals=2; plural=(n != 1);");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/files_versions/l10n/it.json b/apps/files_versions/l10n/it.json
index 26990baabb9..0871aa8c115 100644
--- a/apps/files_versions/l10n/it.json
+++ b/apps/files_versions/l10n/it.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versioni",
"This application automatically maintains older versions of files that are changed." : "Questa applicazione mantiene automaticamente versioni più datate dei file modificati.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Questa applicazione conserva automaticamente versioni più datate dei file che sono stati modificati. Se abilitata, una cartella nascosta delle versioni è generata in ogni cartella degli utenti ed è utilizzata per archiviare le versioni datate dei file. Un utente può tornare a una versione più datata tramite l'interfaccia web in qualsiasi momento, con il file sostituito che diventa una versione. L'applicazione gestisce automaticamente la cartella delle versioni per assicurare che l'utente non esaurisca mai la quota a causa delle versioni.\n\t\tIn aggiunta alla scadenza delle versioni, l'applicazione delle versioni si accerta che non sia utilizzato mai più del 50% dello spazio disponibile attualmente all'utente. Se le versioni archiviate eccedono questo limite, l'applicazione eliminerà prima le versioni più vecchie, fino a raggiungere questo limite. Altre informazioni sono disponibili nella documentazione di Versioni.",
- "Failed to revert {file} to revision {timestamp}." : "Ripristino di {file} alla revisione {timestamp} non riuscito.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n byte"],
- "Restore" : "Ripristina",
- "No other versions available" : "Non sono disponibili altre versioni"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Questa applicazione conserva automaticamente le versioni più datate dei file che sono stati modificati. Se attivata, una cartella nascosta delle versioni viene generata in ogni cartella degli utenti ed è usata per archiviare le versioni datate dei file. Un utente può tornare a una versione più datata tramite l'interfaccia web in qualsiasi momento, con il file sostituito che diventa una versione. L'applicazione gestisce automaticamente la cartella delle versioni per assicurare che l'account non esaurisca mai la quota a causa delle versioni.\n\t\tIn aggiunta alla scadenza delle versioni, l'applicazione delle versioni si accerta che non sia utilizzato mai più del 50% dello spazio disponibile attualmente all'account. Se le versioni archiviate eccedono questo limite, l'applicazione eliminerà prima le versioni più vecchie, fino a raggiungere questo limite. Altre informazioni sono disponibili nella documentazione di Versioni.",
+ "Current version" : "Versione corrente",
+ "Initial version" : "Versione iniziale",
+ "You" : "Tu",
+ "Actions for version from {versionHumanExplicitDate}" : "Azioni per la versione da {versionHumanExplicitDate}",
+ "Name this version" : "Nome di questa versione",
+ "Edit version name" : "Modifica nome versione",
+ "Compare to current version" : "Confronta con la versione attuale",
+ "Restore version" : "Ripristina versione",
+ "Download version" : "Scarica versione",
+ "Delete version" : "Elimina versione",
+ "Cancel" : "Annulla",
+ "Remove version name" : "Rimuovi nome versione",
+ "Save version name" : "Salva nome versione",
+ "Version name" : "Nome versione",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Le versioni con nome sono persistenti ed escluse dalle pulizie automatiche quando lo spazio è pieno.",
+ "Initial version restored" : "Versione iniziale ripristinata",
+ "Version restored" : "Versione ripristinata",
+ "Could not restore version" : "Impossibile ripristinare la versione",
+ "Could not set version label" : "Impossibile impostare l'etichetta della versione",
+ "Could not delete version" : "Impossibile eliminare la versione",
+ "File versions" : "Versioni dei file"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ja.js b/apps/files_versions/l10n/ja.js
index 84e20693faa..d4202f4050d 100644
--- a/apps/files_versions/l10n/ja.js
+++ b/apps/files_versions/l10n/ja.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "バージョン",
"This application automatically maintains older versions of files that are changed." : "このアプリケーションは、変更された古いバージョンのファイルを自動的に維持します。",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "このアプリケーションは、変更された古いバージョンのファイルを自動的に維持します。 有効にすると、隠れバージョンフォルダーはすべてのユーザーのディレクトリにプロビジョニングされ、古いファイルバージョンを格納するために使用されます。 ユーザーはいつでもWebインターフェイスから古いバージョンに戻すことができ、置き換えられたファイルはバージョン管理されます。 バージョン管理のためにクオータが足りなくなっていないことを保証するために、バージョンフォルダーを自動的に管理します。バージョンの有効期限に加えて、バージョン管理アプリは、ユーザーが現在利用可能な空き容量の50%以上利用しないように維持します。 保存されたバージョンがこの制限を超えた場合、アプリはこの制限を満たすまで、最も古いバージョンを最初に削除します。 詳細は、バージョンのドキュメントを参照してください。",
- "Failed to revert {file} to revision {timestamp}." : "{file} を {timestamp} のリビジョンに戻すことができません。",
- "_%n byte_::_%n bytes_" : ["%n バイト"],
- "Restore" : "復元",
- "No other versions available" : "利用可能なバージョンはありません"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "このアプリケーションは、変更された古いバージョンのファイルを自動的に維持します。有効にすると、隠れバージョン用フォルダーがすべてのユーザーのディレクトリに用意され、古いファイルバージョンを格納するために使用されます。ユーザーはいつでもWebインターフェースから古いバージョンに戻すことができ、置き換えられたファイルはバージョン管理されます。アプリはバージョンフォルダーを自動的に管理して、アカウントがバージョン履歴のために容量を使い果たさないようにします。\nバージョンの有効期限に加えて、バージョンアプリは、アカウントの現在利用可能な空き容量の50%以上を使用しないように維持します。保存されたバージョンがこの制限を超えた場合、アプリはこの制限を満たすまで、最初に最も古いバージョンから削除します。詳細は、バージョンのドキュメントを参照してください。",
+ "Current version" : "現在のバージョン",
+ "Initial version" : "最初のバージョン",
+ "You" : "自分",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate}からのバージョンに対するアクション",
+ "Name this version" : "このバージョンに名前を付けます",
+ "Edit version name" : "バージョン名の編集",
+ "Compare to current version" : "現在のバージョンと比較",
+ "Restore version" : "このバージョンを復元する",
+ "Download version" : "このバージョンをダウンロード",
+ "Delete version" : "このバージョンを削除",
+ "Cancel" : "キャンセル",
+ "Remove version name" : "バージョン名を削除",
+ "Save version name" : "バージョン名を保存",
+ "Version name" : "名前付きバージョン",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "名前付きバージョンは永続化され、ストレージクォータがいっぱいになっていても自動クリーンアップから除外されます。",
+ "Initial version restored" : "初期バージョンを復旧",
+ "Version restored" : "指定のバージョンが復旧されました",
+ "Could not restore version" : "このバージョンを復旧できません",
+ "Could not set version label" : "バージョンラベルを付けることができませんでした",
+ "Could not delete version" : "指定のバージョンを削除できませんでした",
+ "File versions" : "ファイルバージョン"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/ja.json b/apps/files_versions/l10n/ja.json
index 1d71637d7dc..2d877d60eb7 100644
--- a/apps/files_versions/l10n/ja.json
+++ b/apps/files_versions/l10n/ja.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "バージョン",
"This application automatically maintains older versions of files that are changed." : "このアプリケーションは、変更された古いバージョンのファイルを自動的に維持します。",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "このアプリケーションは、変更された古いバージョンのファイルを自動的に維持します。 有効にすると、隠れバージョンフォルダーはすべてのユーザーのディレクトリにプロビジョニングされ、古いファイルバージョンを格納するために使用されます。 ユーザーはいつでもWebインターフェイスから古いバージョンに戻すことができ、置き換えられたファイルはバージョン管理されます。 バージョン管理のためにクオータが足りなくなっていないことを保証するために、バージョンフォルダーを自動的に管理します。バージョンの有効期限に加えて、バージョン管理アプリは、ユーザーが現在利用可能な空き容量の50%以上利用しないように維持します。 保存されたバージョンがこの制限を超えた場合、アプリはこの制限を満たすまで、最も古いバージョンを最初に削除します。 詳細は、バージョンのドキュメントを参照してください。",
- "Failed to revert {file} to revision {timestamp}." : "{file} を {timestamp} のリビジョンに戻すことができません。",
- "_%n byte_::_%n bytes_" : ["%n バイト"],
- "Restore" : "復元",
- "No other versions available" : "利用可能なバージョンはありません"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "このアプリケーションは、変更された古いバージョンのファイルを自動的に維持します。有効にすると、隠れバージョン用フォルダーがすべてのユーザーのディレクトリに用意され、古いファイルバージョンを格納するために使用されます。ユーザーはいつでもWebインターフェースから古いバージョンに戻すことができ、置き換えられたファイルはバージョン管理されます。アプリはバージョンフォルダーを自動的に管理して、アカウントがバージョン履歴のために容量を使い果たさないようにします。\nバージョンの有効期限に加えて、バージョンアプリは、アカウントの現在利用可能な空き容量の50%以上を使用しないように維持します。保存されたバージョンがこの制限を超えた場合、アプリはこの制限を満たすまで、最初に最も古いバージョンから削除します。詳細は、バージョンのドキュメントを参照してください。",
+ "Current version" : "現在のバージョン",
+ "Initial version" : "最初のバージョン",
+ "You" : "自分",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate}からのバージョンに対するアクション",
+ "Name this version" : "このバージョンに名前を付けます",
+ "Edit version name" : "バージョン名の編集",
+ "Compare to current version" : "現在のバージョンと比較",
+ "Restore version" : "このバージョンを復元する",
+ "Download version" : "このバージョンをダウンロード",
+ "Delete version" : "このバージョンを削除",
+ "Cancel" : "キャンセル",
+ "Remove version name" : "バージョン名を削除",
+ "Save version name" : "バージョン名を保存",
+ "Version name" : "名前付きバージョン",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "名前付きバージョンは永続化され、ストレージクォータがいっぱいになっていても自動クリーンアップから除外されます。",
+ "Initial version restored" : "初期バージョンを復旧",
+ "Version restored" : "指定のバージョンが復旧されました",
+ "Could not restore version" : "このバージョンを復旧できません",
+ "Could not set version label" : "バージョンラベルを付けることができませんでした",
+ "Could not delete version" : "指定のバージョンを削除できませんでした",
+ "File versions" : "ファイルバージョン"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ka.js b/apps/files_versions/l10n/ka.js
new file mode 100644
index 00000000000..92b8518a28f
--- /dev/null
+++ b/apps/files_versions/l10n/ka.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "files_versions",
+ {
+ "Versions" : "Versions",
+ "This application automatically maintains older versions of files that are changed." : "This application automatically maintains older versions of files that are changed.",
+ "Current version" : "Current version",
+ "Initial version" : "Initial version",
+ "You" : "You",
+ "Name this version" : "Name this version",
+ "Edit version name" : "Edit version name",
+ "Compare to current version" : "Compare to current version",
+ "Restore version" : "Restore version",
+ "Download version" : "Download version",
+ "Delete version" : "Delete version",
+ "Cancel" : "Cancel",
+ "Remove version name" : "Remove version name",
+ "Save version name" : "Save version name",
+ "Version name" : "Version name",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.",
+ "Initial version restored" : "Initial version restored",
+ "Version restored" : "Version restored",
+ "Could not restore version" : "Could not restore version",
+ "Could not delete version" : "Could not delete version"
+},
+"nplurals=2; plural=(n!=1);");
diff --git a/apps/files_versions/l10n/ka.json b/apps/files_versions/l10n/ka.json
new file mode 100644
index 00000000000..fb116a07a9d
--- /dev/null
+++ b/apps/files_versions/l10n/ka.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Versions" : "Versions",
+ "This application automatically maintains older versions of files that are changed." : "This application automatically maintains older versions of files that are changed.",
+ "Current version" : "Current version",
+ "Initial version" : "Initial version",
+ "You" : "You",
+ "Name this version" : "Name this version",
+ "Edit version name" : "Edit version name",
+ "Compare to current version" : "Compare to current version",
+ "Restore version" : "Restore version",
+ "Download version" : "Download version",
+ "Delete version" : "Delete version",
+ "Cancel" : "Cancel",
+ "Remove version name" : "Remove version name",
+ "Save version name" : "Save version name",
+ "Version name" : "Version name",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.",
+ "Initial version restored" : "Initial version restored",
+ "Version restored" : "Version restored",
+ "Could not restore version" : "Could not restore version",
+ "Could not delete version" : "Could not delete version"
+},"pluralForm" :"nplurals=2; plural=(n!=1);"
+} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ka_GE.js b/apps/files_versions/l10n/ka_GE.js
deleted file mode 100644
index 598dd4e40e3..00000000000
--- a/apps/files_versions/l10n/ka_GE.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "ვერსიები",
- "Failed to revert {file} to revision {timestamp}." : "ფაილის {file} დაბრუნება რევიზიაზე {timestamp} ვერ ხერხდება.",
- "_%n byte_::_%n bytes_" : ["%n ბაიტი","%n ბაიტი"],
- "Restore" : "აღდგენა"
-},
-"nplurals=2; plural=(n!=1);");
diff --git a/apps/files_versions/l10n/ka_GE.json b/apps/files_versions/l10n/ka_GE.json
deleted file mode 100644
index 1b2607a309b..00000000000
--- a/apps/files_versions/l10n/ka_GE.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "ვერსიები",
- "Failed to revert {file} to revision {timestamp}." : "ფაილის {file} დაბრუნება რევიზიაზე {timestamp} ვერ ხერხდება.",
- "_%n byte_::_%n bytes_" : ["%n ბაიტი","%n ბაიტი"],
- "Restore" : "აღდგენა"
-},"pluralForm" :"nplurals=2; plural=(n!=1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/km.js b/apps/files_versions/l10n/km.js
deleted file mode 100644
index a459413b284..00000000000
--- a/apps/files_versions/l10n/km.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "កំណែ",
- "Failed to revert {file} to revision {timestamp}." : "មិន​អាច​ត្រឡប់ {file} ទៅ​កំណែ​សម្រួល {timestamp} បាន​ទេ។",
- "Restore" : "ស្ដារ​មក​វិញ",
- "No other versions available" : "មិន​មាន​កំណែ​ផ្សេង​ទៀត​ទេ"
-},
-"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/km.json b/apps/files_versions/l10n/km.json
deleted file mode 100644
index b2e34f4fb35..00000000000
--- a/apps/files_versions/l10n/km.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "កំណែ",
- "Failed to revert {file} to revision {timestamp}." : "មិន​អាច​ត្រឡប់ {file} ទៅ​កំណែ​សម្រួល {timestamp} បាន​ទេ។",
- "Restore" : "ស្ដារ​មក​វិញ",
- "No other versions available" : "មិន​មាន​កំណែ​ផ្សេង​ទៀត​ទេ"
-},"pluralForm" :"nplurals=1; plural=0;"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/kn.js b/apps/files_versions/l10n/kn.js
deleted file mode 100644
index db64a419828..00000000000
--- a/apps/files_versions/l10n/kn.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "ಆವೃತ್ತಿಗಳು",
- "Failed to revert {file} to revision {timestamp}." : "{timestamp} ದ ಪರಿಷ್ಕರಣೆ ಇಂದ {file} ಕಡತವನ್ನು ಹಿಂದಿರುಗಿಸಲು ವಿಫಲವಾಗಿದೆ.",
- "Restore" : "ಮರುಸ್ಥಾಪಿಸು",
- "No other versions available" : "ಇನ್ನಿತರೆ ಯಾವುದೇ ಆವೃತ್ತಿಗಳು ಲಭ್ಯವಿಲ್ಲ"
-},
-"nplurals=2; plural=(n > 1);");
diff --git a/apps/files_versions/l10n/kn.json b/apps/files_versions/l10n/kn.json
deleted file mode 100644
index d7226c306eb..00000000000
--- a/apps/files_versions/l10n/kn.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "ಆವೃತ್ತಿಗಳು",
- "Failed to revert {file} to revision {timestamp}." : "{timestamp} ದ ಪರಿಷ್ಕರಣೆ ಇಂದ {file} ಕಡತವನ್ನು ಹಿಂದಿರುಗಿಸಲು ವಿಫಲವಾಗಿದೆ.",
- "Restore" : "ಮರುಸ್ಥಾಪಿಸು",
- "No other versions available" : "ಇನ್ನಿತರೆ ಯಾವುದೇ ಆವೃತ್ತಿಗಳು ಲಭ್ಯವಿಲ್ಲ"
-},"pluralForm" :"nplurals=2; plural=(n > 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ko.js b/apps/files_versions/l10n/ko.js
index 0d20843dcf4..ec839dace65 100644
--- a/apps/files_versions/l10n/ko.js
+++ b/apps/files_versions/l10n/ko.js
@@ -3,10 +3,23 @@ OC.L10N.register(
{
"Versions" : "버전",
"This application automatically maintains older versions of files that are changed." : "이 앱은 변경된 파일의 이전 버전을 관리합니다.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "이 앱은 변경된 파일의 이전 버전을 관리합니다. 이 앱을 활성화하면 개별 사용자 디렉터리 아래에 숨김 버전 폴더를 생성하며 이전 버전의 파일을 저장합니다. 웹 인터페이스를 사용하여 파일의 이전 버전으로 복원할 수 있으며, 대체된 파일은 새로운 버전으로 간주됩니다. 앱에서 버전 폴더의 크기를 자동으로 관리하여 이전 버전 때문에 할당량을 초과하는 일을 방지합니다.\n\t\t이전 버전 자동 삭제 외에도 버전 앱에서는 사용자의 현재 남은 공간의 50% 이상을 사용하지 않습니다. 저장된 버전이 해당 할당량을 초과한다면 할당량 이하로 떨어질 때까지 앱에서 가장 오래된 버전을 삭제합니다. 자세한 정보를 보려면 버전 문서를 참조하십시오.",
- "Failed to revert {file} to revision {timestamp}." : "{file}을(를) 리비전 {timestamp}(으)로 되돌리는 데 실패했습니다.",
- "_%n byte_::_%n bytes_" : ["%n바이트"],
- "Restore" : "복원",
- "No other versions available" : "다른 버전을 사용할 수 없음"
+ "Current version" : "현재 버전",
+ "Initial version" : "초기 버전",
+ "You" : "당신",
+ "Name this version" : "버전 이름 지정",
+ "Edit version name" : "버전 이름 수정",
+ "Compare to current version" : "현재 버전과 비교하기",
+ "Restore version" : "버전 복원",
+ "Download version" : "버전 다운로드",
+ "Delete version" : "버전 삭제",
+ "Cancel" : "취소",
+ "Remove version name" : "버전 이름 제거",
+ "Save version name" : "버전 이름 저장",
+ "Version name" : "버전 이름",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "이름이 지정된 버전은 유지되며, 저장 공간 할당량이 가득 찼을 때의 자동 정리 목록에서 제외됩니다.",
+ "Initial version restored" : "초기 버전이 복원됨",
+ "Version restored" : "버전이 복원됨",
+ "Could not restore version" : "버전을 복원할 수 없음",
+ "Could not delete version" : "버전을 삭제할 수 없음"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/ko.json b/apps/files_versions/l10n/ko.json
index 511b13e186b..658529bf8bd 100644
--- a/apps/files_versions/l10n/ko.json
+++ b/apps/files_versions/l10n/ko.json
@@ -1,10 +1,23 @@
{ "translations": {
"Versions" : "버전",
"This application automatically maintains older versions of files that are changed." : "이 앱은 변경된 파일의 이전 버전을 관리합니다.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "이 앱은 변경된 파일의 이전 버전을 관리합니다. 이 앱을 활성화하면 개별 사용자 디렉터리 아래에 숨김 버전 폴더를 생성하며 이전 버전의 파일을 저장합니다. 웹 인터페이스를 사용하여 파일의 이전 버전으로 복원할 수 있으며, 대체된 파일은 새로운 버전으로 간주됩니다. 앱에서 버전 폴더의 크기를 자동으로 관리하여 이전 버전 때문에 할당량을 초과하는 일을 방지합니다.\n\t\t이전 버전 자동 삭제 외에도 버전 앱에서는 사용자의 현재 남은 공간의 50% 이상을 사용하지 않습니다. 저장된 버전이 해당 할당량을 초과한다면 할당량 이하로 떨어질 때까지 앱에서 가장 오래된 버전을 삭제합니다. 자세한 정보를 보려면 버전 문서를 참조하십시오.",
- "Failed to revert {file} to revision {timestamp}." : "{file}을(를) 리비전 {timestamp}(으)로 되돌리는 데 실패했습니다.",
- "_%n byte_::_%n bytes_" : ["%n바이트"],
- "Restore" : "복원",
- "No other versions available" : "다른 버전을 사용할 수 없음"
+ "Current version" : "현재 버전",
+ "Initial version" : "초기 버전",
+ "You" : "당신",
+ "Name this version" : "버전 이름 지정",
+ "Edit version name" : "버전 이름 수정",
+ "Compare to current version" : "현재 버전과 비교하기",
+ "Restore version" : "버전 복원",
+ "Download version" : "버전 다운로드",
+ "Delete version" : "버전 삭제",
+ "Cancel" : "취소",
+ "Remove version name" : "버전 이름 제거",
+ "Save version name" : "버전 이름 저장",
+ "Version name" : "버전 이름",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "이름이 지정된 버전은 유지되며, 저장 공간 할당량이 가득 찼을 때의 자동 정리 목록에서 제외됩니다.",
+ "Initial version restored" : "초기 버전이 복원됨",
+ "Version restored" : "버전이 복원됨",
+ "Could not restore version" : "버전을 복원할 수 없음",
+ "Could not delete version" : "버전을 삭제할 수 없음"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/lb.js b/apps/files_versions/l10n/lb.js
deleted file mode 100644
index d0339a4fd2a..00000000000
--- a/apps/files_versions/l10n/lb.js
+++ /dev/null
@@ -1,10 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiounen",
- "Failed to revert {file} to revision {timestamp}." : "Konnt {file} net op d'Versioun {timestamp} zrécksetzen.",
- "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"],
- "Restore" : "Zrécksetzen",
- "No other versions available" : "Keng aner Versiounen disponibel"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/lb.json b/apps/files_versions/l10n/lb.json
deleted file mode 100644
index 68b63f27485..00000000000
--- a/apps/files_versions/l10n/lb.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "translations": {
- "Versions" : "Versiounen",
- "Failed to revert {file} to revision {timestamp}." : "Konnt {file} net op d'Versioun {timestamp} zrécksetzen.",
- "_%n byte_::_%n bytes_" : ["%n Byte","%n Bytes"],
- "Restore" : "Zrécksetzen",
- "No other versions available" : "Keng aner Versiounen disponibel"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/lt_LT.js b/apps/files_versions/l10n/lt_LT.js
index 1b35bc96d8d..101281dae52 100644
--- a/apps/files_versions/l10n/lt_LT.js
+++ b/apps/files_versions/l10n/lt_LT.js
@@ -3,10 +3,20 @@ OC.L10N.register(
{
"Versions" : "Versijos",
"This application automatically maintains older versions of files that are changed." : "Ši programa automatiškai palaiko senesnes pakeistų failų versijas.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ši programa automatiškai palaiko senesnes pakeistų failų versijas. Kai ji įjungiama, kiekvieno naudotojo kataloge yra nustatomas paslėptų versijų aplankas, kuris naudojamas senoms failų versijoms saugoti. Naudotojas naudodamas žiniatinklio sąsają gali bet kada grįžti prie senesnės versijos. Programa automatiškai administruoja versijų aplanką ir užtikrina, kad nauotojui nepritrūktų suteiktos vietos dėl versijavimo.\n\t\t Be to, programa užtikrina, kad versijavimas nenaudotų daugiau nei 50% naudotojui suteiktos laisvos vietos. Jei saugomos versijos viršija šią ribą, programa pirmiausia ištrins seniausias versijas, kol pasieks šią ribą. Daugiau informacijos galima rasti versijavimo dokumentacijoje.",
- "Failed to revert {file} to revision {timestamp}." : "Nepavyko atstatyti {file} versijos {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų","%n baitas"],
- "Restore" : "Atkurti",
- "No other versions available" : "Nėra kitų prieinamų versijų"
+ "Current version" : "Dabartinė versija",
+ "Initial version" : "Pradinė versija",
+ "You" : "Jūs",
+ "Edit version name" : "Taisyti versijos pavadinimą",
+ "Compare to current version" : "Palyginti su dabartine versija",
+ "Restore version" : "Atkurti versiją",
+ "Download version" : "Atsisiųsti versiją",
+ "Delete version" : "Ištrinti versiją",
+ "Cancel" : "Atsisakyti",
+ "Remove version name" : "Šalinti versijos pavadinimą",
+ "Save version name" : "Įrašyti versijos pavadinimą",
+ "Version name" : "Versijos pavadinimas",
+ "Version restored" : "Versija atkurta",
+ "Could not restore version" : "Nepavyko atkurti versijos",
+ "Could not delete version" : "Nepavyko ištrinti versijos"
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
diff --git a/apps/files_versions/l10n/lt_LT.json b/apps/files_versions/l10n/lt_LT.json
index d49038a9524..6f0ce5d3c6d 100644
--- a/apps/files_versions/l10n/lt_LT.json
+++ b/apps/files_versions/l10n/lt_LT.json
@@ -1,10 +1,20 @@
{ "translations": {
"Versions" : "Versijos",
"This application automatically maintains older versions of files that are changed." : "Ši programa automatiškai palaiko senesnes pakeistų failų versijas.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ši programa automatiškai palaiko senesnes pakeistų failų versijas. Kai ji įjungiama, kiekvieno naudotojo kataloge yra nustatomas paslėptų versijų aplankas, kuris naudojamas senoms failų versijoms saugoti. Naudotojas naudodamas žiniatinklio sąsają gali bet kada grįžti prie senesnės versijos. Programa automatiškai administruoja versijų aplanką ir užtikrina, kad nauotojui nepritrūktų suteiktos vietos dėl versijavimo.\n\t\t Be to, programa užtikrina, kad versijavimas nenaudotų daugiau nei 50% naudotojui suteiktos laisvos vietos. Jei saugomos versijos viršija šią ribą, programa pirmiausia ištrins seniausias versijas, kol pasieks šią ribą. Daugiau informacijos galima rasti versijavimo dokumentacijoje.",
- "Failed to revert {file} to revision {timestamp}." : "Nepavyko atstatyti {file} versijos {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų","%n baitas"],
- "Restore" : "Atkurti",
- "No other versions available" : "Nėra kitų prieinamų versijų"
+ "Current version" : "Dabartinė versija",
+ "Initial version" : "Pradinė versija",
+ "You" : "Jūs",
+ "Edit version name" : "Taisyti versijos pavadinimą",
+ "Compare to current version" : "Palyginti su dabartine versija",
+ "Restore version" : "Atkurti versiją",
+ "Download version" : "Atsisiųsti versiją",
+ "Delete version" : "Ištrinti versiją",
+ "Cancel" : "Atsisakyti",
+ "Remove version name" : "Šalinti versijos pavadinimą",
+ "Save version name" : "Įrašyti versijos pavadinimą",
+ "Version name" : "Versijos pavadinimas",
+ "Version restored" : "Versija atkurta",
+ "Could not restore version" : "Nepavyko atkurti versijos",
+ "Could not delete version" : "Nepavyko ištrinti versijos"
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/lv.js b/apps/files_versions/l10n/lv.js
deleted file mode 100644
index f61fff9b8d1..00000000000
--- a/apps/files_versions/l10n/lv.js
+++ /dev/null
@@ -1,11 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versijas",
- "This application automatically maintains older versions of files that are changed." : "Šī lietotne automātiski uztur vecākas versijas datnēm, kas tiek izmainītas.",
- "Failed to revert {file} to revision {timestamp}." : "Neizdevās atjaunot {file} no rediģējuma {timestamp} ",
- "_%n byte_::_%n bytes_" : ["%n baiti","%n baiti","%n baiti"],
- "Restore" : "Atjaunot",
- "No other versions available" : "Citas versijas nav pieejamas"
-},
-"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);");
diff --git a/apps/files_versions/l10n/lv.json b/apps/files_versions/l10n/lv.json
deleted file mode 100644
index 7acbe5f7b15..00000000000
--- a/apps/files_versions/l10n/lv.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{ "translations": {
- "Versions" : "Versijas",
- "This application automatically maintains older versions of files that are changed." : "Šī lietotne automātiski uztur vecākas versijas datnēm, kas tiek izmainītas.",
- "Failed to revert {file} to revision {timestamp}." : "Neizdevās atjaunot {file} no rediģējuma {timestamp} ",
- "_%n byte_::_%n bytes_" : ["%n baiti","%n baiti","%n baiti"],
- "Restore" : "Atjaunot",
- "No other versions available" : "Citas versijas nav pieejamas"
-},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/mk.js b/apps/files_versions/l10n/mk.js
index 33b1f2c79d2..0e23cb9241d 100644
--- a/apps/files_versions/l10n/mk.js
+++ b/apps/files_versions/l10n/mk.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Верзии",
"This application automatically maintains older versions of files that are changed." : "Оваа апликација автоматски ги менаџира постарите верзии на датотеките кој се изменети.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Оваа апликација автоматски ги менаџира постарите верзии на датотеките кој се изменети. Кога е овозможена, скриена папка се креира во секој кориснички директориум и се користи за зачувување на постарите верзии на датотеките. Корисникот има можност да врати стара верзија од датотеката во секое време преку веб-интерфејсот, со што се преклопува постоечката верзија на датотеката. Апликацијата автоматски се грижи за верзиите за да не дојде случај да се искористи просторот за складирање на корисникот.\n\t\tПокрај истекот на верзиите, апликацијата за верзии нема да користи повеќе од 50% од тековно достапната квота за верзии. Ако зачуваните верзии ја надминат оваа граница, апликацијата ги брише најстарите верзии на датотеки сè додека не се дојде под ова ограничување. Повеќе информации се достапни во документацијата за верзии на датотеки.",
- "Failed to revert {file} to revision {timestamp}." : "Не успеав да го вратам {file} на ревизијата {timestamp}.",
- "_%n byte_::_%n bytes_" : ["1 бајт","%n бајти"],
- "Restore" : "Врати",
- "No other versions available" : "Не постојат други верзии"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Оваа апликација автоматски ги менаџира постарите верзии на датотеките кој се изменети. Кога е овозможена, скриена папка се креира во секој кориснички директориум и се користи за зачувување на постарите верзии на датотеките. Корисникот има можност да врати стара верзија од датотеката во секое време преку веб-интерфејсот, со што се преклопува постоечката верзија на датотеката. Апликацијата автоматски се грижи за верзиите за да не дојде случај да се искористи просторот за складирање на корисникот.\n\t\tПокрај истекот на верзиите, апликацијата за верзии нема да користи повеќе од 50% од тековно достапната квота за верзии. Ако зачуваните верзии ја надминат оваа граница, апликацијата ги брише најстарите верзии на датотеки сè додека не се дојде под ова ограничување. Повеќе информации се достапни во документацијата за верзии на датотеки.",
+ "Current version" : "Моментална верзија",
+ "Initial version" : "Првична верзија",
+ "You" : "Вас",
+ "Actions for version from {versionHumanExplicitDate}" : "Акции за верзии од {versionHumanExplicitDate}",
+ "Name this version" : "Додај име на оваа верзијата",
+ "Edit version name" : "Промени име на верзијата",
+ "Compare to current version" : "Спореди со моменталната верзија",
+ "Restore version" : "Врати ја оваа верзија",
+ "Download version" : "Преземи верзија",
+ "Delete version" : "Избриши верзија",
+ "Cancel" : "Откажи",
+ "Remove version name" : "Избриши име на верзијата",
+ "Save version name" : "Зачувај име на верзија",
+ "Version name" : "Име на верзијата",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именуваните верзии опстојуваат и се исклучени од автоматско чистење кога вашата квота за складирање е полна.",
+ "Initial version restored" : "Почетната верзијата е вратена",
+ "Version restored" : "Верзијата е вратена",
+ "Could not restore version" : "Неможе да се врати верзијата",
+ "Could not set version label" : "Неможе да се постави ознака на верзијата",
+ "Could not delete version" : "Неможе да се избрише верзијата",
+ "File versions" : "Верзии на датотеки"
},
"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;");
diff --git a/apps/files_versions/l10n/mk.json b/apps/files_versions/l10n/mk.json
index c85d05fd764..0193422f6a0 100644
--- a/apps/files_versions/l10n/mk.json
+++ b/apps/files_versions/l10n/mk.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Верзии",
"This application automatically maintains older versions of files that are changed." : "Оваа апликација автоматски ги менаџира постарите верзии на датотеките кој се изменети.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Оваа апликација автоматски ги менаџира постарите верзии на датотеките кој се изменети. Кога е овозможена, скриена папка се креира во секој кориснички директориум и се користи за зачувување на постарите верзии на датотеките. Корисникот има можност да врати стара верзија од датотеката во секое време преку веб-интерфејсот, со што се преклопува постоечката верзија на датотеката. Апликацијата автоматски се грижи за верзиите за да не дојде случај да се искористи просторот за складирање на корисникот.\n\t\tПокрај истекот на верзиите, апликацијата за верзии нема да користи повеќе од 50% од тековно достапната квота за верзии. Ако зачуваните верзии ја надминат оваа граница, апликацијата ги брише најстарите верзии на датотеки сè додека не се дојде под ова ограничување. Повеќе информации се достапни во документацијата за верзии на датотеки.",
- "Failed to revert {file} to revision {timestamp}." : "Не успеав да го вратам {file} на ревизијата {timestamp}.",
- "_%n byte_::_%n bytes_" : ["1 бајт","%n бајти"],
- "Restore" : "Врати",
- "No other versions available" : "Не постојат други верзии"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Оваа апликација автоматски ги менаџира постарите верзии на датотеките кој се изменети. Кога е овозможена, скриена папка се креира во секој кориснички директориум и се користи за зачувување на постарите верзии на датотеките. Корисникот има можност да врати стара верзија од датотеката во секое време преку веб-интерфејсот, со што се преклопува постоечката верзија на датотеката. Апликацијата автоматски се грижи за верзиите за да не дојде случај да се искористи просторот за складирање на корисникот.\n\t\tПокрај истекот на верзиите, апликацијата за верзии нема да користи повеќе од 50% од тековно достапната квота за верзии. Ако зачуваните верзии ја надминат оваа граница, апликацијата ги брише најстарите верзии на датотеки сè додека не се дојде под ова ограничување. Повеќе информации се достапни во документацијата за верзии на датотеки.",
+ "Current version" : "Моментална верзија",
+ "Initial version" : "Првична верзија",
+ "You" : "Вас",
+ "Actions for version from {versionHumanExplicitDate}" : "Акции за верзии од {versionHumanExplicitDate}",
+ "Name this version" : "Додај име на оваа верзијата",
+ "Edit version name" : "Промени име на верзијата",
+ "Compare to current version" : "Спореди со моменталната верзија",
+ "Restore version" : "Врати ја оваа верзија",
+ "Download version" : "Преземи верзија",
+ "Delete version" : "Избриши верзија",
+ "Cancel" : "Откажи",
+ "Remove version name" : "Избриши име на верзијата",
+ "Save version name" : "Зачувај име на верзија",
+ "Version name" : "Име на верзијата",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именуваните верзии опстојуваат и се исклучени од автоматско чистење кога вашата квота за складирање е полна.",
+ "Initial version restored" : "Почетната верзијата е вратена",
+ "Version restored" : "Верзијата е вратена",
+ "Could not restore version" : "Неможе да се врати верзијата",
+ "Could not set version label" : "Неможе да се постави ознака на верзијата",
+ "Could not delete version" : "Неможе да се избрише верзијата",
+ "File versions" : "Верзии на датотеки"
},"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ms_MY.js b/apps/files_versions/l10n/ms_MY.js
deleted file mode 100644
index 4ec22f9b141..00000000000
--- a/apps/files_versions/l10n/ms_MY.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versi",
- "Failed to revert {file} to revision {timestamp}." : "Gagal kembalikan {file} ke semakan {timestamp}.",
- "Restore" : "Pulihkan",
- "No other versions available" : "Tiada lagi versi lain"
-},
-"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/ms_MY.json b/apps/files_versions/l10n/ms_MY.json
deleted file mode 100644
index 7510c52ceb8..00000000000
--- a/apps/files_versions/l10n/ms_MY.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versi",
- "Failed to revert {file} to revision {timestamp}." : "Gagal kembalikan {file} ke semakan {timestamp}.",
- "Restore" : "Pulihkan",
- "No other versions available" : "Tiada lagi versi lain"
-},"pluralForm" :"nplurals=1; plural=0;"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/nb.js b/apps/files_versions/l10n/nb.js
index 5943c227d62..16e91d78621 100644
--- a/apps/files_versions/l10n/nb.js
+++ b/apps/files_versions/l10n/nb.js
@@ -3,10 +3,26 @@ OC.L10N.register(
{
"Versions" : "Versjoner",
"This application automatically maintains older versions of files that are changed." : "Dette programmet vedlikeholder eldre versjoner av endrede filer.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Dette programmet vedlikeholder eldre versjoner av endrede filer. Når den aktiveres, legges det inn en skjult mappe i alle brukeres kataloger og brukes til å lagre eldre filversjoner. En bruker kan når som helst gjenopprette til en eldre versjon gjennom web-grensesnittet, og gjøre den erstattede filen til en versjon. Programmet vedlikeholder automatisk versjonsmappen for å sikre at brukeren ikke går tom for kvoten på grunn av for mange versjoner av en fil.\n\n\t\tI tillegg til at versjoner opphører, passer programmet på at den aldri bruker mer enn 50% av brukerens tilgjengelige plass. Hvis lagrede filversjoner går over denne grensen, vil appen slette de eldste versjonene først til det treffer grensen. Mer informasjon er tilgjengelig i Versions dokumentasjon.",
- "Failed to revert {file} to revision {timestamp}." : "Klarte ikke å tilbakeføre {file} til revisjon {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Gjenopprett",
- "No other versions available" : "Ingen andre versjoner tilgjengelig"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Dette programmet opprettholder automatisk eldre versjoner av filer som endres. Når den er aktivert, klargjøres en mappe for skjulte versjoner i hver brukers katalog og brukes til å lagre gamle filversjoner. En bruker kan når som helst gå tilbake til en eldre versjon via webgrensesnittet, og den erstattede filen blir en versjon. Appen administrerer automatisk versjonsmappen for å sikre at brukeren ikke går tom for kvote på grunn av versjoner.\n\t\tI tillegg til at versjoner opphører, sørger versjonsappen for aldri å bruke mer enn 50% av brukerens tilgjengelige ledige plass. Hvis lagrede versjoner overskrider denne grensen, sletter appen de eldste versjonene først til den oppfyller denne grensen. Du finner mer informasjon i dokumentasjonen for Versions.",
+ "Current version" : "Nåværende versjon",
+ "Initial version" : "Opprinnelig versjon",
+ "You" : "Du",
+ "Actions for version from {versionHumanExplicitDate}" : "Handlinger for versjon fra {versionHumanExplicitDate}",
+ "Name this version" : "Navngi denne versjonen",
+ "Edit version name" : "Rediger versjonsnavn",
+ "Compare to current version" : "Sammenlign med gjeldende versjon",
+ "Restore version" : "Gjenopprett versjon",
+ "Download version" : "Last ned versjon",
+ "Delete version" : "Slett versjon",
+ "Cancel" : "Avbryt",
+ "Remove version name" : "Fjern versjonsnavn",
+ "Save version name" : "Lagre versjonsnavn",
+ "Version name" : "Versjonsnavn",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Navngitte versjoner beholdes og utelates fra automatiske oppryddinger når lagringskvoten er full.",
+ "Initial version restored" : "Opprinnelig versjon opprettet",
+ "Version restored" : "Versjon gjenopprettet",
+ "Could not restore version" : "Kunne ikke gjenopprette versjon",
+ "Could not set version label" : "Kunne ikke angi versjonsetikett",
+ "Could not delete version" : "Kunne ikke slette versjon"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/nb.json b/apps/files_versions/l10n/nb.json
index 963c83239ac..a08659e07ac 100644
--- a/apps/files_versions/l10n/nb.json
+++ b/apps/files_versions/l10n/nb.json
@@ -1,10 +1,26 @@
{ "translations": {
"Versions" : "Versjoner",
"This application automatically maintains older versions of files that are changed." : "Dette programmet vedlikeholder eldre versjoner av endrede filer.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Dette programmet vedlikeholder eldre versjoner av endrede filer. Når den aktiveres, legges det inn en skjult mappe i alle brukeres kataloger og brukes til å lagre eldre filversjoner. En bruker kan når som helst gjenopprette til en eldre versjon gjennom web-grensesnittet, og gjøre den erstattede filen til en versjon. Programmet vedlikeholder automatisk versjonsmappen for å sikre at brukeren ikke går tom for kvoten på grunn av for mange versjoner av en fil.\n\n\t\tI tillegg til at versjoner opphører, passer programmet på at den aldri bruker mer enn 50% av brukerens tilgjengelige plass. Hvis lagrede filversjoner går over denne grensen, vil appen slette de eldste versjonene først til det treffer grensen. Mer informasjon er tilgjengelig i Versions dokumentasjon.",
- "Failed to revert {file} to revision {timestamp}." : "Klarte ikke å tilbakeføre {file} til revisjon {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Gjenopprett",
- "No other versions available" : "Ingen andre versjoner tilgjengelig"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Dette programmet opprettholder automatisk eldre versjoner av filer som endres. Når den er aktivert, klargjøres en mappe for skjulte versjoner i hver brukers katalog og brukes til å lagre gamle filversjoner. En bruker kan når som helst gå tilbake til en eldre versjon via webgrensesnittet, og den erstattede filen blir en versjon. Appen administrerer automatisk versjonsmappen for å sikre at brukeren ikke går tom for kvote på grunn av versjoner.\n\t\tI tillegg til at versjoner opphører, sørger versjonsappen for aldri å bruke mer enn 50% av brukerens tilgjengelige ledige plass. Hvis lagrede versjoner overskrider denne grensen, sletter appen de eldste versjonene først til den oppfyller denne grensen. Du finner mer informasjon i dokumentasjonen for Versions.",
+ "Current version" : "Nåværende versjon",
+ "Initial version" : "Opprinnelig versjon",
+ "You" : "Du",
+ "Actions for version from {versionHumanExplicitDate}" : "Handlinger for versjon fra {versionHumanExplicitDate}",
+ "Name this version" : "Navngi denne versjonen",
+ "Edit version name" : "Rediger versjonsnavn",
+ "Compare to current version" : "Sammenlign med gjeldende versjon",
+ "Restore version" : "Gjenopprett versjon",
+ "Download version" : "Last ned versjon",
+ "Delete version" : "Slett versjon",
+ "Cancel" : "Avbryt",
+ "Remove version name" : "Fjern versjonsnavn",
+ "Save version name" : "Lagre versjonsnavn",
+ "Version name" : "Versjonsnavn",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Navngitte versjoner beholdes og utelates fra automatiske oppryddinger når lagringskvoten er full.",
+ "Initial version restored" : "Opprinnelig versjon opprettet",
+ "Version restored" : "Versjon gjenopprettet",
+ "Could not restore version" : "Kunne ikke gjenopprette versjon",
+ "Could not set version label" : "Kunne ikke angi versjonsetikett",
+ "Could not delete version" : "Kunne ikke slette versjon"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/nl.js b/apps/files_versions/l10n/nl.js
index dcf0a239203..7500ff8b9f4 100644
--- a/apps/files_versions/l10n/nl.js
+++ b/apps/files_versions/l10n/nl.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versies",
"This application automatically maintains older versions of files that are changed." : "Deze applicatie beheert automatisch oudere versies van gewijzigde bestanden.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Deze applicatie onderhoudt automatisch oudere versies van bestanden die zijn gewijzigd. Indien ingeschakeld, wordt een map met verborgen versies geplaatst in de directory van elke gebruiker en wordt deze gebruikt om oude bestandsversies op te slaan. Een gebruiker kan via de webinterface op elk gewenst moment terugkeren naar een oudere versie, waarbij het vervangen bestand de nieuwe versie wordt. De app beheert automatisch de map om ervoor te zorgen dat het quotum niet opraakt vanwege versiebeheer.\n\t\tNaast het beheer van versies, zorgt de app er ook voor dat nooit meer dan 50% van de momenteel beschikbare vrije ruimte van de gebruiker wordt gebruikt. Als opgeslagen versies deze limiet overschrijden, verwijdert de app de oudste versies eerst totdat de limiet is bereikt. Meer informatie is beschikbaar in de documentatie van Versiebeheer.",
- "Failed to revert {file} to revision {timestamp}." : "Kon {file} niet terugdraaien naar revisie {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Herstellen",
- "No other versions available" : "Geen andere versies beschikbaar"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Deze applicatie bewaart automatisch oudere versies van bestanden die gewijzigd zijn. Als dit is ingeschakeld, wordt er in de map van elke gebruiker een map met verborgen versies gemaakt waarin oude bestandsversies worden opgeslagen. Een gebruiker kan op elk moment teruggaan naar een oudere versie via de webinterface, waarbij het vervangen bestand een versie wordt. De app beheert de versie map automatisch om ervoor te zorgen dat het account niet zonder quota komt te zitten door versies.\n\t\tNaast het verlopen van versies zorgt de versies-app ervoor dat nooit meer dan 50% van de op dat moment beschikbare vrije ruimte van het account wordt gebruikt. Als opgeslagen versies deze limiet overschrijden, zal de app eerst de oudste versies verwijderen totdat deze limiet is bereikt. Meer informatie is beschikbaar in de documentatie over versies.",
+ "Current version" : "Huidige versie",
+ "Initial version" : "Initiële versie",
+ "You" : "Jij",
+ "Actions for version from {versionHumanExplicitDate}" : "Acties voor versie van {versionHumanExplicitDate}",
+ "Name this version" : "Geef deze versie een naam",
+ "Edit version name" : "Bewerk versie naam",
+ "Compare to current version" : "Vergelijk met huidige versie",
+ "Restore version" : "Herstel versie",
+ "Download version" : "Download versie",
+ "Delete version" : "Verwijder versie",
+ "Cancel" : "Annuleren",
+ "Remove version name" : "Verwijder versie naam",
+ "Save version name" : "Sla versie naam op",
+ "Version name" : "Versie naam",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Versies met naam worden bewaard en uitgesloten van automatische opschoning wanneer je opslagquota vol is.",
+ "Initial version restored" : "Initiële versie hersteld",
+ "Version restored" : "Versie hersteld",
+ "Could not restore version" : "Kon versie niet herstellen",
+ "Could not set version label" : "Kon versie label niet instellen",
+ "Could not delete version" : "Kon versie niet verwijderen",
+ "File versions" : "Bestandsversies"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/nl.json b/apps/files_versions/l10n/nl.json
index 726059fc601..da0eb03c679 100644
--- a/apps/files_versions/l10n/nl.json
+++ b/apps/files_versions/l10n/nl.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versies",
"This application automatically maintains older versions of files that are changed." : "Deze applicatie beheert automatisch oudere versies van gewijzigde bestanden.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Deze applicatie onderhoudt automatisch oudere versies van bestanden die zijn gewijzigd. Indien ingeschakeld, wordt een map met verborgen versies geplaatst in de directory van elke gebruiker en wordt deze gebruikt om oude bestandsversies op te slaan. Een gebruiker kan via de webinterface op elk gewenst moment terugkeren naar een oudere versie, waarbij het vervangen bestand de nieuwe versie wordt. De app beheert automatisch de map om ervoor te zorgen dat het quotum niet opraakt vanwege versiebeheer.\n\t\tNaast het beheer van versies, zorgt de app er ook voor dat nooit meer dan 50% van de momenteel beschikbare vrije ruimte van de gebruiker wordt gebruikt. Als opgeslagen versies deze limiet overschrijden, verwijdert de app de oudste versies eerst totdat de limiet is bereikt. Meer informatie is beschikbaar in de documentatie van Versiebeheer.",
- "Failed to revert {file} to revision {timestamp}." : "Kon {file} niet terugdraaien naar revisie {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Herstellen",
- "No other versions available" : "Geen andere versies beschikbaar"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Deze applicatie bewaart automatisch oudere versies van bestanden die gewijzigd zijn. Als dit is ingeschakeld, wordt er in de map van elke gebruiker een map met verborgen versies gemaakt waarin oude bestandsversies worden opgeslagen. Een gebruiker kan op elk moment teruggaan naar een oudere versie via de webinterface, waarbij het vervangen bestand een versie wordt. De app beheert de versie map automatisch om ervoor te zorgen dat het account niet zonder quota komt te zitten door versies.\n\t\tNaast het verlopen van versies zorgt de versies-app ervoor dat nooit meer dan 50% van de op dat moment beschikbare vrije ruimte van het account wordt gebruikt. Als opgeslagen versies deze limiet overschrijden, zal de app eerst de oudste versies verwijderen totdat deze limiet is bereikt. Meer informatie is beschikbaar in de documentatie over versies.",
+ "Current version" : "Huidige versie",
+ "Initial version" : "Initiële versie",
+ "You" : "Jij",
+ "Actions for version from {versionHumanExplicitDate}" : "Acties voor versie van {versionHumanExplicitDate}",
+ "Name this version" : "Geef deze versie een naam",
+ "Edit version name" : "Bewerk versie naam",
+ "Compare to current version" : "Vergelijk met huidige versie",
+ "Restore version" : "Herstel versie",
+ "Download version" : "Download versie",
+ "Delete version" : "Verwijder versie",
+ "Cancel" : "Annuleren",
+ "Remove version name" : "Verwijder versie naam",
+ "Save version name" : "Sla versie naam op",
+ "Version name" : "Versie naam",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Versies met naam worden bewaard en uitgesloten van automatische opschoning wanneer je opslagquota vol is.",
+ "Initial version restored" : "Initiële versie hersteld",
+ "Version restored" : "Versie hersteld",
+ "Could not restore version" : "Kon versie niet herstellen",
+ "Could not set version label" : "Kon versie label niet instellen",
+ "Could not delete version" : "Kon versie niet verwijderen",
+ "File versions" : "Bestandsversies"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/nn_NO.js b/apps/files_versions/l10n/nn_NO.js
deleted file mode 100644
index 16ed15afe20..00000000000
--- a/apps/files_versions/l10n/nn_NO.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Utgåver",
- "Failed to revert {file} to revision {timestamp}." : "Klarte ikkje å tilbakestilla {file} til utgåva {timestamp}.",
- "Restore" : "Gjenopprett",
- "No other versions available" : "Ingen andre utgåver tilgjengeleg"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/nn_NO.json b/apps/files_versions/l10n/nn_NO.json
deleted file mode 100644
index ea92d533333..00000000000
--- a/apps/files_versions/l10n/nn_NO.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Utgåver",
- "Failed to revert {file} to revision {timestamp}." : "Klarte ikkje å tilbakestilla {file} til utgåva {timestamp}.",
- "Restore" : "Gjenopprett",
- "No other versions available" : "Ingen andre utgåver tilgjengeleg"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/oc.js b/apps/files_versions/l10n/oc.js
deleted file mode 100644
index c5f8550abe0..00000000000
--- a/apps/files_versions/l10n/oc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versions",
- "_%n byte_::_%n bytes_" : ["%n octet","%n octets"],
- "Restore" : "Restaurar",
- "No other versions available" : "Cap d’autra version pas disponibla"
-},
-"nplurals=2; plural=(n > 1);");
diff --git a/apps/files_versions/l10n/oc.json b/apps/files_versions/l10n/oc.json
deleted file mode 100644
index af314939d07..00000000000
--- a/apps/files_versions/l10n/oc.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{ "translations": {
- "Versions" : "Versions",
- "_%n byte_::_%n bytes_" : ["%n octet","%n octets"],
- "Restore" : "Restaurar",
- "No other versions available" : "Cap d’autra version pas disponibla"
-},"pluralForm" :"nplurals=2; plural=(n > 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/pl.js b/apps/files_versions/l10n/pl.js
index a7080f015f2..5ff9d71c737 100644
--- a/apps/files_versions/l10n/pl.js
+++ b/apps/files_versions/l10n/pl.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Wersje",
"This application automatically maintains older versions of files that are changed." : "Aplikacja przechowuje starsze wersje plików poddanych modyfikacji.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikacja automatycznie utrzymuje starsze wersje zmienionych plików. Po włączeniu, ukryty katalog versions jest udostępniany w każdym katalogu użytkownika i służy do przechowywania starych wersji plików. Użytkownik może w dowolnym momencie powrócić do starszej wersji za pośrednictwem strony internetowej, a zastąpiony plik staje się jego wersją. Aplikacja automatycznie zarządza katalogiem versions, aby zapewnić użytkownikowi ciągłość wersji.\n\t\tOprócz wygaśnięcia wersji, aplikacja Versions zapewnia, że nigdy nie będzie wykorzystywać więcej niż 50% dostępnej przestrzeni użytkownika. Jeśli przechowywane wersje przekroczą ten limit, aplikacja usunie najpierw najstarsze wersje, aż do osiągnięcia tego limitu. Więcej informacji można znaleźć w dokumentacji Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Nie udało się przywrócić {file} do wersji z {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajtów","%n bajtów","%n bajtów"],
- "Restore" : "Przywróć",
- "No other versions available" : "Nie są dostępne żadne inne wersje"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ta aplikacja automatycznie utrzymuje starsze wersje plików, które zostały zmienione. Po włączeniu, w katalogu każdego użytkownika udostępniany jest katalog wersji ukrytych, który służy do przechowywania starych wersji plików. Użytkownik może w dowolnym momencie powrócić do starszej wersji za pośrednictwem interfejsu internetowego, a zastąpiony plik staje się wersją. Aplikacja automatycznie zarządza katalogiem wersji, aby mieć pewność, że na koncie nie zabraknie miejsca z powodu wersji.\n\t\tOprócz wygaszania wersji aplikacja sprawdza, by nigdy nie zostało wykorzystane więcej niż 50% aktualnie dostępnego wolnego miejsca na koncie. Jeśli przechowywane wersje przekroczą ten limit, aplikacja najpierw usunie najstarsze wersje, aż do osiągnięcia tego limitu. Więcej informacji można znaleźć w dokumentacji aplikacji wersji.",
+ "Current version" : "Obecna wersja",
+ "Initial version" : "Początkowa wersja",
+ "You" : "Ty",
+ "Actions for version from {versionHumanExplicitDate}" : "Działania dla wersji z {versionHumanExplicitDate}",
+ "Name this version" : "Nazwij tę wersję",
+ "Edit version name" : "Edytuj nazwę wersji",
+ "Compare to current version" : "Porównaj z aktualną wersją",
+ "Restore version" : "Przywróć wersję",
+ "Download version" : "Pobierz wersję",
+ "Delete version" : "Usuń wersję",
+ "Cancel" : "Anuluj",
+ "Remove version name" : "Usuń nazwę wersji",
+ "Save version name" : "Zapis nazwę wersji",
+ "Version name" : "Nazwa wersji",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Nazwane wersje są utrwalane i wykluczane z automatycznego czyszczenia, gdy limit przechowywania zostanie przekroczony.",
+ "Initial version restored" : "Przywrócono wersję początkową",
+ "Version restored" : "Wersja przywrócona",
+ "Could not restore version" : "Nie można przywrócić wersji",
+ "Could not set version label" : "Nie można ustawić etykiety wersji",
+ "Could not delete version" : "Nie można usunąć wersji",
+ "File versions" : "Wersje plików"
},
"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);");
diff --git a/apps/files_versions/l10n/pl.json b/apps/files_versions/l10n/pl.json
index 7cad3b6c4f0..27030065c9e 100644
--- a/apps/files_versions/l10n/pl.json
+++ b/apps/files_versions/l10n/pl.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Wersje",
"This application automatically maintains older versions of files that are changed." : "Aplikacja przechowuje starsze wersje plików poddanych modyfikacji.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikacja automatycznie utrzymuje starsze wersje zmienionych plików. Po włączeniu, ukryty katalog versions jest udostępniany w każdym katalogu użytkownika i służy do przechowywania starych wersji plików. Użytkownik może w dowolnym momencie powrócić do starszej wersji za pośrednictwem strony internetowej, a zastąpiony plik staje się jego wersją. Aplikacja automatycznie zarządza katalogiem versions, aby zapewnić użytkownikowi ciągłość wersji.\n\t\tOprócz wygaśnięcia wersji, aplikacja Versions zapewnia, że nigdy nie będzie wykorzystywać więcej niż 50% dostępnej przestrzeni użytkownika. Jeśli przechowywane wersje przekroczą ten limit, aplikacja usunie najpierw najstarsze wersje, aż do osiągnięcia tego limitu. Więcej informacji można znaleźć w dokumentacji Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Nie udało się przywrócić {file} do wersji z {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajtów","%n bajtów","%n bajtów"],
- "Restore" : "Przywróć",
- "No other versions available" : "Nie są dostępne żadne inne wersje"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ta aplikacja automatycznie utrzymuje starsze wersje plików, które zostały zmienione. Po włączeniu, w katalogu każdego użytkownika udostępniany jest katalog wersji ukrytych, który służy do przechowywania starych wersji plików. Użytkownik może w dowolnym momencie powrócić do starszej wersji za pośrednictwem interfejsu internetowego, a zastąpiony plik staje się wersją. Aplikacja automatycznie zarządza katalogiem wersji, aby mieć pewność, że na koncie nie zabraknie miejsca z powodu wersji.\n\t\tOprócz wygaszania wersji aplikacja sprawdza, by nigdy nie zostało wykorzystane więcej niż 50% aktualnie dostępnego wolnego miejsca na koncie. Jeśli przechowywane wersje przekroczą ten limit, aplikacja najpierw usunie najstarsze wersje, aż do osiągnięcia tego limitu. Więcej informacji można znaleźć w dokumentacji aplikacji wersji.",
+ "Current version" : "Obecna wersja",
+ "Initial version" : "Początkowa wersja",
+ "You" : "Ty",
+ "Actions for version from {versionHumanExplicitDate}" : "Działania dla wersji z {versionHumanExplicitDate}",
+ "Name this version" : "Nazwij tę wersję",
+ "Edit version name" : "Edytuj nazwę wersji",
+ "Compare to current version" : "Porównaj z aktualną wersją",
+ "Restore version" : "Przywróć wersję",
+ "Download version" : "Pobierz wersję",
+ "Delete version" : "Usuń wersję",
+ "Cancel" : "Anuluj",
+ "Remove version name" : "Usuń nazwę wersji",
+ "Save version name" : "Zapis nazwę wersji",
+ "Version name" : "Nazwa wersji",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Nazwane wersje są utrwalane i wykluczane z automatycznego czyszczenia, gdy limit przechowywania zostanie przekroczony.",
+ "Initial version restored" : "Przywrócono wersję początkową",
+ "Version restored" : "Wersja przywrócona",
+ "Could not restore version" : "Nie można przywrócić wersji",
+ "Could not set version label" : "Nie można ustawić etykiety wersji",
+ "Could not delete version" : "Nie można usunąć wersji",
+ "File versions" : "Wersje plików"
},"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/pt_BR.js b/apps/files_versions/l10n/pt_BR.js
index 2ed89e90b2b..bb0880450a1 100644
--- a/apps/files_versions/l10n/pt_BR.js
+++ b/apps/files_versions/l10n/pt_BR.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versões",
"This application automatically maintains older versions of files that are changed." : "Este aplicativo mantém automaticamente versões mais antigas de arquivos que são alterados.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Este aplicativo mantém automaticamente versões mais antigas de arquivos alterados. Quando ativado, uma pasta oculta de versões é criada no diretório de todos os usuários e é usada para armazenar versões antigas de arquivos. Um usuário pode reverter para uma versão mais antiga através da interface da web a qualquer momento, com o arquivo substituído se tornando uma versão. O aplicativo gerencia automaticamente a pasta de versões para garantir que o usuário não fique sem cota por causa disso.\n\t\tAlém do prazo de validade das versões, o aplicativo garante que nunca use mais de 50% do espaço livre disponível no momento pelo usuário. Se as versões armazenadas excederem esse limite, o aplicativo excluirá as versões mais antigas primeiro até atingir esse limite. Mais informações estão disponíveis na documentação do Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Falha ao reverter {file} para a revisão {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Sem outras versões disponíveis"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Este aplicativo mantém automaticamente versões mais antigas de arquivos que foram alterados. Quando ativada, uma pasta de versões oculta é provisionada no diretório de cada usuário e usada para armazenar versões antigas de arquivos. Um usuário pode reverter para uma versão mais antiga através da interface web a qualquer momento, com o arquivo substituído se tornando uma versão. O aplicativo gerencia automaticamente a pasta de versões para garantir que a conta não fique sem cota por causa das versões. \n\t\tAlém da expiração das versões, o aplicativo de versões garante nunca usar mais de 50% do espaço livre disponível atualmente na conta. Se as versões armazenadas excederem esse limite, o aplicativo excluirá primeiro as versões mais antigas até atingir esse limite. Mais informações estão disponíveis na documentação de Versões.",
+ "Current version" : "Versão atual",
+ "Initial version" : "Versão inicial",
+ "You" : "Você",
+ "Actions for version from {versionHumanExplicitDate}" : "Ações para versão de {versionHumanExplicitDate}",
+ "Name this version" : "Nomear esta versão",
+ "Edit version name" : "Editar nome da versão",
+ "Compare to current version" : "Comparar com a versão atual",
+ "Restore version" : "Restaurar versão",
+ "Download version" : "Baixar versão",
+ "Delete version" : "Excluir versão",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Remover nome da versão",
+ "Save version name" : "Salvar nome da versão",
+ "Version name" : "Nome da versão",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "As versões nomeadas são mantidas e excluídas das limpezas automáticas quando sua cota de armazenamento está cheia.",
+ "Initial version restored" : "Versão inicial restaurada",
+ "Version restored" : "Versão restaurada",
+ "Could not restore version" : "Não foi possível restaurar esta versão",
+ "Could not set version label" : "Não foi possível definir o rótulo da versão",
+ "Could not delete version" : "Não foi possível excluir a versão",
+ "File versions" : "Versões do arquivo"
},
-"nplurals=2; plural=(n > 1);");
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/files_versions/l10n/pt_BR.json b/apps/files_versions/l10n/pt_BR.json
index e2dbb6ceefb..b213f3724a8 100644
--- a/apps/files_versions/l10n/pt_BR.json
+++ b/apps/files_versions/l10n/pt_BR.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versões",
"This application automatically maintains older versions of files that are changed." : "Este aplicativo mantém automaticamente versões mais antigas de arquivos que são alterados.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Este aplicativo mantém automaticamente versões mais antigas de arquivos alterados. Quando ativado, uma pasta oculta de versões é criada no diretório de todos os usuários e é usada para armazenar versões antigas de arquivos. Um usuário pode reverter para uma versão mais antiga através da interface da web a qualquer momento, com o arquivo substituído se tornando uma versão. O aplicativo gerencia automaticamente a pasta de versões para garantir que o usuário não fique sem cota por causa disso.\n\t\tAlém do prazo de validade das versões, o aplicativo garante que nunca use mais de 50% do espaço livre disponível no momento pelo usuário. Se as versões armazenadas excederem esse limite, o aplicativo excluirá as versões mais antigas primeiro até atingir esse limite. Mais informações estão disponíveis na documentação do Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Falha ao reverter {file} para a revisão {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Sem outras versões disponíveis"
-},"pluralForm" :"nplurals=2; plural=(n > 1);"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Este aplicativo mantém automaticamente versões mais antigas de arquivos que foram alterados. Quando ativada, uma pasta de versões oculta é provisionada no diretório de cada usuário e usada para armazenar versões antigas de arquivos. Um usuário pode reverter para uma versão mais antiga através da interface web a qualquer momento, com o arquivo substituído se tornando uma versão. O aplicativo gerencia automaticamente a pasta de versões para garantir que a conta não fique sem cota por causa das versões. \n\t\tAlém da expiração das versões, o aplicativo de versões garante nunca usar mais de 50% do espaço livre disponível atualmente na conta. Se as versões armazenadas excederem esse limite, o aplicativo excluirá primeiro as versões mais antigas até atingir esse limite. Mais informações estão disponíveis na documentação de Versões.",
+ "Current version" : "Versão atual",
+ "Initial version" : "Versão inicial",
+ "You" : "Você",
+ "Actions for version from {versionHumanExplicitDate}" : "Ações para versão de {versionHumanExplicitDate}",
+ "Name this version" : "Nomear esta versão",
+ "Edit version name" : "Editar nome da versão",
+ "Compare to current version" : "Comparar com a versão atual",
+ "Restore version" : "Restaurar versão",
+ "Download version" : "Baixar versão",
+ "Delete version" : "Excluir versão",
+ "Cancel" : "Cancelar",
+ "Remove version name" : "Remover nome da versão",
+ "Save version name" : "Salvar nome da versão",
+ "Version name" : "Nome da versão",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "As versões nomeadas são mantidas e excluídas das limpezas automáticas quando sua cota de armazenamento está cheia.",
+ "Initial version restored" : "Versão inicial restaurada",
+ "Version restored" : "Versão restaurada",
+ "Could not restore version" : "Não foi possível restaurar esta versão",
+ "Could not set version label" : "Não foi possível definir o rótulo da versão",
+ "Could not delete version" : "Não foi possível excluir a versão",
+ "File versions" : "Versões do arquivo"
+},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/pt_PT.js b/apps/files_versions/l10n/pt_PT.js
deleted file mode 100644
index 8626da4e6fe..00000000000
--- a/apps/files_versions/l10n/pt_PT.js
+++ /dev/null
@@ -1,10 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versões",
- "Failed to revert {file} to revision {timestamp}." : "Falhou a recuperação do ficheiro {file} para a revisão {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Nenhuma outra versão disponível"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/pt_PT.json b/apps/files_versions/l10n/pt_PT.json
deleted file mode 100644
index 93f8de1eefc..00000000000
--- a/apps/files_versions/l10n/pt_PT.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "translations": {
- "Versions" : "Versões",
- "Failed to revert {file} to revision {timestamp}." : "Falhou a recuperação do ficheiro {file} para a revisão {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Restaurar",
- "No other versions available" : "Nenhuma outra versão disponível"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ro.js b/apps/files_versions/l10n/ro.js
deleted file mode 100644
index 0762fe305b5..00000000000
--- a/apps/files_versions/l10n/ro.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiuni",
- "This application automatically maintains older versions of files that are changed." : "Această aplicație păștrează versiunile mai vechi a fișierelor care sunt schimbate.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Această aplicație păștrează versiunile mai vechi a fișierelor care sunt schimbate.Când este activată un dosar ascuns este creeat în dosarul personal al fiecărui utilizator pentru a memora versiunile mai vechi. Un utilizator poate să revină la o versiune mai veche folosind interfața web în orice moment, cu fișierul înlocuit devenind o versiune păstrată. Aplicația are grijă să nu rămână fără spațiu.\n\t\tDe asemenea aplicația are grijă să nu folosească mai mult de 50% din spațiul disponibil. Dacă veriunile vechi depășec această valoare atunci versiunile mai vechi vor fi șterse. Mai multe informații sunt disponibile în documentația aplicației Versiuni.",
- "Failed to revert {file} to revision {timestamp}." : "S-a eșuat restaurarea fișierului {file} la revizia {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n byți","%n byți"],
- "Restore" : "Restaurare",
- "No other versions available" : "Nu există alte versiuni disponibile"
-},
-"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/apps/files_versions/l10n/ro.json b/apps/files_versions/l10n/ro.json
deleted file mode 100644
index 8188fce3cd3..00000000000
--- a/apps/files_versions/l10n/ro.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "Versiuni",
- "This application automatically maintains older versions of files that are changed." : "Această aplicație păștrează versiunile mai vechi a fișierelor care sunt schimbate.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Această aplicație păștrează versiunile mai vechi a fișierelor care sunt schimbate.Când este activată un dosar ascuns este creeat în dosarul personal al fiecărui utilizator pentru a memora versiunile mai vechi. Un utilizator poate să revină la o versiune mai veche folosind interfața web în orice moment, cu fișierul înlocuit devenind o versiune păstrată. Aplicația are grijă să nu rămână fără spațiu.\n\t\tDe asemenea aplicația are grijă să nu folosească mai mult de 50% din spațiul disponibil. Dacă veriunile vechi depășec această valoare atunci versiunile mai vechi vor fi șterse. Mai multe informații sunt disponibile în documentația aplicației Versiuni.",
- "Failed to revert {file} to revision {timestamp}." : "S-a eșuat restaurarea fișierului {file} la revizia {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n byți","%n byți"],
- "Restore" : "Restaurare",
- "No other versions available" : "Nu există alte versiuni disponibile"
-},"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/apps/files_versions/l10n/ru.js b/apps/files_versions/l10n/ru.js
index cc28b1f69ca..ecdf5913c52 100644
--- a/apps/files_versions/l10n/ru.js
+++ b/apps/files_versions/l10n/ru.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Версии",
"This application automatically maintains older versions of files that are changed." : "Приложение служит для обработки старых версий изменённых файлов.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Это приложение предназначено для автоматического управления предыдущими версиями изменённых файлов. При включении этого приложения в каталогах пользователей создаются скрытые папки, предназначенные для хранения предыдущих версий изменённых файлов. Выбор нужной предыдущей версии и возврат к ней выполняется через веб-интерфейс, при этом актуальная версия файла будет заменена выбранной версией. Приложение также автоматически управляет глубиной хранения версий файлов, чтобы не превышать выделенные для пользователя квоты.\n\t\tПомимо управления сроком хранения предыдущих версий, приложение следит за тем, что бы общий размер сохранённых версий файлов не превышал 50% выделенного пользователю дискового пространства. При превышении такого лимита будет запущен механизм удаления самых старых версий файлов. Удаление будет производиться до тех пор, пока общий размер всех сохранённых версий файлов вновь не станет менее 50% от квоты использования дискового пространства. Дополнительная информация приведена в руководстве к приложению «Версии».",
- "Failed to revert {file} to revision {timestamp}." : "Не удалось откатить {file} к ревизии {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n байт","%n байта","%n байт","%n байт"],
- "Restore" : "Откатить",
- "No other versions available" : "Другие версии недоступны"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Это приложение автоматически поддерживает старые версии файлов, которые были изменены. Если оно включено, в каталоге каждого пользователя создаётся папка \"Скрытые версии\", которая используется для хранения старых версий файлов. Пользователь может в любой момент вернуться к более старой версии через веб-интерфейс, при этом заменённый файл станет версией. Приложение автоматически управляет папкой версий, чтобы гарантировать, что квота учётной записи не исчерпается из-за изменений версий.\n\t\tВ дополнение к истечению срока действия версий, приложение \"Версии\" гарантирует, что вы никогда не будете использовать более 50% доступного в данный момент свободного места в учётной записи. Если сохранённые версии превысят это ограничение, приложение сначала удалит самые старые версии, пока не достигнет этого ограничения. Более подробная информация доступна в документации по версиям.",
+ "Current version" : "Текущая версия",
+ "Initial version" : "Первоначальная версия",
+ "You" : "Вы",
+ "Actions for version from {versionHumanExplicitDate}" : "Действия для версии из {versionHumanExplicitDate}",
+ "Name this version" : "Обозначить версию",
+ "Edit version name" : "Изменить название версии",
+ "Compare to current version" : "Сравнить с текущей версией",
+ "Restore version" : "Востановить версию",
+ "Download version" : "Скачать версию",
+ "Delete version" : "Удалить версию",
+ "Cancel" : "Отмена",
+ "Remove version name" : "Удалить название версии",
+ "Save version name" : "Сохранить название версии",
+ "Version name" : "Название версии",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именованные версии исключены из автоматического удаления старых версий файлов при исчерпании квоты дискового пространства.",
+ "Initial version restored" : "Восстановлена первоначальная версия",
+ "Version restored" : "Версия восстановлена",
+ "Could not restore version" : "Не удалось восстановить версию",
+ "Could not set version label" : "Не удалось установить метку версии",
+ "Could not delete version" : "Не удалось удалить версию",
+ "File versions" : "Версии файлов"
},
"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");
diff --git a/apps/files_versions/l10n/ru.json b/apps/files_versions/l10n/ru.json
index 3fdd1873c20..96392c99021 100644
--- a/apps/files_versions/l10n/ru.json
+++ b/apps/files_versions/l10n/ru.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Версии",
"This application automatically maintains older versions of files that are changed." : "Приложение служит для обработки старых версий изменённых файлов.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Это приложение предназначено для автоматического управления предыдущими версиями изменённых файлов. При включении этого приложения в каталогах пользователей создаются скрытые папки, предназначенные для хранения предыдущих версий изменённых файлов. Выбор нужной предыдущей версии и возврат к ней выполняется через веб-интерфейс, при этом актуальная версия файла будет заменена выбранной версией. Приложение также автоматически управляет глубиной хранения версий файлов, чтобы не превышать выделенные для пользователя квоты.\n\t\tПомимо управления сроком хранения предыдущих версий, приложение следит за тем, что бы общий размер сохранённых версий файлов не превышал 50% выделенного пользователю дискового пространства. При превышении такого лимита будет запущен механизм удаления самых старых версий файлов. Удаление будет производиться до тех пор, пока общий размер всех сохранённых версий файлов вновь не станет менее 50% от квоты использования дискового пространства. Дополнительная информация приведена в руководстве к приложению «Версии».",
- "Failed to revert {file} to revision {timestamp}." : "Не удалось откатить {file} к ревизии {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n байт","%n байта","%n байт","%n байт"],
- "Restore" : "Откатить",
- "No other versions available" : "Другие версии недоступны"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Это приложение автоматически поддерживает старые версии файлов, которые были изменены. Если оно включено, в каталоге каждого пользователя создаётся папка \"Скрытые версии\", которая используется для хранения старых версий файлов. Пользователь может в любой момент вернуться к более старой версии через веб-интерфейс, при этом заменённый файл станет версией. Приложение автоматически управляет папкой версий, чтобы гарантировать, что квота учётной записи не исчерпается из-за изменений версий.\n\t\tВ дополнение к истечению срока действия версий, приложение \"Версии\" гарантирует, что вы никогда не будете использовать более 50% доступного в данный момент свободного места в учётной записи. Если сохранённые версии превысят это ограничение, приложение сначала удалит самые старые версии, пока не достигнет этого ограничения. Более подробная информация доступна в документации по версиям.",
+ "Current version" : "Текущая версия",
+ "Initial version" : "Первоначальная версия",
+ "You" : "Вы",
+ "Actions for version from {versionHumanExplicitDate}" : "Действия для версии из {versionHumanExplicitDate}",
+ "Name this version" : "Обозначить версию",
+ "Edit version name" : "Изменить название версии",
+ "Compare to current version" : "Сравнить с текущей версией",
+ "Restore version" : "Востановить версию",
+ "Download version" : "Скачать версию",
+ "Delete version" : "Удалить версию",
+ "Cancel" : "Отмена",
+ "Remove version name" : "Удалить название версии",
+ "Save version name" : "Сохранить название версии",
+ "Version name" : "Название версии",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именованные версии исключены из автоматического удаления старых версий файлов при исчерпании квоты дискового пространства.",
+ "Initial version restored" : "Восстановлена первоначальная версия",
+ "Version restored" : "Версия восстановлена",
+ "Could not restore version" : "Не удалось восстановить версию",
+ "Could not set version label" : "Не удалось установить метку версии",
+ "Could not delete version" : "Не удалось удалить версию",
+ "File versions" : "Версии файлов"
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/sc.js b/apps/files_versions/l10n/sc.js
deleted file mode 100644
index 40f0fb0652f..00000000000
--- a/apps/files_versions/l10n/sc.js
+++ /dev/null
@@ -1,12 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versiones",
- "This application automatically maintains older versions of files that are changed." : "Custa aplicatzione allogat de manera automàtica is versiones prus bècias de documentos modificados.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Custa aplicatzione allogat in manera automàtica is versiones prus bècias de documentos modificados. Cando est ativa, frunit una cartella cuada de versiones in cada directory de s'utente e dda impreat pro allogare is versiones bècias de su documentu. S'utente podet semper torrare a una versione prus bècias cun s'interface de internet, e su documentu cambiadu benet a èssere una versione. S'aplicatzione gestit de manera automàtica is cartellas de versiones pro assegurare chi s'utente doesn’t run out of Quota because of versions.\n\t\t In prus de s'iscadèntzia de is versiones, s'aplicatzione assegurat de no impreare mai prus de su 50% de su logu lìberu a disponimentu de s'utente. Chi is versiones allogadas bàrigant custu lìmite, s'aplicatzione at a cantzellare innantis is versione prus bècias finas a lòmpere a su lìmite. Sunt disponìbiles prus informatziones in sa documentatzione de Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Non s'at pòdidu torrare a {documentu} pro sa revisione {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%nbyte","%n bytes"],
- "Restore" : "Recùpera",
- "No other versions available" : "Peruna àtera versione disponìbile"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/sc.json b/apps/files_versions/l10n/sc.json
deleted file mode 100644
index b874e8dfb4a..00000000000
--- a/apps/files_versions/l10n/sc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{ "translations": {
- "Versions" : "Versiones",
- "This application automatically maintains older versions of files that are changed." : "Custa aplicatzione allogat de manera automàtica is versiones prus bècias de documentos modificados.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Custa aplicatzione allogat in manera automàtica is versiones prus bècias de documentos modificados. Cando est ativa, frunit una cartella cuada de versiones in cada directory de s'utente e dda impreat pro allogare is versiones bècias de su documentu. S'utente podet semper torrare a una versione prus bècias cun s'interface de internet, e su documentu cambiadu benet a èssere una versione. S'aplicatzione gestit de manera automàtica is cartellas de versiones pro assegurare chi s'utente doesn’t run out of Quota because of versions.\n\t\t In prus de s'iscadèntzia de is versiones, s'aplicatzione assegurat de no impreare mai prus de su 50% de su logu lìberu a disponimentu de s'utente. Chi is versiones allogadas bàrigant custu lìmite, s'aplicatzione at a cantzellare innantis is versione prus bècias finas a lòmpere a su lìmite. Sunt disponìbiles prus informatziones in sa documentatzione de Versions.",
- "Failed to revert {file} to revision {timestamp}." : "Non s'at pòdidu torrare a {documentu} pro sa revisione {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%nbyte","%n bytes"],
- "Restore" : "Recùpera",
- "No other versions available" : "Peruna àtera versione disponìbile"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/sk.js b/apps/files_versions/l10n/sk.js
index e66e1d156b5..ff9ab4ed723 100644
--- a/apps/files_versions/l10n/sk.js
+++ b/apps/files_versions/l10n/sk.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Verzie",
"This application automatically maintains older versions of files that are changed." : "Táto aplikácia automaticky spravuje staršie verzie súborov, ktoré sú zmenené",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Táto aplikácia automaticky udržuje staršie verzie súborov, ktoré sa zmenili. Keď je zapnutá, je v každom priečinku používateľa vytvorený priečinok pre skryté verzie a sú do neho ukladané staré verzie súborov. Používateľ sa kedykoľvek môže vrátič k starším verziám prostredníctvom webového rozhrania s tým, že sám nahradzovaný súbor sa stane verziou. Aplikácia automaticky spravuje priečinok s verziami, aby bolo zaistené, že používateľ kvôli starým verziám nevyčerpá svoju kvótu.\n\t\tOkrem expirácie verzií, aplikácia Verzie zaistí, že nikdy nepoužije viac než 50% voľného miesta priestoru, ktorý má používateľ k dispozícii. Ak uložené verzie presiahnu tento limit, aplikácia najstaršie verzie vymaže, aby sa do tohto limitu vošla. Viac informácií je k dispozícii v dokumentácii aplikácie Verize.",
- "Failed to revert {file} to revision {timestamp}." : "Zlyhalo obnovenie súboru {file} na verziu {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajtov","%n bajtov","%n bajtov"],
- "Restore" : "Obnoviť",
- "No other versions available" : "Žiadne ďalšie verzie nie sú dostupné"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Táto aplikácia automaticky udržiava staršie verzie súborov, ktoré sú zmenené. Keď je táto možnosť povolená, v adresári každého užívateľa sa vytvorí adresáč skrytých verzií, ktorý sa používa na ukladanie starých verzií súborov. Užívateľ sa môže kedykoľvek vrátiť k staršej verzii prostredníctvom webového rozhrania, pričom nahradený súbor sa stane verziou. Aplikácia automaticky spravuje adresár verzií, aby sa zabezpečilo, že užívateľovi nevyčerpá kvóta kvôli verziám.\nOkrem vypršania platnosti verzií, aplikácia verzie zaisťuje, že nikdy nevyužije viac ako 50 % aktuálne dostupného voľného miesta užívateľa. Ak uložené verzie prekročia tento limit, aplikácia najskôr vymaže najstaršie verzie, kým tento limit nedosiahne. Ďalšie informácie sú k dispozícii v dokumentácii k verziám.",
+ "Current version" : "Aktuálna verzia",
+ "Initial version" : "Úvodná verzia",
+ "You" : "Vy",
+ "Actions for version from {versionHumanExplicitDate}" : "Akcie pre verziu od {versionHumanExplicitDate}",
+ "Name this version" : "Pomenovať túto verziu",
+ "Edit version name" : "Upraviť názov verzie",
+ "Compare to current version" : "Porovnať s aktuálnou verziou",
+ "Restore version" : "Obnoviť verziu",
+ "Download version" : "Stiahnuť verziu",
+ "Delete version" : "Odstrániť verziu",
+ "Cancel" : "Zrušiť",
+ "Remove version name" : "Odstrániť názov verzie",
+ "Save version name" : "Uložiť názov verzie",
+ "Version name" : "Názov verzie",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Pomenované verzie sa zachovajú a po naplnení kvóty úložiska budú vylúčené z automatického čistenia.",
+ "Initial version restored" : "Úvodná verzia bola obnovená",
+ "Version restored" : "Verzia bola obnovená",
+ "Could not restore version" : "Nepodarilo sa obnoviť verziu",
+ "Could not set version label" : "Nepodarilo sa nastaviť označenie verzie",
+ "Could not delete version" : "Nepodarilo sa odstrániť verziu",
+ "File versions" : "Verzie súboru"
},
"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);");
diff --git a/apps/files_versions/l10n/sk.json b/apps/files_versions/l10n/sk.json
index 1fbd03de973..afe241520b7 100644
--- a/apps/files_versions/l10n/sk.json
+++ b/apps/files_versions/l10n/sk.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Verzie",
"This application automatically maintains older versions of files that are changed." : "Táto aplikácia automaticky spravuje staršie verzie súborov, ktoré sú zmenené",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Táto aplikácia automaticky udržuje staršie verzie súborov, ktoré sa zmenili. Keď je zapnutá, je v každom priečinku používateľa vytvorený priečinok pre skryté verzie a sú do neho ukladané staré verzie súborov. Používateľ sa kedykoľvek môže vrátič k starším verziám prostredníctvom webového rozhrania s tým, že sám nahradzovaný súbor sa stane verziou. Aplikácia automaticky spravuje priečinok s verziami, aby bolo zaistené, že používateľ kvôli starým verziám nevyčerpá svoju kvótu.\n\t\tOkrem expirácie verzií, aplikácia Verzie zaistí, že nikdy nepoužije viac než 50% voľného miesta priestoru, ktorý má používateľ k dispozícii. Ak uložené verzie presiahnu tento limit, aplikácia najstaršie verzie vymaže, aby sa do tohto limitu vošla. Viac informácií je k dispozícii v dokumentácii aplikácie Verize.",
- "Failed to revert {file} to revision {timestamp}." : "Zlyhalo obnovenie súboru {file} na verziu {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajtov","%n bajtov","%n bajtov"],
- "Restore" : "Obnoviť",
- "No other versions available" : "Žiadne ďalšie verzie nie sú dostupné"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Táto aplikácia automaticky udržiava staršie verzie súborov, ktoré sú zmenené. Keď je táto možnosť povolená, v adresári každého užívateľa sa vytvorí adresáč skrytých verzií, ktorý sa používa na ukladanie starých verzií súborov. Užívateľ sa môže kedykoľvek vrátiť k staršej verzii prostredníctvom webového rozhrania, pričom nahradený súbor sa stane verziou. Aplikácia automaticky spravuje adresár verzií, aby sa zabezpečilo, že užívateľovi nevyčerpá kvóta kvôli verziám.\nOkrem vypršania platnosti verzií, aplikácia verzie zaisťuje, že nikdy nevyužije viac ako 50 % aktuálne dostupného voľného miesta užívateľa. Ak uložené verzie prekročia tento limit, aplikácia najskôr vymaže najstaršie verzie, kým tento limit nedosiahne. Ďalšie informácie sú k dispozícii v dokumentácii k verziám.",
+ "Current version" : "Aktuálna verzia",
+ "Initial version" : "Úvodná verzia",
+ "You" : "Vy",
+ "Actions for version from {versionHumanExplicitDate}" : "Akcie pre verziu od {versionHumanExplicitDate}",
+ "Name this version" : "Pomenovať túto verziu",
+ "Edit version name" : "Upraviť názov verzie",
+ "Compare to current version" : "Porovnať s aktuálnou verziou",
+ "Restore version" : "Obnoviť verziu",
+ "Download version" : "Stiahnuť verziu",
+ "Delete version" : "Odstrániť verziu",
+ "Cancel" : "Zrušiť",
+ "Remove version name" : "Odstrániť názov verzie",
+ "Save version name" : "Uložiť názov verzie",
+ "Version name" : "Názov verzie",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Pomenované verzie sa zachovajú a po naplnení kvóty úložiska budú vylúčené z automatického čistenia.",
+ "Initial version restored" : "Úvodná verzia bola obnovená",
+ "Version restored" : "Verzia bola obnovená",
+ "Could not restore version" : "Nepodarilo sa obnoviť verziu",
+ "Could not set version label" : "Nepodarilo sa nastaviť označenie verzie",
+ "Could not delete version" : "Nepodarilo sa odstrániť verziu",
+ "File versions" : "Verzie súboru"
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/sl.js b/apps/files_versions/l10n/sl.js
index 0b4d7b29918..0881c039161 100644
--- a/apps/files_versions/l10n/sl.js
+++ b/apps/files_versions/l10n/sl.js
@@ -3,10 +3,21 @@ OC.L10N.register(
{
"Versions" : "Različice",
"This application automatically maintains older versions of files that are changed." : "Program samodejno ustvarja zaporedne različice sprememb datotek.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Program samodejno ustvarja različice spremenjenih datotek v skriti uporabnikovi mapi. Za uporabnika to pomeni, da lahko prek spletnega vmesnika kadarkoli obnovi starejšo različico datoteke, zamenjana datoteka pa postane ena od različic. Upravljanje vključuje tudi nadzor nad omejitvijo prostora, pri čemer se najprej brišejo najstarejše različice.\nNastavitve določajo tudi omejitev, da shranjene različice ne zasedejo več kot 50 % razpoložljivega prostora oziroma količinske omejitve. Več podrobnosti je na voljo v dokumentaciji programa.",
- "Failed to revert {file} to revision {timestamp}." : "Povrnitev datoteke {file} na različico {timestamp} je spodletelo.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajta","%n bajti","%n bajtov"],
- "Restore" : "Obnovi",
- "No other versions available" : "Na voljo ni nobene druge različice datoteke"
+ "Current version" : "Trenutna različica",
+ "You" : "Jaz",
+ "Name this version" : "Poimenovanje razičice",
+ "Edit version name" : "Uredi ime različice",
+ "Restore version" : "Obnovi različico",
+ "Download version" : "Prejmi različico",
+ "Delete version" : "Izbriši različico",
+ "Cancel" : "Prekliči",
+ "Remove version name" : "Odstrani ime različice",
+ "Save version name" : "Shrani ime različice",
+ "Version name" : "Ime različice",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Poimenovane različice so trajne in niso vključene v samodejno čiščenje, če je prostora v oblaku malo.",
+ "Initial version restored" : "Začetna različica je obnovljena",
+ "Version restored" : "Različica je obnovljena",
+ "Could not restore version" : "Različice ni mogoče obnoviti",
+ "Could not delete version" : "Različice ji mogoče izbrisati"
},
"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);");
diff --git a/apps/files_versions/l10n/sl.json b/apps/files_versions/l10n/sl.json
index 6c824649ba6..21c2a0b2089 100644
--- a/apps/files_versions/l10n/sl.json
+++ b/apps/files_versions/l10n/sl.json
@@ -1,10 +1,21 @@
{ "translations": {
"Versions" : "Različice",
"This application automatically maintains older versions of files that are changed." : "Program samodejno ustvarja zaporedne različice sprememb datotek.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Program samodejno ustvarja različice spremenjenih datotek v skriti uporabnikovi mapi. Za uporabnika to pomeni, da lahko prek spletnega vmesnika kadarkoli obnovi starejšo različico datoteke, zamenjana datoteka pa postane ena od različic. Upravljanje vključuje tudi nadzor nad omejitvijo prostora, pri čemer se najprej brišejo najstarejše različice.\nNastavitve določajo tudi omejitev, da shranjene različice ne zasedejo več kot 50 % razpoložljivega prostora oziroma količinske omejitve. Več podrobnosti je na voljo v dokumentaciji programa.",
- "Failed to revert {file} to revision {timestamp}." : "Povrnitev datoteke {file} na različico {timestamp} je spodletelo.",
- "_%n byte_::_%n bytes_" : ["%n bajt","%n bajta","%n bajti","%n bajtov"],
- "Restore" : "Obnovi",
- "No other versions available" : "Na voljo ni nobene druge različice datoteke"
+ "Current version" : "Trenutna različica",
+ "You" : "Jaz",
+ "Name this version" : "Poimenovanje razičice",
+ "Edit version name" : "Uredi ime različice",
+ "Restore version" : "Obnovi različico",
+ "Download version" : "Prejmi različico",
+ "Delete version" : "Izbriši različico",
+ "Cancel" : "Prekliči",
+ "Remove version name" : "Odstrani ime različice",
+ "Save version name" : "Shrani ime različice",
+ "Version name" : "Ime različice",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Poimenovane različice so trajne in niso vključene v samodejno čiščenje, če je prostora v oblaku malo.",
+ "Initial version restored" : "Začetna različica je obnovljena",
+ "Version restored" : "Različica je obnovljena",
+ "Could not restore version" : "Različice ni mogoče obnoviti",
+ "Could not delete version" : "Različice ji mogoče izbrisati"
},"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/apps/files_versions/l10n/sq.js b/apps/files_versions/l10n/sq.js
deleted file mode 100644
index 59d42371c2f..00000000000
--- a/apps/files_versions/l10n/sq.js
+++ /dev/null
@@ -1,10 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "Versione",
- "Failed to revert {file} to revision {timestamp}." : "Dështoi në rikthimin e {file} te rishikimi {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajte","%n bajte"],
- "Restore" : "Riktheje",
- "No other versions available" : "Nuk ka versione të tjera të gatshme"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/sq.json b/apps/files_versions/l10n/sq.json
deleted file mode 100644
index 73fe6d0ab58..00000000000
--- a/apps/files_versions/l10n/sq.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "translations": {
- "Versions" : "Versione",
- "Failed to revert {file} to revision {timestamp}." : "Dështoi në rikthimin e {file} te rishikimi {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n bajte","%n bajte"],
- "Restore" : "Riktheje",
- "No other versions available" : "Nuk ka versione të tjera të gatshme"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/sr.js b/apps/files_versions/l10n/sr.js
index adf4a706245..9fae518228f 100644
--- a/apps/files_versions/l10n/sr.js
+++ b/apps/files_versions/l10n/sr.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Верзије",
"This application automatically maintains older versions of files that are changed." : "Ова апликација аутоматски одржава старије верзије измењених фајлова.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ова апликација аутоматски чува старије верзије фајлова који су се изменили. Када се укључи, у свакој корисничкој фасцикли се додаје још једна скривена фасцикла у коју се смештају старије верзије фајлова. Корисник се у сваком тренутку може вратити на старију верзију фајлова кроз веб интерфејс, с тим да замењени фајл постаје исто једна верзија. Апликација аутоматски управља фасциклама са верзијама да би се осигурала да корисник не дође до квоте због чувања верзија.\n\t\tУз истицање верзија, апликација верзионисања се стара да се никад не користи више од 50% корисничког слободног простора. Уколико ускладиштена верзија прелази ову вредност, апликација ће кренути да брише верзије почевши од најстарије све док се не падне испод границе од 50%. Још информација је доступно у документацији апликације за Верзионисање.",
- "Failed to revert {file} to revision {timestamp}." : "Не могу да вратим {file} на ревизију {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n бајт","%n бајта","%n бајтова"],
- "Restore" : "Врати",
- "No other versions available" : "Нема доступних других верзија"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ова апликација аутоматски одржава старије верзије фајлова који су измењени. Када се укључи, у сваком корисниковом директоријуму се креира скривени фолдер са верзијама. Он се користи за чување старијих верзија фајла. У било које време корисник може да се врати на старију верзију користећи веб интерфејс, тако што замењени фајл постаје нова верзија. Апликација аутоматски управља фолдером са верзијама тако да налог не потроши своју Квоту због верзија.\n\t\tУз време истека верзија, апликација обезбеђује да се никада не заузме више од 50% текућег слободног простора налога. Ако сачуване верзије прекораче ово ограничење, апликација ће најпре обриати најстарије верзије све док се не задовољи ограничење. Више информација се налази у документацији апликације Верзије.",
+ "Current version" : "Тренутна верзија",
+ "Initial version" : "Почетна верзија",
+ "You" : "Ви",
+ "Actions for version from {versionHumanExplicitDate}" : "Акције за верзију од {versionHumanExplicitDate}",
+ "Name this version" : "Назив ове верзије",
+ "Edit version name" : "Уреди назив верзије",
+ "Compare to current version" : "Упореди са текућом верзијом",
+ "Restore version" : "Рестаурирај верзију",
+ "Download version" : "Преузми верзију",
+ "Delete version" : "Обриши верзију",
+ "Cancel" : "Откажи",
+ "Remove version name" : "Уклони назив верзије",
+ "Save version name" : "Сачувај назив верзије",
+ "Version name" : "Назив верзије",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именоване верзије су постојане и изузете су из аутоматског чишћења када се испуни ваша диск квота.",
+ "Initial version restored" : "Рестаурирана је почетна верзија",
+ "Version restored" : "Верзија је рестаурирана",
+ "Could not restore version" : "Верзија није могла да се рестаурира",
+ "Could not set version label" : "Није могла да се постави ознака назива верзије",
+ "Could not delete version" : "Верзија није могла да се обрише",
+ "File versions" : "Верзије фајла"
},
"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/apps/files_versions/l10n/sr.json b/apps/files_versions/l10n/sr.json
index ae7bb07b404..c4d24c85abf 100644
--- a/apps/files_versions/l10n/sr.json
+++ b/apps/files_versions/l10n/sr.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Верзије",
"This application automatically maintains older versions of files that are changed." : "Ова апликација аутоматски одржава старије верзије измењених фајлова.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ова апликација аутоматски чува старије верзије фајлова који су се изменили. Када се укључи, у свакој корисничкој фасцикли се додаје још једна скривена фасцикла у коју се смештају старије верзије фајлова. Корисник се у сваком тренутку може вратити на старију верзију фајлова кроз веб интерфејс, с тим да замењени фајл постаје исто једна верзија. Апликација аутоматски управља фасциклама са верзијама да би се осигурала да корисник не дође до квоте због чувања верзија.\n\t\tУз истицање верзија, апликација верзионисања се стара да се никад не користи више од 50% корисничког слободног простора. Уколико ускладиштена верзија прелази ову вредност, апликација ће кренути да брише верзије почевши од најстарије све док се не падне испод границе од 50%. Још информација је доступно у документацији апликације за Верзионисање.",
- "Failed to revert {file} to revision {timestamp}." : "Не могу да вратим {file} на ревизију {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n бајт","%n бајта","%n бајтова"],
- "Restore" : "Врати",
- "No other versions available" : "Нема доступних других верзија"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ова апликација аутоматски одржава старије верзије фајлова који су измењени. Када се укључи, у сваком корисниковом директоријуму се креира скривени фолдер са верзијама. Он се користи за чување старијих верзија фајла. У било које време корисник може да се врати на старију верзију користећи веб интерфејс, тако што замењени фајл постаје нова верзија. Апликација аутоматски управља фолдером са верзијама тако да налог не потроши своју Квоту због верзија.\n\t\tУз време истека верзија, апликација обезбеђује да се никада не заузме више од 50% текућег слободног простора налога. Ако сачуване верзије прекораче ово ограничење, апликација ће најпре обриати најстарије верзије све док се не задовољи ограничење. Више информација се налази у документацији апликације Верзије.",
+ "Current version" : "Тренутна верзија",
+ "Initial version" : "Почетна верзија",
+ "You" : "Ви",
+ "Actions for version from {versionHumanExplicitDate}" : "Акције за верзију од {versionHumanExplicitDate}",
+ "Name this version" : "Назив ове верзије",
+ "Edit version name" : "Уреди назив верзије",
+ "Compare to current version" : "Упореди са текућом верзијом",
+ "Restore version" : "Рестаурирај верзију",
+ "Download version" : "Преузми верзију",
+ "Delete version" : "Обриши верзију",
+ "Cancel" : "Откажи",
+ "Remove version name" : "Уклони назив верзије",
+ "Save version name" : "Сачувај назив верзије",
+ "Version name" : "Назив верзије",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Именоване верзије су постојане и изузете су из аутоматског чишћења када се испуни ваша диск квота.",
+ "Initial version restored" : "Рестаурирана је почетна верзија",
+ "Version restored" : "Верзија је рестаурирана",
+ "Could not restore version" : "Верзија није могла да се рестаурира",
+ "Could not set version label" : "Није могла да се постави ознака назива верзије",
+ "Could not delete version" : "Верзија није могла да се обрише",
+ "File versions" : "Верзије фајла"
},"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/apps/files_versions/l10n/sr@latin.js b/apps/files_versions/l10n/sr@latin.js
deleted file mode 100644
index 627d70eb51b..00000000000
--- a/apps/files_versions/l10n/sr@latin.js
+++ /dev/null
@@ -1,11 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Could not revert: %s" : "Ne mogu da vratim: %s",
- "Versions" : "Verzije",
- "Failed to revert {file} to revision {timestamp}." : "Ne mogu da vratim {file} na reviziju {timestamp}.",
- "Restore" : "Vrati",
- "No other versions available" : "Nema drugih verzija",
- "More versions..." : "Još verzija..."
-},
-"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/apps/files_versions/l10n/sr@latin.json b/apps/files_versions/l10n/sr@latin.json
deleted file mode 100644
index 63fe55cf50e..00000000000
--- a/apps/files_versions/l10n/sr@latin.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{ "translations": {
- "Could not revert: %s" : "Ne mogu da vratim: %s",
- "Versions" : "Verzije",
- "Failed to revert {file} to revision {timestamp}." : "Ne mogu da vratim {file} na reviziju {timestamp}.",
- "Restore" : "Vrati",
- "No other versions available" : "Nema drugih verzija",
- "More versions..." : "Još verzija..."
-},"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/apps/files_versions/l10n/sv.js b/apps/files_versions/l10n/sv.js
index 569c51a6779..31711f5efef 100644
--- a/apps/files_versions/l10n/sv.js
+++ b/apps/files_versions/l10n/sv.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Versioner",
"This application automatically maintains older versions of files that are changed." : "Den här applikationen behåller automatiskt äldre versioner av filer som ändras.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denna applikation upprätthåller automatiskt äldre versioner av filer som ändras. När aktiverad, en dold versionsmapp tillhandahålls i varje användares katalog och används för att lagra gamla filversioner. En användare kan återgå till en äldre version via webbgränssnittet när som helst, med den ersatta filen blir en version. Appen hanterar automatiskt versionsmappen för att säkerställa att användaren inte får slut på kvot på grund av versioner.\nFörutom utgången av versioner, versions appen gör vissa aldrig att använda mer än 50% av användarens tillgängliga ledigt utrymme. Om lagrade versioner överskrider denna gräns, kommer appen att ta bort de äldsta versionerna först tills den uppfyller denna gräns. Mer information finns i Versionsdokumentationen.",
- "Failed to revert {file} to revision {timestamp}." : "Kunde inte återställa {file} till {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Återskapa",
- "No other versions available" : "Inga andra versioner tillgängliga"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denna applikation hanterar automatiskt äldre versioner av filer när de ändras. När funktionen är aktiverad tillhandahålls en dold versionsmapp i varje användares katalog som används för att lagra gamla filversioner. En användare kan när som helst återgå till en äldre version via webbgränssnittet, när detta görs blir den ersatta filen en version. Appen hanterar automatiskt versionsmappen för att säkerställa att användaren inte får slut på sin kvot på grund av sparade versioner.\nUtöver hantering av utgångna versioner så förvissar sig appen för versionshantering att den inte använder sig av mer än 50% av användarens tillgängliga ledigt utrymme. Om lagrade versioner överskrider denna gräns, kommer appen att ta bort de äldsta versionerna först tills den inte längre överskrider gränsen. Mer information finns i Versionsdokumentationen.",
+ "Current version" : "Aktuell version",
+ "Initial version" : "Första versionen",
+ "You" : "Du",
+ "Actions for version from {versionHumanExplicitDate}" : "Åtgärder för version från {versionHumanExplicitDate}",
+ "Name this version" : "Namnge denna version",
+ "Edit version name" : "Ändra versionsnamn",
+ "Compare to current version" : "Jämför med nuvarande version",
+ "Restore version" : "Återställ version",
+ "Download version" : "Ladda ner version",
+ "Delete version" : "Ta bort version",
+ "Cancel" : "Avbryt",
+ "Remove version name" : "Ta bort versionsnamn",
+ "Save version name" : "Spara versionsnamn",
+ "Version name" : "Namn på version",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Namngivna versioner finns kvar och utesluts från automatiska rensningar när din lagringskvot är full.",
+ "Initial version restored" : "Ursprunglig version återställd",
+ "Version restored" : "Version återställd",
+ "Could not restore version" : "Kunde inte återställa versionen",
+ "Could not set version label" : "Det gick inte att ange versionsetikett",
+ "Could not delete version" : "Det gick inte att ta bort versionen",
+ "File versions" : "Filversioner"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/sv.json b/apps/files_versions/l10n/sv.json
index f2fbf4f9524..98a4af8c801 100644
--- a/apps/files_versions/l10n/sv.json
+++ b/apps/files_versions/l10n/sv.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Versioner",
"This application automatically maintains older versions of files that are changed." : "Den här applikationen behåller automatiskt äldre versioner av filer som ändras.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denna applikation upprätthåller automatiskt äldre versioner av filer som ändras. När aktiverad, en dold versionsmapp tillhandahålls i varje användares katalog och används för att lagra gamla filversioner. En användare kan återgå till en äldre version via webbgränssnittet när som helst, med den ersatta filen blir en version. Appen hanterar automatiskt versionsmappen för att säkerställa att användaren inte får slut på kvot på grund av versioner.\nFörutom utgången av versioner, versions appen gör vissa aldrig att använda mer än 50% av användarens tillgängliga ledigt utrymme. Om lagrade versioner överskrider denna gräns, kommer appen att ta bort de äldsta versionerna först tills den uppfyller denna gräns. Mer information finns i Versionsdokumentationen.",
- "Failed to revert {file} to revision {timestamp}." : "Kunde inte återställa {file} till {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Restore" : "Återskapa",
- "No other versions available" : "Inga andra versioner tillgängliga"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Denna applikation hanterar automatiskt äldre versioner av filer när de ändras. När funktionen är aktiverad tillhandahålls en dold versionsmapp i varje användares katalog som används för att lagra gamla filversioner. En användare kan när som helst återgå till en äldre version via webbgränssnittet, när detta görs blir den ersatta filen en version. Appen hanterar automatiskt versionsmappen för att säkerställa att användaren inte får slut på sin kvot på grund av sparade versioner.\nUtöver hantering av utgångna versioner så förvissar sig appen för versionshantering att den inte använder sig av mer än 50% av användarens tillgängliga ledigt utrymme. Om lagrade versioner överskrider denna gräns, kommer appen att ta bort de äldsta versionerna först tills den inte längre överskrider gränsen. Mer information finns i Versionsdokumentationen.",
+ "Current version" : "Aktuell version",
+ "Initial version" : "Första versionen",
+ "You" : "Du",
+ "Actions for version from {versionHumanExplicitDate}" : "Åtgärder för version från {versionHumanExplicitDate}",
+ "Name this version" : "Namnge denna version",
+ "Edit version name" : "Ändra versionsnamn",
+ "Compare to current version" : "Jämför med nuvarande version",
+ "Restore version" : "Återställ version",
+ "Download version" : "Ladda ner version",
+ "Delete version" : "Ta bort version",
+ "Cancel" : "Avbryt",
+ "Remove version name" : "Ta bort versionsnamn",
+ "Save version name" : "Spara versionsnamn",
+ "Version name" : "Namn på version",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Namngivna versioner finns kvar och utesluts från automatiska rensningar när din lagringskvot är full.",
+ "Initial version restored" : "Ursprunglig version återställd",
+ "Version restored" : "Version återställd",
+ "Could not restore version" : "Kunde inte återställa versionen",
+ "Could not set version label" : "Det gick inte att ange versionsetikett",
+ "Could not delete version" : "Det gick inte att ta bort versionen",
+ "File versions" : "Filversioner"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/sw.js b/apps/files_versions/l10n/sw.js
new file mode 100644
index 00000000000..193be71930c
--- /dev/null
+++ b/apps/files_versions/l10n/sw.js
@@ -0,0 +1,29 @@
+OC.L10N.register(
+ "files_versions",
+ {
+ "Versions" : "Matoleo",
+ "This application automatically maintains older versions of files that are changed." : "Programu hii hudumisha kiotomati matoleo ya zamani ya faili ambazo hubadilishwa.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Programu hii hudumisha kiotomati matoleo ya zamani ya faili ambazo hubadilishwa. Inapowashwa, folda ya matoleo yaliyofichwa hutolewa katika saraka ya kila mtumiaji na hutumiwa kuhifadhi matoleo ya zamani ya faili. Mtumiaji anaweza kurejesha toleo la zamani kupitia kiolesura cha wavuti wakati wowote, na faili iliyobadilishwa kuwa toleo. Programu hudhibiti folda ya matoleo kiotomatiki ili kuhakikisha kuwa akaunti haiishiwi na Kiasi kwa sababu ya matoleo.\n\t\tPamoja na kuisha kwa muda wa matoleo, programu ya matoleo huhakikisha kuwa haitawahi kutumia zaidi ya 50% ya nafasi ya bure inayopatikana kwa sasa ya akaunti. Ikiwa matoleo yaliyohifadhiwa yatazidi kikomo hiki, programu itafuta matoleo ya zamani kwanza hadi ifikie kikomo hiki. Maelezo zaidi yanapatikana katika hati za Matoleo.",
+ "Current version" : " Toleo la sasa",
+ "Initial version" : "Toleo la awali",
+ "You" : "Wewe",
+ "Actions for version from {versionHumanExplicitDate}" : "Vitendo vya toleo kutoka {versionHumanExplicitDate}",
+ "Name this version" : "Lipe jina toleo hili",
+ "Edit version name" : "Hariri jina la toleo",
+ "Compare to current version" : "Linganisha kwa toleo la sasa",
+ "Restore version" : "Hifadhi upya toleo",
+ "Download version" : "Pakua toleo",
+ "Delete version" : "Futa toleo",
+ "Cancel" : "Ghairi",
+ "Remove version name" : "Ondoa jina la toleo",
+ "Save version name" : "Hifadhi jina la toleo",
+ "Version name" : "Jina la toleo",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : " Matoleo yaliyotajwa yanaendelea, na hayajumuishwi katika usafishaji kiotomatiki wakati kiasi chako cha hifadhi kimejaa.",
+ "Initial version restored" : "Toleo la awali limerejeshwa",
+ "Version restored" : "Toleo limerejeshwa",
+ "Could not restore version" : "Haikuweza kurejesha toleo",
+ "Could not set version label" : "Haikuweza kuweka lebo ya toleo",
+ "Could not delete version" : "Haikuweza kufuta toleo",
+ "File versions" : "Matoleo ya faili"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/sw.json b/apps/files_versions/l10n/sw.json
new file mode 100644
index 00000000000..7a617882365
--- /dev/null
+++ b/apps/files_versions/l10n/sw.json
@@ -0,0 +1,27 @@
+{ "translations": {
+ "Versions" : "Matoleo",
+ "This application automatically maintains older versions of files that are changed." : "Programu hii hudumisha kiotomati matoleo ya zamani ya faili ambazo hubadilishwa.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Programu hii hudumisha kiotomati matoleo ya zamani ya faili ambazo hubadilishwa. Inapowashwa, folda ya matoleo yaliyofichwa hutolewa katika saraka ya kila mtumiaji na hutumiwa kuhifadhi matoleo ya zamani ya faili. Mtumiaji anaweza kurejesha toleo la zamani kupitia kiolesura cha wavuti wakati wowote, na faili iliyobadilishwa kuwa toleo. Programu hudhibiti folda ya matoleo kiotomatiki ili kuhakikisha kuwa akaunti haiishiwi na Kiasi kwa sababu ya matoleo.\n\t\tPamoja na kuisha kwa muda wa matoleo, programu ya matoleo huhakikisha kuwa haitawahi kutumia zaidi ya 50% ya nafasi ya bure inayopatikana kwa sasa ya akaunti. Ikiwa matoleo yaliyohifadhiwa yatazidi kikomo hiki, programu itafuta matoleo ya zamani kwanza hadi ifikie kikomo hiki. Maelezo zaidi yanapatikana katika hati za Matoleo.",
+ "Current version" : " Toleo la sasa",
+ "Initial version" : "Toleo la awali",
+ "You" : "Wewe",
+ "Actions for version from {versionHumanExplicitDate}" : "Vitendo vya toleo kutoka {versionHumanExplicitDate}",
+ "Name this version" : "Lipe jina toleo hili",
+ "Edit version name" : "Hariri jina la toleo",
+ "Compare to current version" : "Linganisha kwa toleo la sasa",
+ "Restore version" : "Hifadhi upya toleo",
+ "Download version" : "Pakua toleo",
+ "Delete version" : "Futa toleo",
+ "Cancel" : "Ghairi",
+ "Remove version name" : "Ondoa jina la toleo",
+ "Save version name" : "Hifadhi jina la toleo",
+ "Version name" : "Jina la toleo",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : " Matoleo yaliyotajwa yanaendelea, na hayajumuishwi katika usafishaji kiotomatiki wakati kiasi chako cha hifadhi kimejaa.",
+ "Initial version restored" : "Toleo la awali limerejeshwa",
+ "Version restored" : "Toleo limerejeshwa",
+ "Could not restore version" : "Haikuweza kurejesha toleo",
+ "Could not set version label" : "Haikuweza kuweka lebo ya toleo",
+ "Could not delete version" : "Haikuweza kufuta toleo",
+ "File versions" : "Matoleo ya faili"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/files_versions/l10n/th.js b/apps/files_versions/l10n/th.js
deleted file mode 100644
index e86c92c3e8b..00000000000
--- a/apps/files_versions/l10n/th.js
+++ /dev/null
@@ -1,10 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Versions" : "รุ่น",
- "Failed to revert {file} to revision {timestamp}." : "{file} ล้มเหลวที่จะย้อนกลับไปยังการแก้ไขเมื่อ {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n ไบต์"],
- "Restore" : "คืนค่า",
- "No other versions available" : "ไม่มีรุ่นอื่น ๆ"
-},
-"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/th.json b/apps/files_versions/l10n/th.json
deleted file mode 100644
index c46285ab31f..00000000000
--- a/apps/files_versions/l10n/th.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "translations": {
- "Versions" : "รุ่น",
- "Failed to revert {file} to revision {timestamp}." : "{file} ล้มเหลวที่จะย้อนกลับไปยังการแก้ไขเมื่อ {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n ไบต์"],
- "Restore" : "คืนค่า",
- "No other versions available" : "ไม่มีรุ่นอื่น ๆ"
-},"pluralForm" :"nplurals=1; plural=0;"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/tr.js b/apps/files_versions/l10n/tr.js
index f9af9fedb16..dc216107c52 100644
--- a/apps/files_versions/l10n/tr.js
+++ b/apps/files_versions/l10n/tr.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Sürümler",
"This application automatically maintains older versions of files that are changed." : "Bu uygulama değiştirilen dosyaların önceki sürümlerini otomatik olarak izler ve saklar.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Bu uygulama değiştirilen dosyaların önceki sürümlerini otomatik olarak izler ve saklar. etkinleştirildiğinde, dosya sürümlerini saklamak için her kullanıcının klasörlerinde gizli bir versions klasörü oluşturulur. Kullanıcılar web arayüzünü kullanarak istedikleri zaman dosyalarının daha önceki sürümlerine geri dönebilirler. Uygulama versions klasörünü otomatik olarak düzenler ve önceki dosya sürümleri nedeniyle kullanıcının kotasının dolmasını engeller.\n\t\tSürümler uygulaması dosya sürümlerini belirli bir süreyle saklarken, kullanıcı depolama alanının en çok %50 oranındaki bölümünü kullanır. Depolanan sürüm dosyalarının boyutu bu sınırın üzerine çıkarsa, sınır değerine geri dönülene kadar en eski sürüm dosyaları silinir. Ayrıntılı bilgi almak için Sürümler uygulamasının belgelerine bakabilirsiniz.",
- "Failed to revert {file} to revision {timestamp}." : "{file} dosyası {timestamp} sürümüne geri alınamadı.",
- "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"],
- "Restore" : "Geri yükle",
- "No other versions available" : "Başka bir sürüm yok"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Bu uygulama değiştirilen dosyaların önceki sürümlerini otomatik olarak izler ve saklar. Kullanıma alındığında, dosya sürümlerini saklamak için her kullanıcının klasörlerinde gizli bir versions klasörü oluşturulur. Kullanıcılar site arayüzünü kullanarak istedikleri zaman dosyalarının önceki sürümlerine geri dönebilirler. Uygulama versions klasörünü otomatik olarak düzenler ve önceki dosya sürümleri nedeniyle hesabın kotasının dolmasını engeller.\n\t\tSürümler uygulaması dosya sürümlerini belirli bir süreyle saklarken, hesabın depolama alanının en çok %50 oranındaki bölümünü kullanır. Depolanan sürüm dosyalarının boyutu bu sınırın üzerine çıkarsa, sınır değerine geri dönülene kadar en eski sürüm dosyaları silinir. Ayrıntılı bilgi almak için Sürümler uygulamasının belgelerine bakabilirsiniz.",
+ "Current version" : "Geçerli sürüm",
+ "Initial version" : "İlk sürüm",
+ "You" : "Siz",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} tarihindeki sürüm için işlemler",
+ "Name this version" : "Bu sürümü adlandırın",
+ "Edit version name" : "Sürüm adını düzenle",
+ "Compare to current version" : "Geçerli sürüm ile karşılaştır",
+ "Restore version" : "Sürümü geri yükle",
+ "Download version" : "Sürümü indir",
+ "Delete version" : "Sürümü sil",
+ "Cancel" : "İptal",
+ "Remove version name" : "Sürüm adını kaldır",
+ "Save version name" : "Sürüm adını kaydet",
+ "Version name" : "Sürüm adı",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Adlandırılmış sürümler kalıcı olur ve depolama alanı kotanız dolduğunda otomatik temizleme işlemine katılmaz.",
+ "Initial version restored" : "İlk sürüm geri yüklendi",
+ "Version restored" : "Sürüm geri yüklendi",
+ "Could not restore version" : "Sürüm geri yüklenemedi",
+ "Could not set version label" : "Sürüm etiketi ayarlanamadı",
+ "Could not delete version" : "Sürüm silinemedi",
+ "File versions" : "Dosya sürümleri"
},
"nplurals=2; plural=(n > 1);");
diff --git a/apps/files_versions/l10n/tr.json b/apps/files_versions/l10n/tr.json
index f0b4769ad1f..e914457e8bd 100644
--- a/apps/files_versions/l10n/tr.json
+++ b/apps/files_versions/l10n/tr.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Sürümler",
"This application automatically maintains older versions of files that are changed." : "Bu uygulama değiştirilen dosyaların önceki sürümlerini otomatik olarak izler ve saklar.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Bu uygulama değiştirilen dosyaların önceki sürümlerini otomatik olarak izler ve saklar. etkinleştirildiğinde, dosya sürümlerini saklamak için her kullanıcının klasörlerinde gizli bir versions klasörü oluşturulur. Kullanıcılar web arayüzünü kullanarak istedikleri zaman dosyalarının daha önceki sürümlerine geri dönebilirler. Uygulama versions klasörünü otomatik olarak düzenler ve önceki dosya sürümleri nedeniyle kullanıcının kotasının dolmasını engeller.\n\t\tSürümler uygulaması dosya sürümlerini belirli bir süreyle saklarken, kullanıcı depolama alanının en çok %50 oranındaki bölümünü kullanır. Depolanan sürüm dosyalarının boyutu bu sınırın üzerine çıkarsa, sınır değerine geri dönülene kadar en eski sürüm dosyaları silinir. Ayrıntılı bilgi almak için Sürümler uygulamasının belgelerine bakabilirsiniz.",
- "Failed to revert {file} to revision {timestamp}." : "{file} dosyası {timestamp} sürümüne geri alınamadı.",
- "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"],
- "Restore" : "Geri yükle",
- "No other versions available" : "Başka bir sürüm yok"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Bu uygulama değiştirilen dosyaların önceki sürümlerini otomatik olarak izler ve saklar. Kullanıma alındığında, dosya sürümlerini saklamak için her kullanıcının klasörlerinde gizli bir versions klasörü oluşturulur. Kullanıcılar site arayüzünü kullanarak istedikleri zaman dosyalarının önceki sürümlerine geri dönebilirler. Uygulama versions klasörünü otomatik olarak düzenler ve önceki dosya sürümleri nedeniyle hesabın kotasının dolmasını engeller.\n\t\tSürümler uygulaması dosya sürümlerini belirli bir süreyle saklarken, hesabın depolama alanının en çok %50 oranındaki bölümünü kullanır. Depolanan sürüm dosyalarının boyutu bu sınırın üzerine çıkarsa, sınır değerine geri dönülene kadar en eski sürüm dosyaları silinir. Ayrıntılı bilgi almak için Sürümler uygulamasının belgelerine bakabilirsiniz.",
+ "Current version" : "Geçerli sürüm",
+ "Initial version" : "İlk sürüm",
+ "You" : "Siz",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} tarihindeki sürüm için işlemler",
+ "Name this version" : "Bu sürümü adlandırın",
+ "Edit version name" : "Sürüm adını düzenle",
+ "Compare to current version" : "Geçerli sürüm ile karşılaştır",
+ "Restore version" : "Sürümü geri yükle",
+ "Download version" : "Sürümü indir",
+ "Delete version" : "Sürümü sil",
+ "Cancel" : "İptal",
+ "Remove version name" : "Sürüm adını kaldır",
+ "Save version name" : "Sürüm adını kaydet",
+ "Version name" : "Sürüm adı",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Adlandırılmış sürümler kalıcı olur ve depolama alanı kotanız dolduğunda otomatik temizleme işlemine katılmaz.",
+ "Initial version restored" : "İlk sürüm geri yüklendi",
+ "Version restored" : "Sürüm geri yüklendi",
+ "Could not restore version" : "Sürüm geri yüklenemedi",
+ "Could not set version label" : "Sürüm etiketi ayarlanamadı",
+ "Could not delete version" : "Sürüm silinemedi",
+ "File versions" : "Dosya sürümleri"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ug.js b/apps/files_versions/l10n/ug.js
index d0fc24b831f..5fb5ab3d7e3 100644
--- a/apps/files_versions/l10n/ug.js
+++ b/apps/files_versions/l10n/ug.js
@@ -1,7 +1,28 @@
OC.L10N.register(
"files_versions",
{
- "Could not revert: %s" : "ئەسلىگە قايتۇرالمايدۇ: %s",
- "Versions" : "نەشرى"
+ "Versions" : "نەشرى",
+ "This application automatically maintains older versions of files that are changed." : "بۇ پروگرامما ئۆزگەرتىلگەن ھۆججەتلەرنىڭ كونا نەشرىنى ئاپتوماتىك ساقلايدۇ.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "بۇ پروگرامما ئۆزگەرتىلگەن ھۆججەتلەرنىڭ كونا نەشرىنى ئاپتوماتىك ساقلايدۇ. قوزغىتىلغاندا ، ھەر بىر ئىشلەتكۈچىنىڭ مۇندەرىجىسىدە يوشۇرۇن نەشرى قىسقۇچ تەمىنلەنگەن بولۇپ ، كونا ھۆججەت نەشرىنى ساقلاشقا ئىشلىتىلىدۇ. ئىشلەتكۈچى خالىغان ۋاقىتتا تور كۆرۈنمە يۈزى ئارقىلىق كونا نەشرىگە قايتالايدۇ ، ئالماشتۇرۇلغان ھۆججەت نەشرىگە ئايلىنىدۇ. بۇ دېتال نەشرى قىسقۇچنى ئاپتوماتىك باشقۇرۇپ ، نەشرى سەۋەبىدىن ھېساباتنىڭ نورمىدىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىدۇ.\n\t\tنەشرىنىڭ ۋاقتى توشقاندىن باشقا ، نەشىر دېتالى ھېساباتنىڭ ھازىر بار بولغان بوشلۇقنىڭ%50 تىن كۆپرەكىنى ھەرگىز ئىشلەتمەسلىككە كاپالەتلىك قىلىدۇ. ئەگەر ساقلانغان نەشرى بۇ چەكتىن ئېشىپ كەتسە ، ئەپ بۇ چەككە توشقۇچە ئەڭ كونا نەشرىنى ئۆچۈرۈۋېتىدۇ. تېخىمۇ كۆپ ئۇچۇرلار نەشىر ھۆججىتىدە بار.",
+ "Current version" : "نۆۋەتتىكى نەشرى",
+ "Initial version" : "دەسلەپكى نەشرى",
+ "You" : "سەن",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} HumanExplicitDate from نەشرىدىكى مەشغۇلاتلار",
+ "Name this version" : "بۇ نەشرىگە ئىسىم قويۇڭ",
+ "Edit version name" : "نەشرىنىڭ نامىنى تەھرىرلەش",
+ "Compare to current version" : "ھازىرقى نەشرىگە سېلىشتۇرۇڭ",
+ "Restore version" : "نەشرىنى ئەسلىگە كەلتۈرۈش",
+ "Download version" : "نەشرىنى چۈشۈرۈش",
+ "Delete version" : "نەشرىنى ئۆچۈرۈڭ",
+ "Cancel" : "بىكار قىلىش",
+ "Remove version name" : "نەشرىنىڭ نامىنى ئۆچۈرۈڭ",
+ "Save version name" : "نەشرىنىڭ نامىنى ساقلاڭ",
+ "Version name" : "نەشرىنىڭ ئىسمى",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "ئىسمى بار نەشرى ساقلاپ قېلىنىدۇ ، ساقلاش نورمىسى توشقاندا ئاپتوماتىك تازىلاشتىن چىقىرىۋېتىلىدۇ.",
+ "Initial version restored" : "دەسلەپكى نەشرى ئەسلىگە كەلدى",
+ "Version restored" : "نەشرى ئەسلىگە كەلتۈرۈلدى",
+ "Could not restore version" : "نەشرىنى ئەسلىگە كەلتۈرەلمىدى",
+ "Could not set version label" : "نەشىر بەلگىسىنى تەڭشىيەلمىدى",
+ "Could not delete version" : "نەشرىنى ئۆچۈرەلمىدى"
},
-"nplurals=1; plural=0;");
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/ug.json b/apps/files_versions/l10n/ug.json
index 84f12cdc23a..29d3a9be9b6 100644
--- a/apps/files_versions/l10n/ug.json
+++ b/apps/files_versions/l10n/ug.json
@@ -1,5 +1,26 @@
{ "translations": {
- "Could not revert: %s" : "ئەسلىگە قايتۇرالمايدۇ: %s",
- "Versions" : "نەشرى"
-},"pluralForm" :"nplurals=1; plural=0;"
+ "Versions" : "نەشرى",
+ "This application automatically maintains older versions of files that are changed." : "بۇ پروگرامما ئۆزگەرتىلگەن ھۆججەتلەرنىڭ كونا نەشرىنى ئاپتوماتىك ساقلايدۇ.",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "بۇ پروگرامما ئۆزگەرتىلگەن ھۆججەتلەرنىڭ كونا نەشرىنى ئاپتوماتىك ساقلايدۇ. قوزغىتىلغاندا ، ھەر بىر ئىشلەتكۈچىنىڭ مۇندەرىجىسىدە يوشۇرۇن نەشرى قىسقۇچ تەمىنلەنگەن بولۇپ ، كونا ھۆججەت نەشرىنى ساقلاشقا ئىشلىتىلىدۇ. ئىشلەتكۈچى خالىغان ۋاقىتتا تور كۆرۈنمە يۈزى ئارقىلىق كونا نەشرىگە قايتالايدۇ ، ئالماشتۇرۇلغان ھۆججەت نەشرىگە ئايلىنىدۇ. بۇ دېتال نەشرى قىسقۇچنى ئاپتوماتىك باشقۇرۇپ ، نەشرى سەۋەبىدىن ھېساباتنىڭ نورمىدىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىدۇ.\n\t\tنەشرىنىڭ ۋاقتى توشقاندىن باشقا ، نەشىر دېتالى ھېساباتنىڭ ھازىر بار بولغان بوشلۇقنىڭ%50 تىن كۆپرەكىنى ھەرگىز ئىشلەتمەسلىككە كاپالەتلىك قىلىدۇ. ئەگەر ساقلانغان نەشرى بۇ چەكتىن ئېشىپ كەتسە ، ئەپ بۇ چەككە توشقۇچە ئەڭ كونا نەشرىنى ئۆچۈرۈۋېتىدۇ. تېخىمۇ كۆپ ئۇچۇرلار نەشىر ھۆججىتىدە بار.",
+ "Current version" : "نۆۋەتتىكى نەشرى",
+ "Initial version" : "دەسلەپكى نەشرى",
+ "You" : "سەن",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} HumanExplicitDate from نەشرىدىكى مەشغۇلاتلار",
+ "Name this version" : "بۇ نەشرىگە ئىسىم قويۇڭ",
+ "Edit version name" : "نەشرىنىڭ نامىنى تەھرىرلەش",
+ "Compare to current version" : "ھازىرقى نەشرىگە سېلىشتۇرۇڭ",
+ "Restore version" : "نەشرىنى ئەسلىگە كەلتۈرۈش",
+ "Download version" : "نەشرىنى چۈشۈرۈش",
+ "Delete version" : "نەشرىنى ئۆچۈرۈڭ",
+ "Cancel" : "بىكار قىلىش",
+ "Remove version name" : "نەشرىنىڭ نامىنى ئۆچۈرۈڭ",
+ "Save version name" : "نەشرىنىڭ نامىنى ساقلاڭ",
+ "Version name" : "نەشرىنىڭ ئىسمى",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "ئىسمى بار نەشرى ساقلاپ قېلىنىدۇ ، ساقلاش نورمىسى توشقاندا ئاپتوماتىك تازىلاشتىن چىقىرىۋېتىلىدۇ.",
+ "Initial version restored" : "دەسلەپكى نەشرى ئەسلىگە كەلدى",
+ "Version restored" : "نەشرى ئەسلىگە كەلتۈرۈلدى",
+ "Could not restore version" : "نەشرىنى ئەسلىگە كەلتۈرەلمىدى",
+ "Could not set version label" : "نەشىر بەلگىسىنى تەڭشىيەلمىدى",
+ "Could not delete version" : "نەشرىنى ئۆچۈرەلمىدى"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/uk.js b/apps/files_versions/l10n/uk.js
index 7b697b8f868..8b98d0f28c6 100644
--- a/apps/files_versions/l10n/uk.js
+++ b/apps/files_versions/l10n/uk.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "Версії",
"This application automatically maintains older versions of files that are changed." : "Цей застосунок підтримує роботу з попередніми версіями файлів, які було змінено.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Цей застосунок автоматично обслуговує попередні версії файлів, які були змінені. Коли застосунок ввімкнено, у кожній теці користувача створюється прихована тека версій, у якій зберігаються старі версії файлів. Користувач за допомогою веб-інтерфейсу може повернутися у будь-який момент до однієї з попередніх версій файлу. При цьому файл, що замінюється, стає однією з версій. Застосунок також автоматично відслідковує теки версій, щоб задовольнити обмеження користувацьких квот.\n\t\tКрім відслідковування терміну збереження версій застосунок також забезпечує обмеження використаного версіями об'єму, щоб версії ніколи не використовували більше 50% доступного користувачу вільного дискового простору. В разі перевищення вказаних лімітів застосунок автоматично вилучає найдавніші версії аж до повернення в межі лімітів. Додаткова інформація доступна у документації до застосунку Версії.",
- "Failed to revert {file} to revision {timestamp}." : "Не вдалося повернути {file} до ревізії {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n байт","%n байти","%n байтів","%n байтів"],
- "Restore" : "Відновити",
- "No other versions available" : "Інші версії недоступні"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ця програма автоматично зберігає старі версії файлів, які були змінені. Коли ця функція увімкнена, у каталозі кожного користувача створюється прихований каталог «версії», яка використовується для зберігання старих версій файлів. Користувач може в будь-який час повернутися до старішої версії через веб-інтерфейс, а замінений файл стане версією. Програма автоматично керує каталогом «версії», щоб уникнути перевищення квоти облікового запису через версії.\n\nОкрім терміну дії версій, програма «Версії» гарантує, що ніколи не буде використовуватися більше 50% вільного місця, доступного на даний момент в обліковому записі. Якщо збережені версії перевищують цей ліміт, програма спочатку видалить найстаріші версії, доки не буде досягнуто цього ліміту. Більше інформації можна знайти в документації «Версії».",
+ "Current version" : "Поточна версія",
+ "Initial version" : "Початкова версія",
+ "You" : "Ви",
+ "Actions for version from {versionHumanExplicitDate}" : "Дії для версії від {versionHumanExplicitDate}",
+ "Name this version" : "Назвіть цю версію",
+ "Edit version name" : "Редагуйте назву версії",
+ "Compare to current version" : "Порівняти з поточною версією",
+ "Restore version" : "Відновити версію",
+ "Download version" : "Звантажити версію",
+ "Delete version" : "Вилучити версію",
+ "Cancel" : "Скасувати",
+ "Remove version name" : "Вилучити назву версії",
+ "Save version name" : "Зберегти назву версії",
+ "Version name" : "Назва версії",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Версії з назвами є постійними та їх виключено з автоматичного очищення після переповнення квоти у сховищі.",
+ "Initial version restored" : "Початкову версію відновлено",
+ "Version restored" : "Версію відновлено",
+ "Could not restore version" : "Не вдалося відновити версію",
+ "Could not set version label" : "Не вдалося встановити ярлик версії",
+ "Could not delete version" : "Не вдалося вилучити версію",
+ "File versions" : "Версії файлу"
},
"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);");
diff --git a/apps/files_versions/l10n/uk.json b/apps/files_versions/l10n/uk.json
index 2dbcaccedd3..e9ec39ed3d9 100644
--- a/apps/files_versions/l10n/uk.json
+++ b/apps/files_versions/l10n/uk.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "Версії",
"This application automatically maintains older versions of files that are changed." : "Цей застосунок підтримує роботу з попередніми версіями файлів, які було змінено.",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Цей застосунок автоматично обслуговує попередні версії файлів, які були змінені. Коли застосунок ввімкнено, у кожній теці користувача створюється прихована тека версій, у якій зберігаються старі версії файлів. Користувач за допомогою веб-інтерфейсу може повернутися у будь-який момент до однієї з попередніх версій файлу. При цьому файл, що замінюється, стає однією з версій. Застосунок також автоматично відслідковує теки версій, щоб задовольнити обмеження користувацьких квот.\n\t\tКрім відслідковування терміну збереження версій застосунок також забезпечує обмеження використаного версіями об'єму, щоб версії ніколи не використовували більше 50% доступного користувачу вільного дискового простору. В разі перевищення вказаних лімітів застосунок автоматично вилучає найдавніші версії аж до повернення в межі лімітів. Додаткова інформація доступна у документації до застосунку Версії.",
- "Failed to revert {file} to revision {timestamp}." : "Не вдалося повернути {file} до ревізії {timestamp}.",
- "_%n byte_::_%n bytes_" : ["%n байт","%n байти","%n байтів","%n байтів"],
- "Restore" : "Відновити",
- "No other versions available" : "Інші версії недоступні"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Ця програма автоматично зберігає старі версії файлів, які були змінені. Коли ця функція увімкнена, у каталозі кожного користувача створюється прихований каталог «версії», яка використовується для зберігання старих версій файлів. Користувач може в будь-який час повернутися до старішої версії через веб-інтерфейс, а замінений файл стане версією. Програма автоматично керує каталогом «версії», щоб уникнути перевищення квоти облікового запису через версії.\n\nОкрім терміну дії версій, програма «Версії» гарантує, що ніколи не буде використовуватися більше 50% вільного місця, доступного на даний момент в обліковому записі. Якщо збережені версії перевищують цей ліміт, програма спочатку видалить найстаріші версії, доки не буде досягнуто цього ліміту. Більше інформації можна знайти в документації «Версії».",
+ "Current version" : "Поточна версія",
+ "Initial version" : "Початкова версія",
+ "You" : "Ви",
+ "Actions for version from {versionHumanExplicitDate}" : "Дії для версії від {versionHumanExplicitDate}",
+ "Name this version" : "Назвіть цю версію",
+ "Edit version name" : "Редагуйте назву версії",
+ "Compare to current version" : "Порівняти з поточною версією",
+ "Restore version" : "Відновити версію",
+ "Download version" : "Звантажити версію",
+ "Delete version" : "Вилучити версію",
+ "Cancel" : "Скасувати",
+ "Remove version name" : "Вилучити назву версії",
+ "Save version name" : "Зберегти назву версії",
+ "Version name" : "Назва версії",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Версії з назвами є постійними та їх виключено з автоматичного очищення після переповнення квоти у сховищі.",
+ "Initial version restored" : "Початкову версію відновлено",
+ "Version restored" : "Версію відновлено",
+ "Could not restore version" : "Не вдалося відновити версію",
+ "Could not set version label" : "Не вдалося встановити ярлик версії",
+ "Could not delete version" : "Не вдалося вилучити версію",
+ "File versions" : "Версії файлу"
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/ur_PK.js b/apps/files_versions/l10n/ur_PK.js
deleted file mode 100644
index ae55363a2dd..00000000000
--- a/apps/files_versions/l10n/ur_PK.js
+++ /dev/null
@@ -1,6 +0,0 @@
-OC.L10N.register(
- "files_versions",
- {
- "Restore" : "بحال"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_versions/l10n/ur_PK.json b/apps/files_versions/l10n/ur_PK.json
deleted file mode 100644
index bfbcb42de28..00000000000
--- a/apps/files_versions/l10n/ur_PK.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{ "translations": {
- "Restore" : "بحال"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/files_versions/l10n/vi.js b/apps/files_versions/l10n/vi.js
index 208dc7b410e..2b9a02aa4e1 100644
--- a/apps/files_versions/l10n/vi.js
+++ b/apps/files_versions/l10n/vi.js
@@ -2,8 +2,24 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "Phiên bản",
- "Failed to revert {file} to revision {timestamp}." : "Thất bại khi trở lại {file} khi sử đổi {timestamp}.",
- "Restore" : "Khôi phục",
- "No other versions available" : "Không có các phiên bản khác có sẵn"
+ "This application automatically maintains older versions of files that are changed." : "ng dụng này tự động duy trì các phiên bản cũ hơn của tệp đã được thay đổi.",
+ "Current version" : "Phiên bản hiện tại",
+ "Initial version" : "Phiên bản đầu tiên",
+ "You" : "Bạn",
+ "Name this version" : "Đặt tên cho phiên bản này",
+ "Edit version name" : "Chỉnh sửa tên phiên bản",
+ "Compare to current version" : "So sánh với phiên bản hiện tại",
+ "Restore version" : "Khôi phục phiên bản",
+ "Download version" : "Tải xuống phiên bản",
+ "Delete version" : "Xóa phiên bản",
+ "Cancel" : "Hủy",
+ "Remove version name" : "Xóa tên phiên bản",
+ "Save version name" : "Lưu tên phiên bản",
+ "Version name" : "Tên phiên bản",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Các phiên bản được đặt tên vẫn được duy trì và bị loại khỏi quá trình dọn dẹp tự động khi hạn mức bộ nhớ của bạn đã đầy.",
+ "Initial version restored" : "Đã khôi phục phiên bản ban đầu",
+ "Version restored" : "Đã khôi phục phiên bản",
+ "Could not restore version" : "Không thể khôi phục phiên bản",
+ "Could not delete version" : "Không thể xóa phiên bản"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/vi.json b/apps/files_versions/l10n/vi.json
index 7412f8b01c8..db50330b5dc 100644
--- a/apps/files_versions/l10n/vi.json
+++ b/apps/files_versions/l10n/vi.json
@@ -1,7 +1,23 @@
{ "translations": {
"Versions" : "Phiên bản",
- "Failed to revert {file} to revision {timestamp}." : "Thất bại khi trở lại {file} khi sử đổi {timestamp}.",
- "Restore" : "Khôi phục",
- "No other versions available" : "Không có các phiên bản khác có sẵn"
+ "This application automatically maintains older versions of files that are changed." : "ng dụng này tự động duy trì các phiên bản cũ hơn của tệp đã được thay đổi.",
+ "Current version" : "Phiên bản hiện tại",
+ "Initial version" : "Phiên bản đầu tiên",
+ "You" : "Bạn",
+ "Name this version" : "Đặt tên cho phiên bản này",
+ "Edit version name" : "Chỉnh sửa tên phiên bản",
+ "Compare to current version" : "So sánh với phiên bản hiện tại",
+ "Restore version" : "Khôi phục phiên bản",
+ "Download version" : "Tải xuống phiên bản",
+ "Delete version" : "Xóa phiên bản",
+ "Cancel" : "Hủy",
+ "Remove version name" : "Xóa tên phiên bản",
+ "Save version name" : "Lưu tên phiên bản",
+ "Version name" : "Tên phiên bản",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "Các phiên bản được đặt tên vẫn được duy trì và bị loại khỏi quá trình dọn dẹp tự động khi hạn mức bộ nhớ của bạn đã đầy.",
+ "Initial version restored" : "Đã khôi phục phiên bản ban đầu",
+ "Version restored" : "Đã khôi phục phiên bản",
+ "Could not restore version" : "Không thể khôi phục phiên bản",
+ "Could not delete version" : "Không thể xóa phiên bản"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/zh_CN.js b/apps/files_versions/l10n/zh_CN.js
index dc764809dc0..cdc937e9c11 100644
--- a/apps/files_versions/l10n/zh_CN.js
+++ b/apps/files_versions/l10n/zh_CN.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "版本",
"This application automatically maintains older versions of files that are changed." : "此应用程序自动维护已更改文件的旧版本。",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此应用程序自动维护已更改文件的旧版本。 启用后,每个用户目录中都会设置一个隐藏版本文件夹,该文件夹用于存储旧文件版本。 用户可以随时通过网页界面还原到较旧的版本,替换后的文件成为一个版本。 该应用会自动管理版本文件夹,以确保用户不会因版本而用完配额。\n\t\t除了版本有效期外,版本应用程序还可确保永远不会使用用户当前可用空间的 50% 以上。 如果存储的版本超出此限制,则应用将首先删除最旧的版本,直到满足该限制。 有关更多信息,请参见“版本”文档。",
- "Failed to revert {file} to revision {timestamp}." : "无法将 {file} 还原为修订版 {timestamp}。",
- "_%n byte_::_%n bytes_" : ["%n 个字节"],
- "Restore" : "恢复",
- "No other versions available" : "没有其他可用版本"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此应用程序将会自动保留已被更改的老版本文件。当此应用被启用时,每个用户的目录中都会呈现一个用于版本存储的隐藏文件夹。用户可以随时通过网页将文件恢复到旧版本,替换的文件将作为最新版本。应用程序将自动管理版本文件夹以确保账户不会因保留历史版本耗尽存储空间。\n\t\t除了版本有效期限以外,应用程序会确保保留历史版本的文件不会占用超过账户目前可用空间50%。如果存储的版本超出此限制,则版本管理会先删除最早的版本直至低于存储限制。更多资讯详见“版本”说明文档。",
+ "Current version" : "当前版本",
+ "Initial version" : "初始版本",
+ "You" : "您",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} 版本的操作",
+ "Name this version" : "命名此版本",
+ "Edit version name" : "编辑版本名",
+ "Compare to current version" : "与当前版本比较",
+ "Restore version" : "恢复版本",
+ "Download version" : "下载版本",
+ "Delete version" : "删除版本",
+ "Cancel" : "取消",
+ "Remove version name" : "删除版本名",
+ "Save version name" : "保存版本名",
+ "Version name" : "版本名",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "命名版本会保留,且当你的存储配额已满时,它将被从自动清理中排除。",
+ "Initial version restored" : "已还原最初版本",
+ "Version restored" : "版本已还原",
+ "Could not restore version" : "无法还原版本",
+ "Could not set version label" : "无法设置版本标签",
+ "Could not delete version" : "无法删除版本",
+ "File versions" : "文件版本"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/zh_CN.json b/apps/files_versions/l10n/zh_CN.json
index 4480e9bf9d6..24943a2fbf1 100644
--- a/apps/files_versions/l10n/zh_CN.json
+++ b/apps/files_versions/l10n/zh_CN.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "版本",
"This application automatically maintains older versions of files that are changed." : "此应用程序自动维护已更改文件的旧版本。",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此应用程序自动维护已更改文件的旧版本。 启用后,每个用户目录中都会设置一个隐藏版本文件夹,该文件夹用于存储旧文件版本。 用户可以随时通过网页界面还原到较旧的版本,替换后的文件成为一个版本。 该应用会自动管理版本文件夹,以确保用户不会因版本而用完配额。\n\t\t除了版本有效期外,版本应用程序还可确保永远不会使用用户当前可用空间的 50% 以上。 如果存储的版本超出此限制,则应用将首先删除最旧的版本,直到满足该限制。 有关更多信息,请参见“版本”文档。",
- "Failed to revert {file} to revision {timestamp}." : "无法将 {file} 还原为修订版 {timestamp}。",
- "_%n byte_::_%n bytes_" : ["%n 个字节"],
- "Restore" : "恢复",
- "No other versions available" : "没有其他可用版本"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此应用程序将会自动保留已被更改的老版本文件。当此应用被启用时,每个用户的目录中都会呈现一个用于版本存储的隐藏文件夹。用户可以随时通过网页将文件恢复到旧版本,替换的文件将作为最新版本。应用程序将自动管理版本文件夹以确保账户不会因保留历史版本耗尽存储空间。\n\t\t除了版本有效期限以外,应用程序会确保保留历史版本的文件不会占用超过账户目前可用空间50%。如果存储的版本超出此限制,则版本管理会先删除最早的版本直至低于存储限制。更多资讯详见“版本”说明文档。",
+ "Current version" : "当前版本",
+ "Initial version" : "初始版本",
+ "You" : "您",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} 版本的操作",
+ "Name this version" : "命名此版本",
+ "Edit version name" : "编辑版本名",
+ "Compare to current version" : "与当前版本比较",
+ "Restore version" : "恢复版本",
+ "Download version" : "下载版本",
+ "Delete version" : "删除版本",
+ "Cancel" : "取消",
+ "Remove version name" : "删除版本名",
+ "Save version name" : "保存版本名",
+ "Version name" : "版本名",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "命名版本会保留,且当你的存储配额已满时,它将被从自动清理中排除。",
+ "Initial version restored" : "已还原最初版本",
+ "Version restored" : "版本已还原",
+ "Could not restore version" : "无法还原版本",
+ "Could not set version label" : "无法设置版本标签",
+ "Could not delete version" : "无法删除版本",
+ "File versions" : "文件版本"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/zh_HK.js b/apps/files_versions/l10n/zh_HK.js
index 2b5d5c284f6..48a566dc6cb 100644
--- a/apps/files_versions/l10n/zh_HK.js
+++ b/apps/files_versions/l10n/zh_HK.js
@@ -3,10 +3,27 @@ OC.L10N.register(
{
"Versions" : "版本",
"This application automatically maintains older versions of files that are changed." : "本應用程式會自動保存修改前舊版本的檔案",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已變更過檔案的較舊版本。啟用後,每個用戶目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。用戶可以在任何時候透過網路界面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保用戶不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保用戶永遠不會使用超過用戶目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」文件。",
- "Failed to revert {file} to revision {timestamp}." : "無法還原檔案 {file} 至版本 {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n bytes"],
- "Restore" : "復原",
- "No other versions available" : "沒有其他版本了"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已更改過的檔案的較舊版本。啟用後,每個用戶目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。用戶可以在任何時候透過網路界面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保帳戶不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保不會使用超過帳戶目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」說明書。",
+ "Current version" : "目前版本",
+ "Initial version" : "初始版本",
+ "You" : "您",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} 版本的操作",
+ "Name this version" : "為此版本命名",
+ "Edit version name" : "編輯版本名稱",
+ "Compare to current version" : "與目前版本比較",
+ "Restore version" : "還原版本",
+ "Download version" : "下載版本",
+ "Delete version" : "刪除版本",
+ "Cancel" : "取消",
+ "Remove version name" : "移除版本名稱",
+ "Save version name" : "儲存版本名稱",
+ "Version name" : "版本名稱",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "命名版本會保留,並在儲存配額已滿時從自動清理中排除。",
+ "Initial version restored" : "初始版本已還原",
+ "Version restored" : "版本已還原",
+ "Could not restore version" : "無法還原版本",
+ "Could not set version label" : "無法設置版本標籤",
+ "Could not delete version" : "無法刪除版本",
+ "File versions" : "檔案版本"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/zh_HK.json b/apps/files_versions/l10n/zh_HK.json
index 23c6fee3e0c..b3ef15aae24 100644
--- a/apps/files_versions/l10n/zh_HK.json
+++ b/apps/files_versions/l10n/zh_HK.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "版本",
"This application automatically maintains older versions of files that are changed." : "本應用程式會自動保存修改前舊版本的檔案",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已變更過檔案的較舊版本。啟用後,每個用戶目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。用戶可以在任何時候透過網路界面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保用戶不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保用戶永遠不會使用超過用戶目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」文件。",
- "Failed to revert {file} to revision {timestamp}." : "無法還原檔案 {file} 至版本 {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n bytes"],
- "Restore" : "復原",
- "No other versions available" : "沒有其他版本了"
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已更改過的檔案的較舊版本。啟用後,每個用戶目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。用戶可以在任何時候透過網路界面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保帳戶不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保不會使用超過帳戶目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」說明書。",
+ "Current version" : "目前版本",
+ "Initial version" : "初始版本",
+ "You" : "您",
+ "Actions for version from {versionHumanExplicitDate}" : "{versionHumanExplicitDate} 版本的操作",
+ "Name this version" : "為此版本命名",
+ "Edit version name" : "編輯版本名稱",
+ "Compare to current version" : "與目前版本比較",
+ "Restore version" : "還原版本",
+ "Download version" : "下載版本",
+ "Delete version" : "刪除版本",
+ "Cancel" : "取消",
+ "Remove version name" : "移除版本名稱",
+ "Save version name" : "儲存版本名稱",
+ "Version name" : "版本名稱",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "命名版本會保留,並在儲存配額已滿時從自動清理中排除。",
+ "Initial version restored" : "初始版本已還原",
+ "Version restored" : "版本已還原",
+ "Could not restore version" : "無法還原版本",
+ "Could not set version label" : "無法設置版本標籤",
+ "Could not delete version" : "無法刪除版本",
+ "File versions" : "檔案版本"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_versions/l10n/zh_TW.js b/apps/files_versions/l10n/zh_TW.js
index 75e2ec8f6ae..8cb5f7c5c32 100644
--- a/apps/files_versions/l10n/zh_TW.js
+++ b/apps/files_versions/l10n/zh_TW.js
@@ -2,11 +2,28 @@ OC.L10N.register(
"files_versions",
{
"Versions" : "版本",
- "This application automatically maintains older versions of files that are changed." : "本應用程式會自動維護修改前舊版本的檔案",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已變更過檔案的較舊版本。啟用後,每個使用者目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。使用者可以在任何時候透過網路介面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保使用者不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保使用者永遠不會使用超過使用者目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」文件。",
- "Failed to revert {file} to revision {timestamp}." : "無法還原檔案 {file} 至版本 {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n 位元組"],
- "Restore" : "還原",
- "No other versions available" : "沒有其他版本了"
+ "This application automatically maintains older versions of files that are changed." : "本應用程式會自動維護檔案較舊的修改版本。",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已變更過檔案的較舊版本。啟用後,每個使用者目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。使用者可以在任何時候透過網路介面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保使用者不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保使用者永遠不會使用超過使用者目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」文件。",
+ "Current version" : "目前版本",
+ "Initial version" : "初始版本",
+ "You" : "您",
+ "Actions for version from {versionHumanExplicitDate}" : "來自 {versionHumanExplicitDate} 版本的動作",
+ "Name this version" : "為此版本命名",
+ "Edit version name" : "編輯版本名稱",
+ "Compare to current version" : "與目前版本比較",
+ "Restore version" : "還原版本",
+ "Download version" : "下載版本",
+ "Delete version" : "刪除版本",
+ "Cancel" : "取消",
+ "Remove version name" : "移除版本名稱",
+ "Save version name" : "儲存版本名稱",
+ "Version name" : "版本名稱",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "命名的版本會持續保留,並且在儲存容量限制已滿時,排除在自動清理外。",
+ "Initial version restored" : "已還原初始版本",
+ "Version restored" : "版本已還原",
+ "Could not restore version" : "無法還原版本",
+ "Could not set version label" : "無法設定版本標籤",
+ "Could not delete version" : "無法刪除版本",
+ "File versions" : "檔案版本"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_versions/l10n/zh_TW.json b/apps/files_versions/l10n/zh_TW.json
index c69393ce326..f56231dcda0 100644
--- a/apps/files_versions/l10n/zh_TW.json
+++ b/apps/files_versions/l10n/zh_TW.json
@@ -1,10 +1,27 @@
{ "translations": {
"Versions" : "版本",
- "This application automatically maintains older versions of files that are changed." : "本應用程式會自動維護修改前舊版本的檔案",
- "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已變更過檔案的較舊版本。啟用後,每個使用者目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。使用者可以在任何時候透過網路介面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保使用者不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保使用者永遠不會使用超過使用者目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」文件。",
- "Failed to revert {file} to revision {timestamp}." : "無法還原檔案 {file} 至版本 {timestamp}",
- "_%n byte_::_%n bytes_" : ["%n 位元組"],
- "Restore" : "還原",
- "No other versions available" : "沒有其他版本了"
+ "This application automatically maintains older versions of files that are changed." : "本應用程式會自動維護檔案較舊的修改版本。",
+ "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the account does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the account's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "此應用程式會自動維護已變更過檔案的較舊版本。啟用後,每個使用者目錄中都會有一個隱藏的版本資料夾,此資料夾用於儲存較舊版本的檔案。使用者可以在任何時候透過網路介面還原到較舊的版本,取代目前版本成為新的版本。應用程式會自動管理版本資料夾以確保使用者不會因為版本而用完配額。\n\t\t除了版本有效期限以外,版本應用程式還會確保使用者永遠不會使用超過使用者目前可用空間的 50%。如果儲存的版本超出此限制,則應用程式會先刪除最舊的版本,直到低於此限制。更多資訊請見「版本」文件。",
+ "Current version" : "目前版本",
+ "Initial version" : "初始版本",
+ "You" : "您",
+ "Actions for version from {versionHumanExplicitDate}" : "來自 {versionHumanExplicitDate} 版本的動作",
+ "Name this version" : "為此版本命名",
+ "Edit version name" : "編輯版本名稱",
+ "Compare to current version" : "與目前版本比較",
+ "Restore version" : "還原版本",
+ "Download version" : "下載版本",
+ "Delete version" : "刪除版本",
+ "Cancel" : "取消",
+ "Remove version name" : "移除版本名稱",
+ "Save version name" : "儲存版本名稱",
+ "Version name" : "版本名稱",
+ "Named versions are persisted, and excluded from automatic cleanups when your storage quota is full." : "命名的版本會持續保留,並且在儲存容量限制已滿時,排除在自動清理外。",
+ "Initial version restored" : "已還原初始版本",
+ "Version restored" : "版本已還原",
+ "Could not restore version" : "無法還原版本",
+ "Could not set version label" : "無法設定版本標籤",
+ "Could not delete version" : "無法刪除版本",
+ "File versions" : "檔案版本"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php
index c994cd2f54a..29158276415 100644
--- a/apps/files_versions/lib/AppInfo/Application.php
+++ b/apps/files_versions/lib/AppInfo/Application.php
@@ -1,29 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\AppInfo;
@@ -33,22 +13,39 @@ use OCA\DAV\Connector\Sabre\Principal;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCA\Files\Event\LoadSidebar;
use OCA\Files_Versions\Capabilities;
-use OCA\Files_Versions\Hooks;
+use OCA\Files_Versions\Events\VersionRestoredEvent;
+use OCA\Files_Versions\Listener\FileEventsListener;
+use OCA\Files_Versions\Listener\LegacyRollbackListener;
use OCA\Files_Versions\Listener\LoadAdditionalListener;
use OCA\Files_Versions\Listener\LoadSidebarListener;
+use OCA\Files_Versions\Listener\VersionAuthorListener;
+use OCA\Files_Versions\Listener\VersionStorageMoveListener;
use OCA\Files_Versions\Versions\IVersionManager;
use OCA\Files_Versions\Versions\VersionManager;
+use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
+use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
+use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
+use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
+use OCP\Files\Events\Node\BeforeNodeTouchedEvent;
+use OCP\Files\Events\Node\BeforeNodeWrittenEvent;
+use OCP\Files\Events\Node\NodeCopiedEvent;
+use OCP\Files\Events\Node\NodeCreatedEvent;
+use OCP\Files\Events\Node\NodeDeletedEvent;
+use OCP\Files\Events\Node\NodeRenamedEvent;
+use OCP\Files\Events\Node\NodeTouchedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IServerContainer;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\L10N\IFactory;
+use OCP\Server;
use OCP\Share\IManager as IShareManager;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@@ -75,6 +72,7 @@ class Application extends App implements IBootstrap {
return new Principal(
$server->get(IUserManager::class),
$server->get(IGroupManager::class),
+ Server::get(IAccountManager::class),
$server->get(IShareManager::class),
$server->get(IUserSession::class),
$server->get(IAppManager::class),
@@ -85,28 +83,43 @@ class Application extends App implements IBootstrap {
);
});
- $context->registerService(IVersionManager::class, function () {
- return new VersionManager();
- });
+ $context->registerServiceAlias(IVersionManager::class, VersionManager::class);
/**
* Register Events
*/
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
$context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class);
+
+ $context->registerEventListener(BeforeNodeRenamedEvent::class, VersionStorageMoveListener::class);
+ $context->registerEventListener(NodeRenamedEvent::class, VersionStorageMoveListener::class);
+ $context->registerEventListener(BeforeNodeCopiedEvent::class, VersionStorageMoveListener::class);
+ $context->registerEventListener(NodeCopiedEvent::class, VersionStorageMoveListener::class);
+
+ $context->registerEventListener(NodeCreatedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(BeforeNodeTouchedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(NodeTouchedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(BeforeNodeWrittenEvent::class, FileEventsListener::class);
+ $context->registerEventListener(NodeWrittenEvent::class, FileEventsListener::class);
+ $context->registerEventListener(BeforeNodeDeletedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(NodeDeletedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(NodeRenamedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(NodeCopiedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(BeforeNodeRenamedEvent::class, FileEventsListener::class);
+ $context->registerEventListener(BeforeNodeCopiedEvent::class, FileEventsListener::class);
+
+ // we add the version author listener with lower priority to make sure new versions already are created by FileEventsListener
+ $context->registerEventListener(NodeWrittenEvent::class, VersionAuthorListener::class, -1);
+
+ $context->registerEventListener(VersionRestoredEvent::class, LegacyRollbackListener::class);
}
public function boot(IBootContext $context): void {
$context->injectFn(\Closure::fromCallable([$this, 'registerVersionBackends']));
-
- /**
- * Register hooks
- */
- Hooks::connectHooks();
}
public function registerVersionBackends(ContainerInterface $container, IAppManager $appManager, LoggerInterface $logger): void {
- foreach ($appManager->getInstalledApps() as $app) {
+ foreach ($appManager->getEnabledApps() as $app) {
$appInfo = $appManager->getAppInfo($app);
if (isset($appInfo['versions'])) {
$backends = $appInfo['versions'];
diff --git a/apps/files_versions/lib/BackgroundJob/ExpireVersions.php b/apps/files_versions/lib/BackgroundJob/ExpireVersions.php
index a8a311f0a05..794cbc5b882 100644
--- a/apps/files_versions/lib/BackgroundJob/ExpireVersions.php
+++ b/apps/files_versions/lib/BackgroundJob/ExpireVersions.php
@@ -1,59 +1,33 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\BackgroundJob;
+use OC\Files\View;
use OCA\Files_Versions\Expiration;
use OCA\Files_Versions\Storage;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\TimedJob;
use OCP\IConfig;
use OCP\IUser;
use OCP\IUserManager;
-class ExpireVersions extends \OC\BackgroundJob\TimedJob {
+class ExpireVersions extends TimedJob {
public const ITEMS_PER_SESSION = 1000;
- /** @var IConfig */
- private $config;
-
- /**
- * @var Expiration
- */
- private $expiration;
-
- /**
- * @var IUserManager
- */
- private $userManager;
-
- public function __construct(IConfig $config, IUserManager $userManager, Expiration $expiration) {
+ public function __construct(
+ private IConfig $config,
+ private IUserManager $userManager,
+ private Expiration $expiration,
+ ITimeFactory $time,
+ ) {
+ parent::__construct($time);
// Run once per 30 minutes
$this->setInterval(60 * 30);
-
- $this->config = $config;
- $this->expiration = $expiration;
- $this->userManager = $userManager;
}
public function run($argument) {
@@ -67,7 +41,7 @@ class ExpireVersions extends \OC\BackgroundJob\TimedJob {
return;
}
- $this->userManager->callForSeenUsers(function (IUser $user) {
+ $this->userManager->callForSeenUsers(function (IUser $user): void {
$uid = $user->getUID();
if (!$this->setupFS($uid)) {
return;
@@ -78,15 +52,13 @@ class ExpireVersions extends \OC\BackgroundJob\TimedJob {
/**
* Act on behalf on trash item owner
- * @param string $user
- * @return boolean
*/
- protected function setupFS($user) {
+ protected function setupFS(string $user): bool {
\OC_Util::tearDownFS();
\OC_Util::setupFS($user);
// Check if this user has a versions directory
- $view = new \OC\Files\View('/' . $user);
+ $view = new View('/' . $user);
if (!$view->is_dir('/files_versions')) {
return false;
}
diff --git a/apps/files_versions/lib/Capabilities.php b/apps/files_versions/lib/Capabilities.php
index b8602540ec8..cb6394f0a36 100644
--- a/apps/files_versions/lib/Capabilities.php
+++ b/apps/files_versions/lib/Capabilities.php
@@ -1,42 +1,34 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Tom Needham <tom@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions;
+use OCP\App\IAppManager;
use OCP\Capabilities\ICapability;
+use OCP\IConfig;
class Capabilities implements ICapability {
-
+ public function __construct(
+ private IConfig $config,
+ private IAppManager $appManager,
+ ) {
+ }
+
/**
* Return this classes capabilities
*
- * @return array
+ * @return array{files: array{versioning: bool, version_labeling: bool, version_deletion: bool}}
*/
public function getCapabilities() {
return [
'files' => [
- 'versioning' => true
+ 'versioning' => true,
+ 'version_labeling' => $this->config->getSystemValueBool('enable_version_labeling', true),
+ 'version_deletion' => $this->config->getSystemValueBool('enable_version_deletion', true),
]
];
}
diff --git a/apps/files_versions/lib/Command/CleanUp.php b/apps/files_versions/lib/Command/CleanUp.php
index d7bb4caa483..e8c46afef16 100644
--- a/apps/files_versions/lib/Command/CleanUp.php
+++ b/apps/files_versions/lib/Command/CleanUp.php
@@ -1,29 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Daniel Rudolf <nextcloud.com@daniel-rudolf.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Command;
+use OCA\Files_Versions\Db\VersionsMapper;
use OCP\Files\IRootFolder;
use OCP\IUserBackend;
use OCP\IUserManager;
@@ -34,24 +18,15 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class CleanUp extends Command {
-
- /** @var IUserManager */
- protected $userManager;
-
- /** @var IRootFolder */
- protected $rootFolder;
-
- /**
- * @param IRootFolder $rootFolder
- * @param IUserManager $userManager
- */
- public function __construct(IRootFolder $rootFolder, IUserManager $userManager) {
+ public function __construct(
+ protected IRootFolder $rootFolder,
+ protected IUserManager $userManager,
+ protected VersionsMapper $versionMapper,
+ ) {
parent::__construct();
- $this->userManager = $userManager;
- $this->rootFolder = $rootFolder;
}
- protected function configure() {
+ protected function configure(): void {
$this
->setName('versions:cleanup')
->setDescription('Delete versions')
@@ -75,8 +50,8 @@ class CleanUp extends Command {
$path = $input->getOption('path');
if ($path) {
if (!preg_match('#^/([^/]+)/files(/.*)?$#', $path, $pathMatches)) {
- $output->writeln("<error>Invalid path given</error>");
- return 1;
+ $output->writeln('<error>Invalid path given</error>');
+ return self::FAILURE;
}
$users = [ $pathMatches[1] ];
@@ -85,51 +60,53 @@ class CleanUp extends Command {
if (!empty($users)) {
foreach ($users as $user) {
- if ($this->userManager->userExists($user)) {
- $output->writeln("Delete versions of <info>$user</info>");
- $this->deleteVersions($user, $path);
- } else {
+ if (!$this->userManager->userExists($user)) {
$output->writeln("<error>Unknown user $user</error>");
- return 1;
+ return self::FAILURE;
}
+
+ $output->writeln("Delete versions of <info>$user</info>");
+ $this->deleteVersions($user, $path);
}
- } else {
- $output->writeln('Delete all versions');
- foreach ($this->userManager->getBackends() as $backend) {
- $name = get_class($backend);
+ return self::SUCCESS;
+ }
- if ($backend instanceof IUserBackend) {
- $name = $backend->getBackendName();
- }
+ $output->writeln('Delete all versions');
+ foreach ($this->userManager->getBackends() as $backend) {
+ $name = get_class($backend);
- $output->writeln("Delete versions for users on backend <info>$name</info>");
-
- $limit = 500;
- $offset = 0;
- do {
- $users = $backend->getUsers('', $limit, $offset);
- foreach ($users as $user) {
- $output->writeln(" <info>$user</info>");
- $this->deleteVersions($user);
- }
- $offset += $limit;
- } while (count($users) >= $limit);
+ if ($backend instanceof IUserBackend) {
+ $name = $backend->getBackendName();
}
+
+ $output->writeln("Delete versions for users on backend <info>$name</info>");
+
+ $limit = 500;
+ $offset = 0;
+ do {
+ $users = $backend->getUsers('', $limit, $offset);
+ foreach ($users as $user) {
+ $output->writeln(" <info>$user</info>");
+ $this->deleteVersions($user);
+ }
+ $offset += $limit;
+ } while (count($users) >= $limit);
}
- return 0;
+
+ return self::SUCCESS;
}
/**
* delete versions for the given user
- *
- * @param string $user
- * @param string|null $path
*/
- protected function deleteVersions(string $user, string $path = null): void {
+ protected function deleteVersions(string $user, ?string $path = null): void {
\OC_Util::tearDownFS();
\OC_Util::setupFS($user);
+ $userHomeStorageId = $this->rootFolder->getUserFolder($user)->getStorage()->getCache()->getNumericStorageId();
+ $this->versionMapper->deleteAllVersionsForUser($userHomeStorageId, $path);
+
$fullPath = '/' . $user . '/files_versions' . ($path ? '/' . $path : '');
if ($this->rootFolder->nodeExists($fullPath)) {
$this->rootFolder->get($fullPath)->delete();
diff --git a/apps/files_versions/lib/Command/Expire.php b/apps/files_versions/lib/Command/Expire.php
index 62b2343a5e0..a30e623c347 100644
--- a/apps/files_versions/lib/Command/Expire.php
+++ b/apps/files_versions/lib/Command/Expire.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Command;
@@ -28,29 +12,21 @@ use OCA\Files_Versions\Storage;
use OCP\Command\ICommand;
use OCP\Files\StorageNotAvailableException;
use OCP\IUserManager;
+use OCP\Server;
use Psr\Log\LoggerInterface;
class Expire implements ICommand {
use FileAccess;
- /**
- * @var string
- */
- private $fileName;
-
- /**
- * @var string
- */
- private $user;
-
- public function __construct(string $user, string $fileName) {
- $this->user = $user;
- $this->fileName = $fileName;
+ public function __construct(
+ private string $user,
+ private string $fileName,
+ ) {
}
- public function handle() {
+ public function handle(): void {
/** @var IUserManager $userManager */
- $userManager = \OC::$server->get(IUserManager::class);
+ $userManager = Server::get(IUserManager::class);
if (!$userManager->userExists($this->user)) {
// User has been deleted already
return;
@@ -62,8 +38,7 @@ class Expire implements ICommand {
// In case of external storage and session credentials, the expiration
// fails because the command does not have those credentials
- /** @var LoggerInterface */
- $logger = \OC::$server->get(LoggerInterface::class);
+ $logger = Server::get(LoggerInterface::class);
$logger->warning($e->getMessage(), [
'exception' => $e,
'uid' => $this->user,
diff --git a/apps/files_versions/lib/Command/ExpireVersions.php b/apps/files_versions/lib/Command/ExpireVersions.php
index 43068e21451..d3f341a21d2 100644
--- a/apps/files_versions/lib/Command/ExpireVersions.php
+++ b/apps/files_versions/lib/Command/ExpireVersions.php
@@ -1,30 +1,13 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud GmbH.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud GmbH.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Command;
+use OC\Files\View;
use OCA\Files_Versions\Expiration;
use OCA\Files_Versions\Storage;
use OCP\IUser;
@@ -36,73 +19,58 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ExpireVersions extends Command {
-
- /**
- * @var Expiration
- */
- private $expiration;
-
- /**
- * @var IUserManager
- */
- private $userManager;
-
- /**
- * @param IUserManager $userManager
- * @param Expiration $expiration
- */
- public function __construct(IUserManager $userManager,
- Expiration $expiration) {
+ public function __construct(
+ private IUserManager $userManager,
+ private Expiration $expiration,
+ ) {
parent::__construct();
-
- $this->userManager = $userManager;
- $this->expiration = $expiration;
}
- protected function configure() {
+ protected function configure(): void {
$this
->setName('versions:expire')
->setDescription('Expires the users file versions')
->addArgument(
'user_id',
InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
- 'expire file versions of the given user(s), if no user is given file versions for all users will be expired.'
+ 'expire file versions of the given account(s), if no account is given file versions for all accounts will be expired.'
);
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$maxAge = $this->expiration->getMaxAgeAsTimestamp();
if (!$maxAge) {
- $output->writeln("Auto expiration is configured - expiration will be handled automatically according to the expiration patterns detailed at the following link https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/file_versioning.html.");
- return 1;
+ $output->writeln('Auto expiration is configured - expiration will be handled automatically according to the expiration patterns detailed at the following link https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/file_versioning.html.');
+ return self::FAILURE;
}
$users = $input->getArgument('user_id');
if (!empty($users)) {
foreach ($users as $user) {
- if ($this->userManager->userExists($user)) {
- $output->writeln("Remove deleted files of <info>$user</info>");
- $userObject = $this->userManager->get($user);
- $this->expireVersionsForUser($userObject);
- } else {
- $output->writeln("<error>Unknown user $user</error>");
- return 1;
+ if (!$this->userManager->userExists($user)) {
+ $output->writeln("<error>Unknown account $user</error>");
+ return self::FAILURE;
}
+
+ $output->writeln("Remove deleted files of <info>$user</info>");
+ $userObject = $this->userManager->get($user);
+ $this->expireVersionsForUser($userObject);
}
- } else {
- $p = new ProgressBar($output);
- $p->start();
- $this->userManager->callForSeenUsers(function (IUser $user) use ($p) {
- $p->advance();
- $this->expireVersionsForUser($user);
- });
- $p->finish();
- $output->writeln('');
+ return self::SUCCESS;
}
- return 0;
+
+ $p = new ProgressBar($output);
+ $p->start();
+ $this->userManager->callForSeenUsers(function (IUser $user) use ($p): void {
+ $p->advance();
+ $this->expireVersionsForUser($user);
+ });
+ $p->finish();
+ $output->writeln('');
+ return self::SUCCESS;
}
- public function expireVersionsForUser(IUser $user) {
+ public function expireVersionsForUser(IUser $user): void {
$uid = $user->getUID();
if (!$this->setupFS($uid)) {
return;
@@ -112,15 +80,13 @@ class ExpireVersions extends Command {
/**
* Act on behalf on versions item owner
- * @param string $user
- * @return boolean
*/
- protected function setupFS($user) {
+ protected function setupFS(string $user): bool {
\OC_Util::tearDownFS();
\OC_Util::setupFS($user);
// Check if this user has a version directory
- $view = new \OC\Files\View('/' . $user);
+ $view = new View('/' . $user);
if (!$view->is_dir('/files_versions')) {
return false;
}
diff --git a/apps/files_versions/lib/Controller/PreviewController.php b/apps/files_versions/lib/Controller/PreviewController.php
index 0e625dc2139..2c3ff8da70d 100644
--- a/apps/files_versions/lib/Controller/PreviewController.php
+++ b/apps/files_versions/lib/Controller/PreviewController.php
@@ -1,98 +1,89 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Controller;
use OCA\Files_Versions\Versions\IVersionManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
+use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
+use OCP\AppFramework\Http\RedirectResponse;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IPreview;
use OCP\IRequest;
use OCP\IUserSession;
+use OCP\Preview\IMimeIconProvider;
+#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
class PreviewController extends Controller {
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IUserSession */
- private $userSession;
-
- /** @var IVersionManager */
- private $versionManager;
-
- /** @var IPreview */
- private $previewManager;
-
public function __construct(
string $appName,
IRequest $request,
- IRootFolder $rootFolder,
- IUserSession $userSession,
- IVersionManager $versionManager,
- IPreview $previewManager
+ private IRootFolder $rootFolder,
+ private IUserSession $userSession,
+ private IVersionManager $versionManager,
+ private IPreview $previewManager,
+ private IMimeIconProvider $mimeIconProvider,
) {
parent::__construct($appName, $request);
-
- $this->rootFolder = $rootFolder;
- $this->userSession = $userSession;
- $this->versionManager = $versionManager;
- $this->previewManager = $previewManager;
}
/**
- * @NoAdminRequired
- * @NoCSRFRequired
+ * Get the preview for a file version
*
- * @param string $file
- * @param int $x
- * @param int $y
- * @param string $version
- * @return DataResponse|FileDisplayResponse
+ * @param string $file Path of the file
+ * @param int $x Width of the preview
+ * @param int $y Height of the preview
+ * @param string $version Version of the file to get the preview for
+ * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
+ * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
+ *
+ * 200: Preview returned
+ * 303: Redirect to the mime icon url if mimeFallback is true
+ * 400: Getting preview is not possible
+ * 404: Preview not found
*/
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
public function getPreview(
string $file = '',
int $x = 44,
int $y = 44,
- string $version = ''
+ string $version = '',
+ bool $mimeFallback = false,
) {
if ($file === '' || $version === '' || $x === 0 || $y === 0) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
+ $versionFile = null;
try {
$user = $this->userSession->getUser();
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
$file = $userFolder->get($file);
$versionFile = $this->versionManager->getVersionFile($user, $file, $version);
$preview = $this->previewManager->getPreview($versionFile, $x, $y, true, IPreview::MODE_FILL, $versionFile->getMimetype());
- return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
+ $response = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
+ $response->cacheFor(3600 * 24, false, true);
+ return $response;
} catch (NotFoundException $e) {
+ // If we have no preview enabled, we can redirect to the mime icon if any
+ if ($mimeFallback && $versionFile !== null) {
+ $url = $this->mimeIconProvider->getMimeIconUrl($versionFile->getMimeType());
+ if ($url !== null) {
+ return new RedirectResponse($url);
+ }
+ }
+
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (\InvalidArgumentException $e) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
diff --git a/apps/files_versions/lib/Db/VersionEntity.php b/apps/files_versions/lib/Db/VersionEntity.php
new file mode 100644
index 00000000000..10f1dc8cbba
--- /dev/null
+++ b/apps/files_versions/lib/Db/VersionEntity.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_Versions\Db;
+
+use JsonSerializable;
+
+use OCP\AppFramework\Db\Entity;
+use OCP\DB\Types;
+
+/**
+ * @method int getFileId()
+ * @method void setFileId(int $fileId)
+ * @method int getTimestamp()
+ * @method void setTimestamp(int $timestamp)
+ * @method int|float getSize()
+ * @method void setSize(int|float $size)
+ * @method int getMimetype()
+ * @method void setMimetype(int $mimetype)
+ * @method array|null getMetadata()
+ * @method void setMetadata(array $metadata)
+ */
+class VersionEntity extends Entity implements JsonSerializable {
+ protected ?int $fileId = null;
+ protected ?int $timestamp = null;
+ protected ?int $size = null;
+ protected ?int $mimetype = null;
+ protected ?array $metadata = null;
+
+ public function __construct() {
+ $this->addType('id', Types::INTEGER);
+ $this->addType('file_id', Types::INTEGER);
+ $this->addType('timestamp', Types::INTEGER);
+ $this->addType('size', Types::INTEGER);
+ $this->addType('mimetype', Types::INTEGER);
+ $this->addType('metadata', Types::JSON);
+ }
+
+ public function jsonSerialize(): array {
+ return [
+ 'id' => $this->id,
+ 'file_id' => $this->fileId,
+ 'timestamp' => $this->timestamp,
+ 'size' => $this->size,
+ 'mimetype' => $this->mimetype,
+ 'metadata' => $this->metadata,
+ ];
+ }
+
+ /**
+ * @abstract given a key, return the value associated with the key in the metadata column
+ * if nothing is found, we return an empty string
+ * @param string $key key associated with the value
+ */
+ public function getMetadataValue(string $key): ?string {
+ return $this->metadata[$key] ?? null;
+ }
+
+ /**
+ * @abstract sets a key value pair in the metadata column
+ * @param string $key key associated with the value
+ * @param string $value value associated with the key
+ */
+ public function setMetadataValue(string $key, string $value): void {
+ $this->metadata[$key] = $value;
+ $this->markFieldUpdated('metadata');
+ }
+}
diff --git a/apps/files_versions/lib/Db/VersionsMapper.php b/apps/files_versions/lib/Db/VersionsMapper.php
new file mode 100644
index 00000000000..318dd8f0d82
--- /dev/null
+++ b/apps/files_versions/lib/Db/VersionsMapper.php
@@ -0,0 +1,104 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_Versions\Db;
+
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+/**
+ * @extends QBMapper<VersionEntity>
+ */
+class VersionsMapper extends QBMapper {
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'files_versions', VersionEntity::class);
+ }
+
+ /**
+ * @return VersionEntity[]
+ */
+ public function findAllVersionsForFileId(int $fileId): array {
+ $qb = $this->db->getQueryBuilder();
+
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId)));
+
+ return $this->findEntities($qb);
+ }
+
+ /**
+ * @return VersionEntity
+ */
+ public function findCurrentVersionForFileId(int $fileId): VersionEntity {
+ $qb = $this->db->getQueryBuilder();
+
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId)))
+ ->orderBy('timestamp', 'DESC')
+ ->setMaxResults(1);
+
+ return $this->findEntity($qb);
+ }
+
+ public function findVersionForFileId(int $fileId, int $timestamp): VersionEntity {
+ $qb = $this->db->getQueryBuilder();
+
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId)))
+ ->andWhere($qb->expr()->eq('timestamp', $qb->createNamedParameter($timestamp)));
+
+ return $this->findEntity($qb);
+ }
+
+ public function deleteAllVersionsForFileId(int $fileId): int {
+ $qb = $this->db->getQueryBuilder();
+
+ return $qb->delete($this->getTableName())
+ ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId)))
+ ->executeStatement();
+ }
+
+ public function deleteAllVersionsForUser(int $storageId, ?string $path = null): void {
+ $fileIdsGenerator = $this->getFileIdsGenerator($storageId, $path);
+
+ $versionEntitiesDeleteQuery = $this->db->getQueryBuilder();
+ $versionEntitiesDeleteQuery->delete($this->getTableName())
+ ->where($versionEntitiesDeleteQuery->expr()->in('file_id', $versionEntitiesDeleteQuery->createParameter('file_ids')));
+
+ foreach ($fileIdsGenerator as $fileIds) {
+ $versionEntitiesDeleteQuery->setParameter('file_ids', $fileIds, IQueryBuilder::PARAM_INT_ARRAY);
+ $versionEntitiesDeleteQuery->executeStatement();
+ }
+ }
+
+ private function getFileIdsGenerator(int $storageId, ?string $path): \Generator {
+ $offset = 0;
+ do {
+ $filesIdsSelect = $this->db->getQueryBuilder();
+ $filesIdsSelect->select('fileid')
+ ->from('filecache')
+ ->where($filesIdsSelect->expr()->eq('storage', $filesIdsSelect->createNamedParameter($storageId, IQueryBuilder::PARAM_STR)))
+ ->andWhere($filesIdsSelect->expr()->like('path', $filesIdsSelect->createNamedParameter('files' . ($path ? '/' . $this->db->escapeLikeParameter($path) : '') . '/%', IQueryBuilder::PARAM_STR)))
+ ->andWhere($filesIdsSelect->expr()->gt('fileid', $filesIdsSelect->createParameter('offset')))
+ ->setMaxResults(1000)
+ ->orderBy('fileid', 'ASC');
+
+ $filesIdsSelect->setParameter('offset', $offset, IQueryBuilder::PARAM_INT);
+ $result = $filesIdsSelect->executeQuery();
+ $fileIds = $result->fetchAll(\PDO::FETCH_COLUMN);
+ $offset = end($fileIds);
+
+ yield $fileIds;
+ } while (!empty($fileIds));
+ }
+}
diff --git a/apps/files_versions/lib/Events/CreateVersionEvent.php b/apps/files_versions/lib/Events/CreateVersionEvent.php
index d1a5bb00c35..92ed26b2dd6 100644
--- a/apps/files_versions/lib/Events/CreateVersionEvent.php
+++ b/apps/files_versions/lib/Events/CreateVersionEvent.php
@@ -1,26 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Events;
@@ -40,17 +22,15 @@ class CreateVersionEvent extends Event {
/** @var bool */
private $createVersion;
- /** @var Node */
- private $node;
-
/**
* CreateVersionEvent constructor.
*
* @param Node $node
*/
- public function __construct(Node $node) {
+ public function __construct(
+ private Node $node,
+ ) {
$this->createVersion = true;
- $this->node = $node;
}
/**
diff --git a/apps/files_versions/lib/Events/VersionCreatedEvent.php b/apps/files_versions/lib/Events/VersionCreatedEvent.php
new file mode 100644
index 00000000000..4dc7a7cb505
--- /dev/null
+++ b/apps/files_versions/lib/Events/VersionCreatedEvent.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Events;
+
+use OCA\Files_Versions\Versions\IVersion;
+use OCP\EventDispatcher\Event;
+use OCP\Files\Node;
+
+/**
+ * Event dispatched after a successful creation of a version
+ */
+class VersionCreatedEvent extends Event {
+ public function __construct(
+ private Node $node,
+ private IVersion $version,
+ ) {
+ parent::__construct();
+ }
+
+ /**
+ * Node of the file that has been versioned
+ */
+ public function getNode(): Node {
+ return $this->node;
+ }
+
+ /**
+ * Version of the file that was created
+ */
+ public function getVersion(): IVersion {
+ return $this->version;
+ }
+}
diff --git a/apps/files_versions/lib/Events/VersionRestoredEvent.php b/apps/files_versions/lib/Events/VersionRestoredEvent.php
new file mode 100644
index 00000000000..12e91bd258d
--- /dev/null
+++ b/apps/files_versions/lib/Events/VersionRestoredEvent.php
@@ -0,0 +1,33 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Events;
+
+use OCA\Files_Versions\Versions\IVersion;
+use OCP\EventDispatcher\Event;
+
+/**
+ * Class VersionRestoredEvent
+ *
+ * Event that is called after a successful restore of a previous version
+ *
+ * @package OCA\Files_Versions
+ */
+class VersionRestoredEvent extends Event {
+ public function __construct(
+ private IVersion $version,
+ ) {
+ }
+
+ /**
+ * Version that was restored
+ */
+ public function getVersion(): IVersion {
+ return $this->version;
+ }
+}
diff --git a/apps/files_versions/lib/Expiration.php b/apps/files_versions/lib/Expiration.php
index 40768e90af7..1e04d93379f 100644
--- a/apps/files_versions/lib/Expiration.php
+++ b/apps/files_versions/lib/Expiration.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions;
@@ -33,9 +16,6 @@ class Expiration {
// how long do we keep files a version if no other value is defined in the config file (unit: days)
public const NO_OBLIGATION = -1;
- /** @var ITimeFactory */
- private $timeFactory;
-
/** @var string */
private $retentionObligation;
@@ -48,12 +28,11 @@ class Expiration {
/** @var bool */
private $canPurgeToSaveSpace;
- /** @var LoggerInterface */
- private $logger;
-
- public function __construct(IConfig $config, ITimeFactory $timeFactory, LoggerInterface $logger) {
- $this->timeFactory = $timeFactory;
- $this->logger = $logger;
+ public function __construct(
+ IConfig $config,
+ private ITimeFactory $timeFactory,
+ private LoggerInterface $logger,
+ ) {
$this->retentionObligation = $config->getSystemValue('versions_retention_obligation', 'auto');
if ($this->retentionObligation !== 'disabled') {
@@ -121,6 +100,20 @@ class Expiration {
}
/**
+ * Get minimal retention obligation as a timestamp
+ *
+ * @return int|false
+ */
+ public function getMinAgeAsTimestamp() {
+ $minAge = false;
+ if ($this->isEnabled() && $this->minAge !== self::NO_OBLIGATION) {
+ $time = $this->timeFactory->getTime();
+ $minAge = $time - ($this->minAge * 86400);
+ }
+ return $minAge;
+ }
+
+ /**
* Get maximal retention obligation as a timestamp
*
* @return int|false
@@ -157,16 +150,16 @@ class Expiration {
if (!ctype_digit($minValue) && $minValue !== 'auto') {
$isValid = false;
$this->logger->warning(
- $minValue . ' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
- ['app' => 'files_versions']
+ $minValue . ' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
+ ['app' => 'files_versions']
);
}
if (!ctype_digit($maxValue) && $maxValue !== 'auto') {
$isValid = false;
$this->logger->warning(
- $maxValue . ' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
- ['app' => 'files_versions']
+ $maxValue . ' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
+ ['app' => 'files_versions']
);
}
diff --git a/apps/files_versions/lib/Hooks.php b/apps/files_versions/lib/Hooks.php
deleted file mode 100644
index 02f562b1874..00000000000
--- a/apps/files_versions/lib/Hooks.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Sam Tuke <mail@samtuke.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OCA\Files_Versions;
-
-use OC\Files\Filesystem;
-use OC\Files\Mount\MoveableMount;
-use OC\Files\View;
-use OCP\Util;
-
-class Hooks {
- public static function connectHooks() {
- // Listen to write signals
- Util::connectHook('OC_Filesystem', 'write', Hooks::class, 'write_hook');
- // Listen to delete and rename signals
- Util::connectHook('OC_Filesystem', 'post_delete', Hooks::class, 'remove_hook');
- Util::connectHook('OC_Filesystem', 'delete', Hooks::class, 'pre_remove_hook');
- Util::connectHook('OC_Filesystem', 'post_rename', Hooks::class, 'rename_hook');
- Util::connectHook('OC_Filesystem', 'post_copy', Hooks::class, 'copy_hook');
- Util::connectHook('OC_Filesystem', 'rename', Hooks::class, 'pre_renameOrCopy_hook');
- Util::connectHook('OC_Filesystem', 'copy', Hooks::class, 'pre_renameOrCopy_hook');
- }
-
- /**
- * listen to write event.
- */
- public static function write_hook(array $params): void {
- $path = $params[Filesystem::signal_param_path];
- if ($path !== '') {
- Storage::store($path);
- }
- }
-
-
- /**
- * Erase versions of deleted file
- * @param array $params
- *
- * This function is connected to the delete signal of OC_Filesystem
- * cleanup the versions directory if the actual file gets deleted
- */
- public static function remove_hook(array $params): void {
- $path = $params[Filesystem::signal_param_path];
- if ($path !== '') {
- Storage::delete($path);
- }
- }
-
- /**
- * mark file as "deleted" so that we can clean up the versions if the file is gone
- * @param array $params
- */
- public static function pre_remove_hook(array $params): void {
- $path = $params[Filesystem::signal_param_path];
- if ($path !== '') {
- Storage::markDeletedFile($path);
- }
- }
-
- /**
- * rename/move versions of renamed/moved files
- * @param array $params array with oldpath and newpath
- *
- * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
- * of the stored versions along the actual file
- */
- public static function rename_hook(array $params): void {
- $oldpath = $params['oldpath'];
- $newpath = $params['newpath'];
- if ($oldpath !== '' && $newpath !== '') {
- Storage::renameOrCopy($oldpath, $newpath, 'rename');
- }
- }
-
- /**
- * copy versions of copied files
- * @param array $params array with oldpath and newpath
- *
- * This function is connected to the copy signal of OC_Filesystem and copies the
- * the stored versions to the new location
- */
- public static function copy_hook(array $params): void {
- $oldpath = $params['oldpath'];
- $newpath = $params['newpath'];
- if ($oldpath !== '' && $newpath !== '') {
- Storage::renameOrCopy($oldpath, $newpath, 'copy');
- }
- }
-
- /**
- * Remember owner and the owner path of the source file.
- * If the file already exists, then it was a upload of a existing file
- * over the web interface and we call Storage::store() directly
- *
- * @param array $params array with oldpath and newpath
- *
- */
- public static function pre_renameOrCopy_hook(array $params): void {
- // if we rename a movable mount point, then the versions don't have
- // to be renamed
- $absOldPath = Filesystem::normalizePath('/' . \OC_User::getUser() . '/files' . $params['oldpath']);
- $manager = Filesystem::getMountManager();
- $mount = $manager->find($absOldPath);
- $internalPath = $mount->getInternalPath($absOldPath);
- if ($internalPath === '' and $mount instanceof MoveableMount) {
- return;
- }
-
- $view = new View(\OC_User::getUser() . '/files');
- if ($view->file_exists($params['newpath'])) {
- Storage::store($params['newpath']);
- } else {
- Storage::setSourcePathAndUser($params['oldpath']);
- }
- }
-}
diff --git a/apps/files_versions/lib/Listener/FileEventsListener.php b/apps/files_versions/lib/Listener/FileEventsListener.php
new file mode 100644
index 00000000000..969ca4ded45
--- /dev/null
+++ b/apps/files_versions/lib/Listener/FileEventsListener.php
@@ -0,0 +1,472 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_Versions\Listener;
+
+use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
+use OC\DB\Exceptions\DbalException;
+use OC\Files\Filesystem;
+use OC\Files\Mount\MoveableMount;
+use OC\Files\Node\NonExistingFile;
+use OC\Files\Node\NonExistingFolder;
+use OC\Files\View;
+use OCA\Files_Versions\Storage;
+use OCA\Files_Versions\Versions\INeedSyncVersionBackend;
+use OCA\Files_Versions\Versions\IVersionManager;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\DB\Exception;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
+use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
+use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
+use OCP\Files\Events\Node\BeforeNodeTouchedEvent;
+use OCP\Files\Events\Node\BeforeNodeWrittenEvent;
+use OCP\Files\Events\Node\NodeCopiedEvent;
+use OCP\Files\Events\Node\NodeCreatedEvent;
+use OCP\Files\Events\Node\NodeDeletedEvent;
+use OCP\Files\Events\Node\NodeRenamedEvent;
+use OCP\Files\Events\Node\NodeTouchedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\Files\File;
+use OCP\Files\Folder;
+use OCP\Files\IMimeTypeLoader;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
+
+/** @template-implements IEventListener<BeforeNodeCopiedEvent|BeforeNodeDeletedEvent|BeforeNodeRenamedEvent|BeforeNodeTouchedEvent|BeforeNodeWrittenEvent|NodeCopiedEvent|NodeCreatedEvent|NodeDeletedEvent|NodeRenamedEvent|NodeTouchedEvent|NodeWrittenEvent> */
+class FileEventsListener implements IEventListener {
+ /**
+ * @var array<int, array>
+ */
+ private array $writeHookInfo = [];
+ /**
+ * @var array<int, Node>
+ */
+ private array $nodesTouched = [];
+ /**
+ * @var array<string, Node>
+ */
+ private array $versionsDeleted = [];
+
+ public function __construct(
+ private IRootFolder $rootFolder,
+ private IVersionManager $versionManager,
+ private IMimeTypeLoader $mimeTypeLoader,
+ private IUserSession $userSession,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if ($event instanceof NodeCreatedEvent) {
+ $this->created($event->getNode());
+ }
+
+ if ($event instanceof BeforeNodeTouchedEvent) {
+ $this->pre_touch_hook($event->getNode());
+ }
+
+ if ($event instanceof NodeTouchedEvent) {
+ $this->touch_hook($event->getNode());
+ }
+
+ if ($event instanceof BeforeNodeWrittenEvent) {
+ $this->write_hook($event->getNode());
+ }
+
+ if ($event instanceof NodeWrittenEvent) {
+ $this->post_write_hook($event->getNode());
+ }
+
+ if ($event instanceof BeforeNodeDeletedEvent) {
+ $this->pre_remove_hook($event->getNode());
+ }
+
+ if ($event instanceof NodeDeletedEvent) {
+ $this->remove_hook($event->getNode());
+ }
+
+ if ($event instanceof NodeRenamedEvent) {
+ $this->rename_hook($event->getSource(), $event->getTarget());
+ }
+
+ if ($event instanceof NodeCopiedEvent) {
+ $this->copy_hook($event->getSource(), $event->getTarget());
+ }
+
+ if ($event instanceof BeforeNodeRenamedEvent) {
+ $this->pre_renameOrCopy_hook($event->getSource(), $event->getTarget());
+ }
+
+ if ($event instanceof BeforeNodeCopiedEvent) {
+ $this->pre_renameOrCopy_hook($event->getSource(), $event->getTarget());
+ }
+ }
+
+ public function pre_touch_hook(Node $node): void {
+ // Do not handle folders.
+ if ($node instanceof Folder) {
+ return;
+ }
+
+ // $node is a non-existing on file creation.
+ if ($node instanceof NonExistingFile) {
+ return;
+ }
+
+ $this->nodesTouched[$node->getId()] = $node;
+ }
+
+ public function touch_hook(Node $node): void {
+ // Do not handle folders.
+ if ($node instanceof Folder) {
+ return;
+ }
+
+ if ($node instanceof NonExistingFile) {
+ $this->logger->error(
+ 'Failed to create or update version for {path}, node does not exist',
+ [
+ 'path' => $node->getPath(),
+ ]
+ );
+
+ return;
+ }
+
+ $previousNode = $this->nodesTouched[$node->getId()] ?? null;
+
+ if ($previousNode === null) {
+ return;
+ }
+
+ unset($this->nodesTouched[$node->getId()]);
+
+ try {
+ if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
+ $revision = $this->versionManager->getRevision($previousNode);
+
+ // We update the timestamp of the version entity associated with the previousNode.
+ $this->versionManager->updateVersionEntity($node, $revision, ['timestamp' => $node->getMTime()]);
+ }
+ } catch (DbalException $ex) {
+ // Ignore UniqueConstraintViolationException, as we are probably in the middle of a rollback
+ // Where the previous node would temporary have the mtime of the old version, so the rollback touches it to fix it.
+ if (!($ex->getPrevious() instanceof UniqueConstraintViolationException)) {
+ throw $ex;
+ }
+ } catch (DoesNotExistException $ex) {
+ // Ignore DoesNotExistException, as we are probably in the middle of a rollback
+ // Where the previous node would temporary have a wrong mtime, so the rollback touches it to fix it.
+ }
+ }
+
+ public function created(Node $node): void {
+ // Do not handle folders.
+ if (!($node instanceof File)) {
+ return;
+ }
+
+ if ($node instanceof NonExistingFile) {
+ $this->logger->error(
+ 'Failed to create version for {path}, node does not exist',
+ [
+ 'path' => $node->getPath(),
+ ]
+ );
+
+ return;
+ }
+
+ if ($this->versionManager instanceof INeedSyncVersionBackend) {
+ $this->versionManager->createVersionEntity($node);
+ }
+ }
+
+ /**
+ * listen to write event.
+ */
+ public function write_hook(Node $node): void {
+ // Do not handle folders.
+ if ($node instanceof Folder) {
+ return;
+ }
+
+ // $node is a non-existing on file creation.
+ if ($node instanceof NonExistingFile) {
+ return;
+ }
+
+ $path = $this->getPathForNode($node);
+ $result = Storage::store($path);
+
+ // Store the result of the version creation so it can be used in post_write_hook.
+ $this->writeHookInfo[$node->getId()] = [
+ 'previousNode' => $node,
+ 'versionCreated' => $result !== false
+ ];
+ }
+
+ /**
+ * listen to post_write event.
+ */
+ public function post_write_hook(Node $node): void {
+ // Do not handle folders.
+ if ($node instanceof Folder) {
+ return;
+ }
+
+ if ($node instanceof NonExistingFile) {
+ $this->logger->error(
+ 'Failed to create or update version for {path}, node does not exist',
+ [
+ 'path' => $node->getPath(),
+ ]
+ );
+
+ return;
+ }
+
+ $writeHookInfo = $this->writeHookInfo[$node->getId()] ?? null;
+
+ if ($writeHookInfo === null) {
+ return;
+ }
+
+ if (
+ $writeHookInfo['versionCreated']
+ && $node->getMTime() !== $writeHookInfo['previousNode']->getMTime()
+ ) {
+ // If a new version was created, insert a version in the DB for the current content.
+ // If both versions have the same mtime, it means the latest version file simply got overrode,
+ // so no need to create a new version.
+ $this->created($node);
+ } else {
+ try {
+ // If no new version was stored in the FS, no new version should be added in the DB.
+ // So we simply update the associated version.
+ if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
+ $revision = $this->versionManager->getRevision($writeHookInfo['previousNode']);
+
+ $this->versionManager->updateVersionEntity(
+ $node,
+ $revision,
+ [
+ 'timestamp' => $node->getMTime(),
+ 'size' => $node->getSize(),
+ 'mimetype' => $this->mimeTypeLoader->getId($node->getMimetype()),
+ ],
+ );
+ }
+ } catch (DoesNotExistException $e) {
+ // This happens if the versions app was not enabled while the file was created or updated the last time.
+ // meaning there is no such revision and we need to create this file.
+ if ($writeHookInfo['versionCreated']) {
+ $this->created($node);
+ } else {
+ // Normally this should not happen so we re-throw the exception to not hide any potential issues.
+ throw $e;
+ }
+ } catch (Exception $e) {
+ $this->logger->error('Failed to update existing version for ' . $node->getPath(), [
+ 'exception' => $e,
+ 'versionCreated' => $writeHookInfo['versionCreated'],
+ 'previousNode' => [
+ 'size' => $writeHookInfo['previousNode']->getSize(),
+ 'mtime' => $writeHookInfo['previousNode']->getMTime(),
+ ],
+ 'node' => [
+ 'size' => $node->getSize(),
+ 'mtime' => $node->getMTime(),
+ ]
+ ]);
+ throw $e;
+ }
+ }
+
+ unset($this->writeHookInfo[$node->getId()]);
+ }
+
+ /**
+ * Erase versions of deleted file
+ *
+ * This function is connected to the NodeDeletedEvent event
+ * cleanup the versions directory if the actual file gets deleted
+ */
+ public function remove_hook(Node $node): void {
+ // Need to normalize the path as there is an issue with path concatenation in View.php::getAbsolutePath.
+ $path = Filesystem::normalizePath($node->getPath());
+ if (!array_key_exists($path, $this->versionsDeleted)) {
+ return;
+ }
+ $node = $this->versionsDeleted[$path];
+ $relativePath = $this->getPathForNode($node);
+ unset($this->versionsDeleted[$path]);
+ Storage::delete($relativePath);
+ // If no new version was stored in the FS, no new version should be added in the DB.
+ // So we simply update the associated version.
+ if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
+ $this->versionManager->deleteVersionsEntity($node);
+ }
+ }
+
+ /**
+ * mark file as "deleted" so that we can clean up the versions if the file is gone
+ */
+ public function pre_remove_hook(Node $node): void {
+ $path = $this->getPathForNode($node);
+ Storage::markDeletedFile($path);
+ $this->versionsDeleted[$node->getPath()] = $node;
+ }
+
+ /**
+ * rename/move versions of renamed/moved files
+ *
+ * This function is connected to the NodeRenamedEvent event and adjust the name and location
+ * of the stored versions along the actual file
+ */
+ public function rename_hook(Node $source, Node $target): void {
+ $sourceBackend = $this->versionManager->getBackendForStorage($source->getParent()->getStorage());
+ $targetBackend = $this->versionManager->getBackendForStorage($target->getStorage());
+ // If different backends, do nothing.
+ if ($sourceBackend !== $targetBackend) {
+ return;
+ }
+
+ $oldPath = $this->getPathForNode($source);
+ $newPath = $this->getPathForNode($target);
+ Storage::renameOrCopy($oldPath, $newPath, 'rename');
+ }
+
+ /**
+ * copy versions of copied files
+ *
+ * This function is connected to the NodeCopiedEvent event and copies the
+ * the stored versions to the new location
+ */
+ public function copy_hook(Node $source, Node $target): void {
+ $sourceBackend = $this->versionManager->getBackendForStorage($source->getParent()->getStorage());
+ $targetBackend = $this->versionManager->getBackendForStorage($target->getStorage());
+ // If different backends, do nothing.
+ if ($sourceBackend !== $targetBackend) {
+ return;
+ }
+
+ $oldPath = $this->getPathForNode($source);
+ $newPath = $this->getPathForNode($target);
+ Storage::renameOrCopy($oldPath, $newPath, 'copy');
+ }
+
+ /**
+ * Remember owner and the owner path of the source file.
+ * If the file already exists, then it was a upload of a existing file
+ * over the web interface and we call Storage::store() directly
+ *
+ *
+ */
+ public function pre_renameOrCopy_hook(Node $source, Node $target): void {
+ $sourceBackend = $this->versionManager->getBackendForStorage($source->getStorage());
+ $targetBackend = $this->versionManager->getBackendForStorage($target->getParent()->getStorage());
+ // If different backends, do nothing.
+ if ($sourceBackend !== $targetBackend) {
+ return;
+ }
+
+ // if we rename a movable mount point, then the versions don't have to be renamed
+ $oldPath = $this->getPathForNode($source);
+ $newPath = $this->getPathForNode($target);
+ if ($oldPath === null || $newPath === null) {
+ return;
+ }
+
+ $user = $this->userSession->getUser()?->getUID();
+ if ($user === null) {
+ return;
+ }
+
+ $absOldPath = Filesystem::normalizePath('/' . $user . '/files' . $oldPath);
+ $manager = Filesystem::getMountManager();
+ $mount = $manager->find($absOldPath);
+ $internalPath = $mount->getInternalPath($absOldPath);
+ if ($internalPath === '' and $mount instanceof MoveableMount) {
+ return;
+ }
+
+ $view = new View($user . '/files');
+ if ($view->file_exists($newPath)) {
+ Storage::store($newPath);
+ } else {
+ Storage::setSourcePathAndUser($oldPath);
+ }
+ }
+
+ /**
+ * Retrieve the path relative to the current user root folder.
+ * If no user is connected, try to use the node's owner.
+ */
+ private function getPathForNode(Node $node): ?string {
+ $user = $this->userSession->getUser()?->getUID();
+ if ($user) {
+ $path = $this->rootFolder
+ ->getUserFolder($user)
+ ->getRelativePath($node->getPath());
+
+ if ($path !== null) {
+ return $path;
+ }
+ }
+
+ try {
+ $owner = $node->getOwner()?->getUid();
+ } catch (NotFoundException) {
+ $owner = null;
+ }
+
+ // If no owner, extract it from the path.
+ // e.g. /user/files/foobar.txt
+ if (!$owner) {
+ $parts = explode('/', $node->getPath(), 4);
+ if (count($parts) === 4) {
+ $owner = $parts[1];
+ }
+ }
+
+ if ($owner) {
+ $path = $this->rootFolder
+ ->getUserFolder($owner)
+ ->getRelativePath($node->getPath());
+
+ if ($path !== null) {
+ return $path;
+ }
+ }
+
+ if (!($node instanceof NonExistingFile) && !($node instanceof NonExistingFolder)) {
+ $this->logger->debug('Failed to compute path for node', [
+ 'node' => [
+ 'path' => $node->getPath(),
+ 'owner' => $owner,
+ 'fileid' => $node->getId(),
+ 'size' => $node->getSize(),
+ 'mtime' => $node->getMTime(),
+ ]
+ ]);
+ } else {
+ $this->logger->debug('Failed to compute path for node', [
+ 'node' => [
+ 'path' => $node->getPath(),
+ 'owner' => $owner,
+ ]
+ ]);
+ }
+ return null;
+ }
+}
diff --git a/apps/files_versions/lib/Listener/LegacyRollbackListener.php b/apps/files_versions/lib/Listener/LegacyRollbackListener.php
new file mode 100644
index 00000000000..072c1511caa
--- /dev/null
+++ b/apps/files_versions/lib/Listener/LegacyRollbackListener.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Listener;
+
+use OCA\Files_Versions\Events\VersionRestoredEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+
+/**
+ * This listener is designed to be compatible with third-party code
+ * that can still use a hook. This listener will be removed in
+ * the next version and the rollback hook will stop working.
+ *
+ * @deprecated 32.0.0
+ * @template-implements IEventListener<VersionRestoredEvent>
+ */
+class LegacyRollbackListener implements IEventListener {
+ public function handle(Event $event): void {
+ if (!($event instanceof VersionRestoredEvent)) {
+ return;
+ }
+ $version = $event->getVersion();
+ \OC_Hook::emit('\OCP\Versions', 'rollback', [
+ 'path' => $version->getVersionPath(),
+ 'revision' => $version->getRevisionId(),
+ 'node' => $version->getSourceFile(),
+ ]);
+ }
+}
diff --git a/apps/files_versions/lib/Listener/LoadAdditionalListener.php b/apps/files_versions/lib/Listener/LoadAdditionalListener.php
index aeea8756515..cb955629c0f 100644
--- a/apps/files_versions/lib/Listener/LoadAdditionalListener.php
+++ b/apps/files_versions/lib/Listener/LoadAdditionalListener.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Listener;
@@ -33,6 +14,7 @@ use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Util;
+/** @template-implements IEventListener<LoadAdditionalScriptsEvent> */
class LoadAdditionalListener implements IEventListener {
public function handle(Event $event): void {
if (!($event instanceof LoadAdditionalScriptsEvent)) {
diff --git a/apps/files_versions/lib/Listener/LoadSidebarListener.php b/apps/files_versions/lib/Listener/LoadSidebarListener.php
index 27261fbc3d2..b8d13fa4810 100644
--- a/apps/files_versions/lib/Listener/LoadSidebarListener.php
+++ b/apps/files_versions/lib/Listener/LoadSidebarListener.php
@@ -3,27 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Listener;
@@ -33,6 +14,7 @@ use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Util;
+/** @template-implements IEventListener<LoadSidebar> */
class LoadSidebarListener implements IEventListener {
public function handle(Event $event): void {
if (!($event instanceof LoadSidebar)) {
diff --git a/apps/files_versions/lib/Listener/VersionAuthorListener.php b/apps/files_versions/lib/Listener/VersionAuthorListener.php
new file mode 100644
index 00000000000..9b93b1f888b
--- /dev/null
+++ b/apps/files_versions/lib/Listener/VersionAuthorListener.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Listener;
+
+use OC\Files\Node\Folder;
+use OCA\Files_Versions\Sabre\Plugin;
+use OCA\Files_Versions\Versions\IMetadataVersionBackend;
+use OCA\Files_Versions\Versions\IVersionManager;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\Files\Node;
+use OCP\IUserSession;
+
+/** @template-implements IEventListener<NodeWrittenEvent> */
+class VersionAuthorListener implements IEventListener {
+ public function __construct(
+ private IVersionManager $versionManager,
+ private IUserSession $userSession,
+ ) {
+ }
+
+ /**
+ * @abstract handles events from a nodes version being changed
+ * @param Event $event the event that triggered this listener to activate
+ */
+ public function handle(Event $event): void {
+ if ($event instanceof NodeWrittenEvent) {
+ $this->post_write_hook($event->getNode());
+ }
+ }
+
+ /**
+ * @abstract handles the NodeWrittenEvent, and sets the metadata for the associated node
+ * @param Node $node the node that is currently being written
+ */
+ public function post_write_hook(Node $node): void {
+ $user = $this->userSession->getUser();
+ // Do not handle folders or users that we cannot get metadata from
+ if ($node instanceof Folder || is_null($user)) {
+ return;
+ }
+ // check if our version manager supports setting the metadata
+ if ($this->versionManager instanceof IMetadataVersionBackend) {
+ $revision = $this->versionManager->getRevision($node);
+ $author = $user->getUID();
+ $this->versionManager->setMetadataValue($node, $revision, Plugin::AUTHOR, $author);
+ }
+ }
+}
diff --git a/apps/files_versions/lib/Listener/VersionStorageMoveListener.php b/apps/files_versions/lib/Listener/VersionStorageMoveListener.php
new file mode 100644
index 00000000000..d0a0bcf4a92
--- /dev/null
+++ b/apps/files_versions/lib/Listener/VersionStorageMoveListener.php
@@ -0,0 +1,140 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_Versions\Listener;
+
+use Exception;
+use OC\Files\Node\NonExistingFile;
+use OC\Files\Node\NonExistingFolder;
+use OCA\Files_Versions\Versions\IVersionBackend;
+use OCA\Files_Versions\Versions\IVersionManager;
+use OCA\Files_Versions\Versions\IVersionsImporterBackend;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Events\Node\AbstractNodesEvent;
+use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
+use OCP\Files\Events\Node\NodeCopiedEvent;
+use OCP\Files\Events\Node\NodeRenamedEvent;
+use OCP\Files\File;
+use OCP\Files\Folder;
+use OCP\Files\Node;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+use OCP\IUserSession;
+
+/** @template-implements IEventListener<Event> */
+class VersionStorageMoveListener implements IEventListener {
+ /** @var File[] */
+ private array $movedNodes = [];
+
+ public function __construct(
+ private IVersionManager $versionManager,
+ private IUserSession $userSession,
+ ) {
+ }
+
+ /**
+ * @abstract Moves version across storages if necessary.
+ * @throws Exception No user in session
+ */
+ public function handle(Event $event): void {
+ if (!($event instanceof AbstractNodesEvent)) {
+ return;
+ }
+
+ $source = $event->getSource();
+ $target = $event->getTarget();
+
+ $sourceStorage = $this->getNodeStorage($source);
+ $targetStorage = $this->getNodeStorage($target);
+
+ $sourceBackend = $this->versionManager->getBackendForStorage($sourceStorage);
+ $targetBackend = $this->versionManager->getBackendForStorage($targetStorage);
+
+ // If same backend, nothing to do.
+ if ($sourceBackend === $targetBackend) {
+ return;
+ }
+
+ $user = $this->userSession->getUser() ?? $source->getOwner();
+
+ if ($user === null) {
+ throw new Exception('Cannot move versions across storages without a user.');
+ }
+
+ if ($event instanceof BeforeNodeRenamedEvent) {
+ $this->recursivelyPrepareMove($source);
+ } elseif ($event instanceof NodeRenamedEvent || $event instanceof NodeCopiedEvent) {
+ $this->recursivelyHandleMoveOrCopy($event, $user, $source, $target, $sourceBackend, $targetBackend);
+ }
+ }
+
+ /**
+ * Store all sub files in this->movedNodes so their info can be used after the operation.
+ */
+ private function recursivelyPrepareMove(Node $source): void {
+ if ($source instanceof File) {
+ $this->movedNodes[$source->getId()] = $source;
+ } elseif ($source instanceof Folder) {
+ foreach ($source->getDirectoryListing() as $child) {
+ $this->recursivelyPrepareMove($child);
+ }
+ }
+ }
+
+ /**
+ * Call handleMoveOrCopy on each sub files
+ * @param NodeRenamedEvent|NodeCopiedEvent $event
+ */
+ private function recursivelyHandleMoveOrCopy(Event $event, IUser $user, ?Node $source, Node $target, IVersionBackend $sourceBackend, IVersionBackend $targetBackend): void {
+ if ($target instanceof File) {
+ if ($event instanceof NodeRenamedEvent) {
+ $source = $this->movedNodes[$target->getId()];
+ }
+
+ /** @var File $source */
+ $this->handleMoveOrCopy($event, $user, $source, $target, $sourceBackend, $targetBackend);
+ } elseif ($target instanceof Folder) {
+ /** @var Folder $source */
+ foreach ($target->getDirectoryListing() as $targetChild) {
+ if ($event instanceof NodeCopiedEvent) {
+ $sourceChild = $source->get($targetChild->getName());
+ } else {
+ $sourceChild = null;
+ }
+
+ $this->recursivelyHandleMoveOrCopy($event, $user, $sourceChild, $targetChild, $sourceBackend, $targetBackend);
+ }
+ }
+ }
+
+ /**
+ * Called only during NodeRenamedEvent or NodeCopiedEvent
+ * Will send the source node versions to the new backend, and then delete them from the old backend.
+ * @param NodeRenamedEvent|NodeCopiedEvent $event
+ */
+ private function handleMoveOrCopy(Event $event, IUser $user, File $source, File $target, IVersionBackend $sourceBackend, IVersionBackend $targetBackend): void {
+ if ($targetBackend instanceof IVersionsImporterBackend) {
+ $versions = $sourceBackend->getVersionsForFile($user, $source);
+ $targetBackend->importVersionsForFile($user, $source, $target, $versions);
+ }
+
+ if ($event instanceof NodeRenamedEvent && $sourceBackend instanceof IVersionsImporterBackend) {
+ $sourceBackend->clearVersionsForFile($user, $source, $target);
+ }
+ }
+
+ private function getNodeStorage(Node $node): IStorage {
+ if ($node instanceof NonExistingFile || $node instanceof NonExistingFolder) {
+ return $node->getParent()->getStorage();
+ } else {
+ return $node->getStorage();
+ }
+ }
+}
diff --git a/apps/files_versions/lib/Migration/Version1020Date20221114144058.php b/apps/files_versions/lib/Migration/Version1020Date20221114144058.php
new file mode 100644
index 00000000000..77c8c2201f3
--- /dev/null
+++ b/apps/files_versions/lib/Migration/Version1020Date20221114144058.php
@@ -0,0 +1,67 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_Versions\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\DB\Types;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * Auto-generated migration step: Please modify to your needs!
+ */
+class Version1020Date20221114144058 extends SimpleMigrationStep {
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if ($schema->hasTable('files_versions')) {
+ return null;
+ }
+
+ $table = $schema->createTable('files_versions');
+ $table->addColumn('id', Types::BIGINT, [
+ 'autoincrement' => true,
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('file_id', Types::BIGINT, [
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('timestamp', Types::BIGINT, [
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('size', Types::BIGINT, [
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('mimetype', Types::BIGINT, [
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('metadata', Types::JSON, [
+ 'notnull' => true,
+ ]);
+
+ $table->setPrimaryKey(['id']);
+ $table->addUniqueIndex(['file_id', 'timestamp'], 'files_versions_uniq_index');
+
+ return $schema;
+ }
+}
diff --git a/apps/files_versions/lib/Sabre/Plugin.php b/apps/files_versions/lib/Sabre/Plugin.php
index 5a127b4251d..984c4a36e5b 100644
--- a/apps/files_versions/lib/Sabre/Plugin.php
+++ b/apps/files_versions/lib/Sabre/Plugin.php
@@ -3,45 +3,39 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
use OC\AppFramework\Http\Request;
+use OCA\DAV\Connector\Sabre\FilesPlugin;
+use OCP\IPreview;
use OCP\IRequest;
use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\INode;
+use Sabre\DAV\PropFind;
+use Sabre\DAV\PropPatch;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
class Plugin extends ServerPlugin {
+ private Server $server;
- /** @var Server */
- private $server;
- /** @var IRequest */
- private $request;
+ public const LABEL = 'label';
- public function __construct(IRequest $request) {
+ public const AUTHOR = 'author';
+
+ public const VERSION_LABEL = '{http://nextcloud.org/ns}version-label';
+
+ public const VERSION_AUTHOR = '{http://nextcloud.org/ns}version-author'; // dav property for author
+
+ public function __construct(
+ private IRequest $request,
+ private IPreview $previewManager,
+ ) {
$this->request = $request;
}
@@ -49,6 +43,8 @@ class Plugin extends ServerPlugin {
$this->server = $server;
$server->on('afterMethod:GET', [$this, 'afterGet']);
+ $server->on('propFind', [$this, 'propFind']);
+ $server->on('propPatch', [$this, 'propPatch']);
}
public function afterGet(RequestInterface $request, ResponseInterface $response) {
@@ -81,4 +77,23 @@ class Plugin extends ServerPlugin {
. '; filename="' . rawurlencode($filename) . '"');
}
}
+
+ public function propFind(PropFind $propFind, INode $node): void {
+ if ($node instanceof VersionFile) {
+ $propFind->handle(self::VERSION_LABEL, fn () => $node->getMetadataValue(self::LABEL));
+ $propFind->handle(self::VERSION_AUTHOR, fn () => $node->getMetadataValue(self::AUTHOR));
+ $propFind->handle(
+ FilesPlugin::HAS_PREVIEW_PROPERTYNAME,
+ fn (): string => $this->previewManager->isMimeSupported($node->getContentType()) ? 'true' : 'false',
+ );
+ }
+ }
+
+ public function propPatch($path, PropPatch $propPatch): void {
+ $node = $this->server->tree->getNodeForPath($path);
+
+ if ($node instanceof VersionFile) {
+ $propPatch->handle(self::VERSION_LABEL, fn (string $label) => $node->setMetadataValue(self::LABEL, $label));
+ }
+ }
}
diff --git a/apps/files_versions/lib/Sabre/RestoreFolder.php b/apps/files_versions/lib/Sabre/RestoreFolder.php
index 31d87cc7112..7904b098a4f 100644
--- a/apps/files_versions/lib/Sabre/RestoreFolder.php
+++ b/apps/files_versions/lib/Sabre/RestoreFolder.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
diff --git a/apps/files_versions/lib/Sabre/RootCollection.php b/apps/files_versions/lib/Sabre/RootCollection.php
index 835df5930bc..1e7129f23da 100644
--- a/apps/files_versions/lib/Sabre/RootCollection.php
+++ b/apps/files_versions/lib/Sabre/RootCollection.php
@@ -1,25 +1,8 @@
<?php
+
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
@@ -34,33 +17,16 @@ use Sabre\DAVACL\PrincipalBackend;
class RootCollection extends AbstractPrincipalCollection {
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var IVersionManager */
- private $versionManager;
-
- /** @var IUserSession */
- private $userSession;
-
public function __construct(
PrincipalBackend\BackendInterface $principalBackend,
- IRootFolder $rootFolder,
+ private IRootFolder $rootFolder,
IConfig $config,
- IUserManager $userManager,
- IVersionManager $versionManager,
- IUserSession $userSession
+ private IUserManager $userManager,
+ private IVersionManager $versionManager,
+ private IUserSession $userSession,
) {
parent::__construct($principalBackend, 'principals/users');
- $this->rootFolder = $rootFolder;
- $this->userManager = $userManager;
- $this->versionManager = $versionManager;
- $this->userSession = $userSession;
-
$this->disableListing = !$config->getSystemValue('debug', false);
}
diff --git a/apps/files_versions/lib/Sabre/VersionCollection.php b/apps/files_versions/lib/Sabre/VersionCollection.php
index 946ac9baad7..375d5cf99f2 100644
--- a/apps/files_versions/lib/Sabre/VersionCollection.php
+++ b/apps/files_versions/lib/Sabre/VersionCollection.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
@@ -36,19 +18,11 @@ use Sabre\DAV\ICollection;
class VersionCollection implements ICollection {
- /** @var File */
- private $file;
-
- /** @var IUser */
- private $user;
-
- /** @var IVersionManager */
- private $versionManager;
-
- public function __construct(File $file, IUser $user, IVersionManager $versionManager) {
- $this->file = $file;
- $this->user = $user;
- $this->versionManager = $versionManager;
+ public function __construct(
+ private File $file,
+ private IUser $user,
+ private IVersionManager $versionManager,
+ ) {
}
public function createFile($name, $data = null) {
diff --git a/apps/files_versions/lib/Sabre/VersionFile.php b/apps/files_versions/lib/Sabre/VersionFile.php
index b7c7e6db1a6..faa03473648 100644
--- a/apps/files_versions/lib/Sabre/VersionFile.php
+++ b/apps/files_versions/lib/Sabre/VersionFile.php
@@ -3,29 +3,16 @@
declare(strict_types=1);
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
+use OCA\Files_Versions\Versions\IDeletableVersionBackend;
+use OCA\Files_Versions\Versions\IMetadataVersion;
+use OCA\Files_Versions\Versions\IMetadataVersionBackend;
+use OCA\Files_Versions\Versions\INameableVersion;
+use OCA\Files_Versions\Versions\INameableVersionBackend;
use OCA\Files_Versions\Versions\IVersion;
use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\NotFoundException;
@@ -34,15 +21,10 @@ use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\IFile;
class VersionFile implements IFile {
- /** @var IVersion */
- private $version;
-
- /** @var IVersionManager */
- private $versionManager;
-
- public function __construct(IVersion $version, IVersionManager $versionManager) {
- $this->version = $version;
- $this->versionManager = $versionManager;
+ public function __construct(
+ private IVersion $version,
+ private IVersionManager $versionManager,
+ ) {
}
public function put($data) {
@@ -65,12 +47,20 @@ class VersionFile implements IFile {
return (string)$this->version->getRevisionId();
}
- public function getSize(): int {
+ /**
+ * @psalm-suppress ImplementedReturnTypeMismatch \Sabre\DAV\IFile::getSize signature does not support 32bit
+ * @return int|float
+ */
+ public function getSize(): int|float {
return $this->version->getSize();
}
public function delete() {
- throw new Forbidden();
+ if ($this->versionManager instanceof IDeletableVersionBackend) {
+ $this->versionManager->deleteVersion($this->version);
+ } else {
+ throw new Forbidden();
+ }
}
public function getName(): string {
@@ -81,6 +71,29 @@ class VersionFile implements IFile {
throw new Forbidden();
}
+ public function setMetadataValue(string $key, string $value): bool {
+ $backend = $this->version->getBackend();
+
+ if ($backend instanceof IMetadataVersionBackend) {
+ $backend->setMetadataValue($this->version->getSourceFile(), $this->version->getTimestamp(), $key, $value);
+ return true;
+ } elseif ($key === 'label' && $backend instanceof INameableVersionBackend) {
+ $backend->setVersionLabel($this->version, $value);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function getMetadataValue(string $key): ?string {
+ if ($this->version instanceof IMetadataVersion) {
+ return $this->version->getMetadataValue($key);
+ } elseif ($key === 'label' && $this->version instanceof INameableVersion) {
+ return $this->version->getLabel();
+ }
+ return null;
+ }
+
public function getLastModified(): int {
return $this->version->getTimestamp();
}
diff --git a/apps/files_versions/lib/Sabre/VersionHome.php b/apps/files_versions/lib/Sabre/VersionHome.php
index 13505d9a96c..07ac491f2a1 100644
--- a/apps/files_versions/lib/Sabre/VersionHome.php
+++ b/apps/files_versions/lib/Sabre/VersionHome.php
@@ -1,25 +1,8 @@
<?php
+
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
@@ -32,23 +15,12 @@ use Sabre\DAV\ICollection;
class VersionHome implements ICollection {
- /** @var array */
- private $principalInfo;
-
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var IVersionManager */
- private $versionManager;
-
- public function __construct(array $principalInfo, IRootFolder $rootFolder, IUserManager $userManager, IVersionManager $versionManager) {
- $this->principalInfo = $principalInfo;
- $this->rootFolder = $rootFolder;
- $this->userManager = $userManager;
- $this->versionManager = $versionManager;
+ public function __construct(
+ private array $principalInfo,
+ private IRootFolder $rootFolder,
+ private IUserManager $userManager,
+ private IVersionManager $versionManager,
+ ) {
}
private function getUser() {
diff --git a/apps/files_versions/lib/Sabre/VersionRoot.php b/apps/files_versions/lib/Sabre/VersionRoot.php
index 69ac12ed8e9..7f7014fbee3 100644
--- a/apps/files_versions/lib/Sabre/VersionRoot.php
+++ b/apps/files_versions/lib/Sabre/VersionRoot.php
@@ -3,26 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Sabre;
@@ -36,19 +18,11 @@ use Sabre\DAV\ICollection;
class VersionRoot implements ICollection {
- /** @var IUser */
- private $user;
-
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IVersionManager */
- private $versionManager;
-
- public function __construct(IUser $user, IRootFolder $rootFolder, IVersionManager $versionManager) {
- $this->user = $user;
- $this->rootFolder = $rootFolder;
- $this->versionManager = $versionManager;
+ public function __construct(
+ private IUser $user,
+ private IRootFolder $rootFolder,
+ private IVersionManager $versionManager,
+ ) {
}
public function delete() {
@@ -75,14 +49,12 @@ class VersionRoot implements ICollection {
$userFolder = $this->rootFolder->getUserFolder($this->user->getUID());
$fileId = (int)$name;
- $nodes = $userFolder->getById($fileId);
+ $node = $userFolder->getFirstNodeById($fileId);
- if ($nodes === []) {
+ if (!$node) {
throw new NotFound();
}
- $node = array_pop($nodes);
-
if (!$node instanceof File) {
throw new NotFound();
}
diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php
index 3f91e32ef95..6d53a19a518 100644
--- a/apps/files_versions/lib/Storage.php
+++ b/apps/files_versions/lib/Storage.php
@@ -1,70 +1,49 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Felix Nieuwenhuizen <felix@tdlrali.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Liam JACK <liamjack@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions;
+use OC\Files\Filesystem;
+use OC\Files\ObjectStore\ObjectStoreStorage;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
-use OC_User;
-use OC\Files\Filesystem;
use OC\Files\View;
+use OC\User\NoUserException;
+use OC_User;
+use OCA\Files_Sharing\SharedMount;
use OCA\Files_Versions\AppInfo\Application;
use OCA\Files_Versions\Command\Expire;
+use OCA\Files_Versions\Db\VersionsMapper;
use OCA\Files_Versions\Events\CreateVersionEvent;
use OCA\Files_Versions\Versions\IVersionManager;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\Command\IBus;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
+use OCP\Files\IMimeTypeDetector;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
-use OCP\Command\IBus;
-use OCP\EventDispatcher\IEventDispatcher;
-use OCP\Files\IMimeTypeDetector;
use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
+use OCP\Files\Storage\IWriteStreamStorage;
+use OCP\Files\StorageInvalidException;
use OCP\Files\StorageNotAvailableException;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Lock\ILockingProvider;
+use OCP\Server;
+use OCP\Util;
use Psr\Log\LoggerInterface;
class Storage {
@@ -96,7 +75,7 @@ class Storage {
6 => ['intervalEndsAfter' => -1, 'step' => 604800],
];
- /** @var \OCA\Files_Versions\AppInfo\Application */
+ /** @var Application */
private static $application;
/**
@@ -105,11 +84,11 @@ class Storage {
*
* @param string $filename
* @return array
- * @throws \OC\User\NoUserException
+ * @throws NoUserException
*/
public static function getUidAndFilename($filename) {
$uid = Filesystem::getOwner($filename);
- $userManager = \OC::$server->get(IUserManager::class);
+ $userManager = Server::get(IUserManager::class);
// if the user with the UID doesn't exists, e.g. because the UID points
// to a remote user with a federated cloud ID we use the current logged-in
// user. We need a valid local user to create the versions
@@ -119,7 +98,7 @@ class Storage {
Filesystem::initMountPoints($uid);
if ($uid !== OC_User::getUser()) {
$info = Filesystem::getFileInfo($filename);
- $ownerView = new View('/'.$uid.'/files');
+ $ownerView = new View('/' . $uid . '/files');
try {
$filename = $ownerView->getPath($info['fileid']);
// make sure that the file name doesn't end with a trailing slash
@@ -175,7 +154,6 @@ class Storage {
* store a new version of a file.
*/
public static function store($filename) {
-
// if the file gets streamed we need to remove the .part extension
// to get the right target
$ext = pathinfo($filename, PATHINFO_EXTENSION);
@@ -188,33 +166,54 @@ class Storage {
return false;
}
- [$uid, $filename] = self::getUidAndFilename($filename);
+ // since hook paths are always relative to the "default filesystem view"
+ // we always use the owner from there to get the full node
+ $uid = Filesystem::getView()->getOwner('');
- $files_view = new View('/'.$uid .'/files');
+ /** @var IRootFolder $rootFolder */
+ $rootFolder = Server::get(IRootFolder::class);
+ $userFolder = $rootFolder->getUserFolder($uid);
- $eventDispatcher = \OC::$server->get(IEventDispatcher::class);
- $fileInfo = $files_view->getFileInfo($filename);
- $id = $fileInfo->getId();
- $nodes = \OC::$server->get(IRootFolder::class)->getUserFolder($uid)->getById($id);
- foreach ($nodes as $node) {
- $event = new CreateVersionEvent($node);
- $eventDispatcher->dispatch('OCA\Files_Versions::createVersion', $event);
- if ($event->shouldCreateVersion() === false) {
- return false;
+ $eventDispatcher = Server::get(IEventDispatcher::class);
+ try {
+ $file = $userFolder->get($filename);
+ } catch (NotFoundException $e) {
+ return false;
+ }
+
+ $mount = $file->getMountPoint();
+ if ($mount instanceof SharedMount) {
+ $ownerFolder = $rootFolder->getUserFolder($mount->getShare()->getShareOwner());
+ $ownerNode = $ownerFolder->getFirstNodeById($file->getId());
+ if ($ownerNode) {
+ $file = $ownerNode;
+ $uid = $mount->getShare()->getShareOwner();
}
}
+ /** @var IUserManager $userManager */
+ $userManager = Server::get(IUserManager::class);
+ $user = $userManager->get($uid);
+
+ if (!$user) {
+ return false;
+ }
+
// no use making versions for empty files
- if ($fileInfo->getSize() === 0) {
+ if ($file->getSize() === 0) {
+ return false;
+ }
+
+ $event = new CreateVersionEvent($file);
+ $eventDispatcher->dispatch('OCA\Files_Versions::createVersion', $event);
+ if ($event->shouldCreateVersion() === false) {
return false;
}
/** @var IVersionManager $versionManager */
- $versionManager = \OC::$server->get(IVersionManager::class);
- $userManager = \OC::$server->get(IUserManager::class);
- $user = $userManager->get($uid);
+ $versionManager = Server::get(IVersionManager::class);
- $versionManager->createVersion($user, $fileInfo);
+ $versionManager->createVersion($user, $file);
}
@@ -270,12 +269,23 @@ class Storage {
}
/**
+ * Delete a version of a file
+ */
+ public static function deleteRevision(string $path, int $revision): void {
+ [$uid, $filename] = self::getUidAndFilename($path);
+ $view = new View('/' . $uid . '/files_versions');
+ \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path . $revision, 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
+ self::deleteVersion($view, $filename . '.v' . $revision);
+ \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path . $revision, 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
+ }
+
+ /**
* Rename or copy versions of a file of the given paths
*
* @param string $sourcePath source path of the file to move, relative to
- * the currently logged in user's "files" folder
+ * the currently logged in user's "files" folder
* @param string $targetPath target path of the file to move, relative to
- * the currently logged in user's "files" folder
+ * the currently logged in user's "files" folder
* @param string $operation can be 'copy' or 'rename'
*/
public static function renameOrCopy($sourcePath, $targetPath, $operation) {
@@ -300,7 +310,7 @@ class Storage {
// does the directory exists for versions too ?
if ($rootView->is_dir('/' . $sourceOwner . '/files_versions/' . $sourcePath)) {
// create missing dirs if necessary
- self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
+ self::createMissingDirectories($targetPath, new View('/' . $targetOwner));
// move the directory containing the versions
$rootView->$operation(
@@ -310,13 +320,13 @@ class Storage {
}
} elseif ($versions = Storage::getVersions($sourceOwner, '/' . $sourcePath)) {
// create missing dirs if necessary
- self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
+ self::createMissingDirectories($targetPath, new View('/' . $targetOwner));
foreach ($versions as $v) {
// move each version one by one to the target directory
$rootView->$operation(
- '/' . $sourceOwner . '/files_versions/' . $sourcePath.'.v' . $v['version'],
- '/' . $targetOwner . '/files_versions/' . $targetPath.'.v'.$v['version']
+ '/' . $sourceOwner . '/files_versions/' . $sourcePath . '.v' . $v['version'],
+ '/' . $targetOwner . '/files_versions/' . $targetPath . '.v' . $v['version']
);
}
}
@@ -335,16 +345,15 @@ class Storage {
* @return bool
*/
public static function rollback(string $file, int $revision, IUser $user) {
-
// add expected leading slash
$filename = '/' . ltrim($file, '/');
// Fetch the userfolder to trigger view hooks
- $root = \OC::$server->get(IRootFolder::class);
+ $root = Server::get(IRootFolder::class);
$userFolder = $root->getUserFolder($user->getUID());
- $users_view = new View('/'.$user->getUID());
- $files_view = new View('/'. $user->getUID().'/files');
+ $users_view = new View('/' . $user->getUID());
+ $files_view = new View('/' . $user->getUID() . '/files');
$versionCreated = false;
@@ -356,9 +365,9 @@ class Storage {
}
//first create a new version
- $version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename);
+ $version = 'files_versions' . $filename . '.v' . $users_view->filemtime('files' . $filename);
if (!$users_view->file_exists($version)) {
- $users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename));
+ $users_view->copy('files' . $filename, 'files_versions' . $filename . '.v' . $users_view->filemtime('files' . $filename));
$versionCreated = true;
}
@@ -373,7 +382,8 @@ class Storage {
$fileInfo->getId(), [
'encrypted' => $oldVersion,
'encryptedVersion' => $oldVersion,
- 'size' => $oldFileInfo->getSize()
+ 'size' => $oldFileInfo->getData()['size'],
+ 'unencrypted_size' => $oldFileInfo->getData()['unencrypted_size'],
]
);
@@ -382,14 +392,6 @@ class Storage {
$files_view->touch($file, $revision);
Storage::scheduleExpire($user->getUID(), $file);
- $node = $userFolder->get($file);
-
- // TODO: move away from those legacy hooks!
- \OC_Hook::emit('\OCP\Versions', 'rollback', [
- 'path' => $filename,
- 'revision' => $revision,
- 'node' => $node,
- ]);
return true;
} elseif ($versionCreated) {
self::deleteVersion($users_view, $version);
@@ -416,24 +418,45 @@ class Storage {
$view->lockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
$view->lockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
- // TODO add a proper way of overwriting a file while maintaining file ids
- if ($storage1->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage') || $storage2->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage')) {
- $source = $storage1->fopen($internalPath1, 'r');
- $target = $storage2->fopen($internalPath2, 'w');
- [, $result] = \OC_Helper::streamCopy($source, $target);
- fclose($source);
- fclose($target);
+ try {
+ // TODO add a proper way of overwriting a file while maintaining file ids
+ if ($storage1->instanceOfStorage(ObjectStoreStorage::class)
+ || $storage2->instanceOfStorage(ObjectStoreStorage::class)
+ ) {
+ $source = $storage1->fopen($internalPath1, 'r');
+ $result = $source !== false;
+ if ($result) {
+ if ($storage2->instanceOfStorage(IWriteStreamStorage::class)) {
+ /** @var IWriteStreamStorage $storage2 */
+ $storage2->writeStream($internalPath2, $source);
+ } else {
+ $target = $storage2->fopen($internalPath2, 'w');
+ $result = $target !== false;
+ if ($result) {
+ [, $result] = Files::streamCopy($source, $target, true);
+ }
+ // explicit check as S3 library closes streams already
+ if (is_resource($target)) {
+ fclose($target);
+ }
+ }
+ }
+ // explicit check as S3 library closes streams already
+ if (is_resource($source)) {
+ fclose($source);
+ }
- if ($result !== false) {
- $storage1->unlink($internalPath1);
+ if ($result !== false) {
+ $storage1->unlink($internalPath1);
+ }
+ } else {
+ $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
}
- } else {
- $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
+ } finally {
+ $view->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
+ $view->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
}
- $view->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
- $view->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
-
return ($result !== false);
}
@@ -473,23 +496,33 @@ class Storage {
$filename = $pathparts['filename'];
if ($filename === $versionedFile) {
$pathparts = pathinfo($entryName);
- $timestamp = substr($pathparts['extension'], 1);
+ $timestamp = substr($pathparts['extension'] ?? '', 1);
+ if (!is_numeric($timestamp)) {
+ Server::get(LoggerInterface::class)->error(
+ 'Version file {path} has incorrect name format',
+ [
+ 'path' => $entryName,
+ 'app' => 'files_versions',
+ ]
+ );
+ continue;
+ }
$filename = $pathparts['filename'];
$key = $timestamp . '#' . $filename;
$versions[$key]['version'] = $timestamp;
- $versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($timestamp);
+ $versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp((int)$timestamp);
if (empty($userFullPath)) {
$versions[$key]['preview'] = '';
} else {
/** @var IURLGenerator $urlGenerator */
- $urlGenerator = \OC::$server->get(IURLGenerator::class);
+ $urlGenerator = Server::get(IURLGenerator::class);
$versions[$key]['preview'] = $urlGenerator->linkToRoute('files_version.Preview.getPreview',
['file' => $userFullPath, 'version' => $timestamp]);
}
$versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'] . '/' . $filename);
$versions[$key]['name'] = $versionedFile;
$versions[$key]['size'] = $view->filesize($dir . '/' . $entryName);
- $versions[$key]['mimetype'] = \OC::$server->get(IMimeTypeDetector::class)->detectPath($versionedFile);
+ $versions[$key]['mimetype'] = Server::get(IMimeTypeDetector::class)->detectPath($versionedFile);
}
}
}
@@ -509,7 +542,7 @@ class Storage {
*/
public static function expireOlderThanMaxForUser($uid) {
/** @var IRootFolder $root */
- $root = \OC::$server->get(IRootFolder::class);
+ $root = Server::get(IRootFolder::class);
try {
/** @var Folder $versionsRoot */
$versionsRoot = $root->get('/' . $uid . '/files_versions');
@@ -532,21 +565,66 @@ class Storage {
[]
));
+ /** @var VersionsMapper $versionsMapper */
+ $versionsMapper = Server::get(VersionsMapper::class);
+ $userFolder = $root->getUserFolder($uid);
+ $versionEntities = [];
+
/** @var Node[] $versions */
- $versions = array_filter($allVersions, function (Node $info) use ($threshold) {
+ $versions = array_filter($allVersions, function (Node $info) use ($threshold, $userFolder, $versionsMapper, $versionsRoot, &$versionEntities) {
+ // Check that the file match '*.v*'
$versionsBegin = strrpos($info->getName(), '.v');
if ($versionsBegin === false) {
return false;
}
+
$version = (int)substr($info->getName(), $versionsBegin + 2);
+
+ // Check that the version does not have a label.
+ $path = $versionsRoot->getRelativePath($info->getPath());
+ if ($path === null) {
+ throw new DoesNotExistException('Could not find relative path of (' . $info->getPath() . ')');
+ }
+
+ try {
+ $node = $userFolder->get(substr($path, 0, -strlen('.v' . $version)));
+ $versionEntity = $versionsMapper->findVersionForFileId($node->getId(), $version);
+ $versionEntities[$info->getId()] = $versionEntity;
+
+ if ($versionEntity->getMetadataValue('label') !== null && $versionEntity->getMetadataValue('label') !== '') {
+ return false;
+ }
+ } catch (NotFoundException $e) {
+ // Original node not found, delete the version
+ return true;
+ } catch (StorageNotAvailableException|StorageInvalidException $e) {
+ // Storage can't be used, but it might only be temporary so we can't always delete the version
+ // since we can't determine if the version is named we take the safe route and don't expire
+ return false;
+ } catch (DoesNotExistException $ex) {
+ // Version on FS can have no equivalent in the DB if they were created before the version naming feature.
+ // So we ignore DoesNotExistException.
+ }
+
+ // Check that the version's timestamp is lower than $threshold
return $version < $threshold;
});
foreach ($versions as $version) {
$internalPath = $version->getInternalPath();
\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $internalPath, 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
- $version->delete();
- \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $internalPath, 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
+
+ $versionEntity = isset($versionEntities[$version->getId()]) ? $versionEntities[$version->getId()] : null;
+ if (!is_null($versionEntity)) {
+ $versionsMapper->delete($versionEntity);
+ }
+
+ try {
+ $version->delete();
+ \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $internalPath, 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
+ } catch (NotPermittedException $e) {
+ Server::get(LoggerInterface::class)->error("Missing permissions to delete version: {$internalPath}", ['app' => 'files_versions', 'exception' => $e]);
+ }
}
}
@@ -556,23 +634,23 @@ class Storage {
* @param int $timestamp
* @return string for example "5 days ago"
*/
- private static function getHumanReadableTimestamp($timestamp) {
+ private static function getHumanReadableTimestamp(int $timestamp): string {
$diff = time() - $timestamp;
if ($diff < 60) { // first minute
- return $diff . " seconds ago";
+ return $diff . ' seconds ago';
} elseif ($diff < 3600) { //first hour
- return round($diff / 60) . " minutes ago";
+ return round($diff / 60) . ' minutes ago';
} elseif ($diff < 86400) { // first day
- return round($diff / 3600) . " hours ago";
+ return round($diff / 3600) . ' hours ago';
} elseif ($diff < 604800) { //first week
- return round($diff / 86400) . " days ago";
+ return round($diff / 86400) . ' days ago';
} elseif ($diff < 2419200) { //first month
- return round($diff / 604800) . " weeks ago";
+ return round($diff / 604800) . ' weeks ago';
} elseif ($diff < 29030400) { // first year
- return round($diff / 2419200) . " months ago";
+ return round($diff / 2419200) . ' months ago';
} else {
- return round($diff / 29030400) . " years ago";
+ return round($diff / 29030400) . ' years ago';
}
}
@@ -615,7 +693,7 @@ class Storage {
];
foreach ($versions as $key => $value) {
- $size = $view->filesize(self::VERSIONS_ROOT.'/'.$value['path'].'.v'.$value['timestamp']);
+ $size = $view->filesize(self::VERSIONS_ROOT . '/' . $value['path'] . '.v' . $value['timestamp']);
$filename = $value['path'];
$result['all'][$key]['version'] = $value['timestamp'];
@@ -641,14 +719,28 @@ class Storage {
$expiration = self::getExpiration();
if ($expiration->shouldAutoExpire()) {
- [$toDelete, $size] = self::getAutoExpireList($time, $versions);
+ // Exclude versions that are newer than the minimum age from the auto expiration logic.
+ $minAge = $expiration->getMinAgeAsTimestamp();
+ if ($minAge !== false) {
+ $versionsToAutoExpire = array_filter($versions, fn ($version) => $version['version'] < $minAge);
+ } else {
+ $versionsToAutoExpire = $versions;
+ }
+
+ [$toDelete, $size] = self::getAutoExpireList($time, $versionsToAutoExpire);
} else {
$size = 0;
$toDelete = []; // versions we want to delete
}
foreach ($versions as $key => $version) {
- if ($expiration->isExpired($version['version'], $quotaExceeded) && !isset($toDelete[$key])) {
+ if (!is_numeric($version['version'])) {
+ Server::get(LoggerInterface::class)->error(
+ 'Found a non-numeric timestamp version: ' . json_encode($version),
+ ['app' => 'files_versions']);
+ continue;
+ }
+ if ($expiration->isExpired((int)($version['version']), $quotaExceeded) && !isset($toDelete[$key])) {
$size += $version['size'];
$toDelete[$key] = $version['path'] . '.v' . $version['version'];
}
@@ -694,7 +786,7 @@ class Storage {
//distance between two version too small, mark to delete
$toDelete[$key] = $version['path'] . '.v' . $version['version'];
$size += $version['size'];
- \OC::$server->get(LoggerInterface::class)->info('Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, ['app' => 'files_versions']);
+ Server::get(LoggerInterface::class)->info('Mark to expire ' . $version['path'] . ' next version should be ' . $nextVersion . ' or smaller. (prevTimestamp: ' . $prevTimestamp . '; step: ' . $step, ['app' => 'files_versions']);
} else {
$nextVersion = $version['version'] - $step;
$prevTimestamp = $version['version'];
@@ -729,7 +821,7 @@ class Storage {
if ($expiration->isEnabled()) {
$command = new Expire($uid, $fileName);
/** @var IBus $bus */
- $bus = \OC::$server->get(IBus::class);
+ $bus = Server::get(IBus::class);
$bus->push($command);
}
}
@@ -748,14 +840,14 @@ class Storage {
$expiration = self::getExpiration();
/** @var LoggerInterface $logger */
- $logger = \OC::$server->get(LoggerInterface::class);
+ $logger = Server::get(LoggerInterface::class);
if ($expiration->isEnabled()) {
// get available disk space for user
- $user = \OC::$server->get(IUserManager::class)->get($uid);
+ $user = Server::get(IUserManager::class)->get($uid);
if (is_null($user)) {
$logger->error('Backends provided no user object for ' . $uid, ['app' => 'files_versions']);
- throw new \OC\User\NoUserException('Backends provided no user object for ' . $uid);
+ throw new NoUserException('Backends provided no user object for ' . $uid);
}
\OC_Util::setupFS($uid);
@@ -774,7 +866,7 @@ class Storage {
// file maybe renamed or deleted
return false;
}
- $versionsFileview = new View('/'.$uid.'/files_versions');
+ $versionsFileview = new View('/' . $uid . '/files_versions');
$softQuota = true;
$quota = $user->getQuota();
@@ -782,7 +874,7 @@ class Storage {
$quota = Filesystem::free_space('/');
$softQuota = false;
} else {
- $quota = \OCP\Util::computerFileSize($quota);
+ $quota = Util::computerFileSize($quota);
}
// make sure that we have the current size of the version history
@@ -792,7 +884,7 @@ class Storage {
// subtract size of files and current versions size from quota
if ($quota >= 0) {
if ($softQuota) {
- $root = \OC::$server->get(IRootFolder::class);
+ $root = Server::get(IRootFolder::class);
$userFolder = $root->getUserFolder($uid);
if (is_null($userFolder)) {
$availableSpace = 0;
@@ -834,6 +926,21 @@ class Storage {
}
foreach ($toDelete as $key => $path) {
+ // Make sure to cleanup version table relations as expire does not pass deleteVersion
+ try {
+ /** @var VersionsMapper $versionsMapper */
+ $versionsMapper = Server::get(VersionsMapper::class);
+ $file = Server::get(IRootFolder::class)->getUserFolder($uid)->get($filename);
+ $pathparts = pathinfo($path);
+ $timestamp = (int)substr($pathparts['extension'] ?? '', 1);
+ $versionEntity = $versionsMapper->findVersionForFileId($file->getId(), $timestamp);
+ if ($versionEntity->getMetadataValue('label') !== null && $versionEntity->getMetadataValue('label') !== '') {
+ continue;
+ }
+ $versionsMapper->delete($versionEntity);
+ } catch (DoesNotExistException $e) {
+ }
+
\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
self::deleteVersion($versionsFileview, $path);
\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
@@ -851,10 +958,10 @@ class Storage {
reset($allVersions);
while ($availableSpace < 0 && $i < $numOfVersions) {
$version = current($allVersions);
- \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
+ \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'] . '.v' . $version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']);
- \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
- $logger->info('running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'], ['app' => 'files_versions']);
+ \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'] . '.v' . $version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
+ $logger->info('running out of space! Delete oldest version: ' . $version['path'] . '.v' . $version['version'], ['app' => 'files_versions']);
$versionsSize -= $version['size'];
$availableSpace += $version['size'];
next($allVersions);
@@ -872,13 +979,13 @@ class Storage {
* that match the given path to a file.
*
* @param string $filename $path to a file, relative to the user's
- * "files" folder
+ * "files" folder
* @param View $view view on data/user/
*/
public static function createMissingDirectories($filename, $view) {
$dirname = Filesystem::normalizePath(dirname($filename));
$dirParts = explode('/', $dirname);
- $dir = "/files_versions";
+ $dir = '/files_versions';
foreach ($dirParts as $part) {
$dir = $dir . '/' . $part;
if (!$view->file_exists($dir)) {
@@ -893,7 +1000,7 @@ class Storage {
*/
protected static function getExpiration() {
if (self::$application === null) {
- self::$application = \OC::$server->get(Application::class);
+ self::$application = Server::get(Application::class);
}
return self::$application->getContainer()->get(Expiration::class);
}
diff --git a/apps/files_versions/lib/Versions/BackendNotFoundException.php b/apps/files_versions/lib/Versions/BackendNotFoundException.php
index 151957c116a..f1fbecb852a 100644
--- a/apps/files_versions/lib/Versions/BackendNotFoundException.php
+++ b/apps/files_versions/lib/Versions/BackendNotFoundException.php
@@ -1,24 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Versions;
diff --git a/apps/files_versions/lib/Versions/IDeletableVersionBackend.php b/apps/files_versions/lib/Versions/IDeletableVersionBackend.php
new file mode 100644
index 00000000000..fefc038864f
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IDeletableVersionBackend.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+/**
+ * @since 26.0.0
+ */
+interface IDeletableVersionBackend {
+ /**
+ * Delete a version.
+ *
+ * @since 26.0.0
+ */
+ public function deleteVersion(IVersion $version): void;
+}
diff --git a/apps/files_versions/lib/Versions/IMetadataVersion.php b/apps/files_versions/lib/Versions/IMetadataVersion.php
new file mode 100644
index 00000000000..bc4cd77138b
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IMetadataVersion.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+/**
+ * This interface allows for just direct accessing of the metadata column JSON
+ * @since 29.0.0
+ */
+interface IMetadataVersion {
+ /**
+ * retrieves the all the metadata
+ *
+ * @return string[]
+ * @since 29.0.0
+ */
+ public function getMetadata(): array;
+
+ /**
+ * retrieves the metadata value from our $key param
+ *
+ * @param string $key the key for the json value of the metadata column
+ * @since 29.0.0
+ */
+ public function getMetadataValue(string $key): ?string;
+}
diff --git a/apps/files_versions/lib/Versions/IMetadataVersionBackend.php b/apps/files_versions/lib/Versions/IMetadataVersionBackend.php
new file mode 100644
index 00000000000..79db85e460b
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IMetadataVersionBackend.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+use OCP\Files\Node;
+
+/**
+ * This interface edits the metadata column of a node.
+ * Each column of the metadata has a key => value mapping.
+ * @since 29.0.0
+ */
+interface IMetadataVersionBackend {
+ /**
+ * Sets a key value pair in the metadata column corresponding to the node's version.
+ *
+ * @param Node $node the node that triggered the Metadata event listener, aka, the file version
+ * @param int $revision the key for the json value of the metadata column
+ * @param string $key the key for the json value of the metadata column
+ * @param string $value the value that corresponds to the key in the metadata column
+ * @since 29.0.0
+ */
+ public function setMetadataValue(Node $node, int $revision, string $key, string $value): void;
+}
diff --git a/apps/files_versions/lib/Versions/INameableVersion.php b/apps/files_versions/lib/Versions/INameableVersion.php
new file mode 100644
index 00000000000..a470239f128
--- /dev/null
+++ b/apps/files_versions/lib/Versions/INameableVersion.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+/**
+ * @deprecated 29.0.0
+ * @since 26.0.0
+ */
+interface INameableVersion {
+ /**
+ * Get the user created label
+ * @deprecated 29.0.0
+ * @return string
+ * @since 26.0.0
+ */
+ public function getLabel(): string;
+}
diff --git a/apps/files_versions/lib/Versions/INameableVersionBackend.php b/apps/files_versions/lib/Versions/INameableVersionBackend.php
new file mode 100644
index 00000000000..d2ab7ed8135
--- /dev/null
+++ b/apps/files_versions/lib/Versions/INameableVersionBackend.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+/**
+ * @deprecated 29.0.0
+ * @since 26.0.0
+ */
+interface INameableVersionBackend {
+ /**
+ * Set the label for a version.
+ * @deprecated 29.0.0
+ * @since 26.0.0
+ */
+ public function setVersionLabel(IVersion $version, string $label): void;
+}
diff --git a/apps/files_versions/lib/Versions/INeedSyncVersionBackend.php b/apps/files_versions/lib/Versions/INeedSyncVersionBackend.php
new file mode 100644
index 00000000000..e52e2f8e8bc
--- /dev/null
+++ b/apps/files_versions/lib/Versions/INeedSyncVersionBackend.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+use OCA\Files_Versions\Db\VersionEntity;
+use OCP\Files\File;
+
+/**
+ * @since 28.0.0
+ */
+interface INeedSyncVersionBackend {
+ /**
+ * TODO: Convert return type to strong type once all implementations are fixed.
+ * @return null|VersionEntity
+ */
+ public function createVersionEntity(File $file);
+ public function updateVersionEntity(File $sourceFile, int $revision, array $properties): void;
+ public function deleteVersionsEntity(File $file): void;
+}
diff --git a/apps/files_versions/lib/Versions/IVersion.php b/apps/files_versions/lib/Versions/IVersion.php
index 8ab3357b1e2..e5fd53d0157 100644
--- a/apps/files_versions/lib/Versions/IVersion.php
+++ b/apps/files_versions/lib/Versions/IVersion.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Versions;
@@ -65,10 +48,10 @@ interface IVersion {
/**
* Get the size of this version
*
- * @return int
+ * @return int|float
* @since 15.0.0
*/
- public function getSize(): int;
+ public function getSize(): int|float;
/**
* Get the name of the source file at the time of making this version
diff --git a/apps/files_versions/lib/Versions/IVersionBackend.php b/apps/files_versions/lib/Versions/IVersionBackend.php
index c06e395e4c1..18f8c17f0ac 100644
--- a/apps/files_versions/lib/Versions/IVersionBackend.php
+++ b/apps/files_versions/lib/Versions/IVersionBackend.php
@@ -3,29 +3,12 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Versions;
+use OC\Files\Node\Node;
use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\Files\NotFoundException;
@@ -78,7 +61,7 @@ interface IVersionBackend {
* Open the file for reading
*
* @param IVersion $version
- * @return resource
+ * @return resource|false
* @throws NotFoundException
* @since 15.0.0
*/
@@ -96,4 +79,11 @@ interface IVersionBackend {
* @since 15.0.0
*/
public function getVersionFile(IUser $user, FileInfo $sourceFile, $revision): File;
+
+ /**
+ * Get the revision for a node
+ *
+ * @since 32.0.0
+ */
+ public function getRevision(Node $node): int;
}
diff --git a/apps/files_versions/lib/Versions/IVersionManager.php b/apps/files_versions/lib/Versions/IVersionManager.php
index afc3046fa48..ecd424d0cc1 100644
--- a/apps/files_versions/lib/Versions/IVersionManager.php
+++ b/apps/files_versions/lib/Versions/IVersionManager.php
@@ -3,28 +3,13 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Versions;
+use OCP\Files\Storage\IStorage;
+
/**
* @since 15.0.0
*/
@@ -37,4 +22,10 @@ interface IVersionManager extends IVersionBackend {
* @since 15.0.0
*/
public function registerBackend(string $storageType, IVersionBackend $backend);
+
+ /**
+ * @throws BackendNotFoundException
+ * @since 29.0.0
+ */
+ public function getBackendForStorage(IStorage $storage): IVersionBackend;
}
diff --git a/apps/files_versions/lib/Versions/IVersionsImporterBackend.php b/apps/files_versions/lib/Versions/IVersionsImporterBackend.php
new file mode 100644
index 00000000000..db9349328e9
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IVersionsImporterBackend.php
@@ -0,0 +1,33 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Versions\Versions;
+
+use OCP\Files\Node;
+use OCP\IUser;
+
+/**
+ * @since 29.0.0
+ */
+interface IVersionsImporterBackend {
+ /**
+ * Import the given versions for the target file.
+ *
+ * @param Node $source - The source might not exist anymore.
+ * @param IVersion[] $versions
+ * @since 29.0.0
+ */
+ public function importVersionsForFile(IUser $user, Node $source, Node $target, array $versions): void;
+
+ /**
+ * Clear all versions for a file
+ *
+ * @since 29.0.0
+ */
+ public function clearVersionsForFile(IUser $user, Node $source, Node $target): void;
+}
diff --git a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
index 4ea0985e113..48d69d31629 100644
--- a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
+++ b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
@@ -3,50 +3,42 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
+
namespace OCA\Files_Versions\Versions;
+use Exception;
use OC\Files\View;
-use OCA\Files_Sharing\SharedStorage;
+use OCA\DAV\Connector\Sabre\Exception\Forbidden;
+use OCA\Files_Versions\Db\VersionEntity;
+use OCA\Files_Versions\Db\VersionsMapper;
use OCA\Files_Versions\Storage;
+use OCP\Constants;
use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
+use OCP\Files\IMimeTypeLoader;
use OCP\Files\IRootFolder;
+use OCP\Files\Node;
use OCP\Files\NotFoundException;
+use OCP\Files\Storage\ISharedStorage;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
-class LegacyVersionsBackend implements IVersionBackend {
- /** @var IRootFolder */
- private $rootFolder;
- /** @var IUserManager */
- private $userManager;
-
- public function __construct(IRootFolder $rootFolder, IUserManager $userManager) {
- $this->rootFolder = $rootFolder;
- $this->userManager = $userManager;
+class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend, INeedSyncVersionBackend, IMetadataVersionBackend, IVersionsImporterBackend {
+ public function __construct(
+ private IRootFolder $rootFolder,
+ private IUserManager $userManager,
+ private VersionsMapper $versionsMapper,
+ private IMimeTypeLoader $mimeTypeLoader,
+ private IUserSession $userSession,
+ private LoggerInterface $logger,
+ ) {
}
public function useBackendForStorage(IStorage $storage): bool {
@@ -55,29 +47,104 @@ class LegacyVersionsBackend implements IVersionBackend {
public function getVersionsForFile(IUser $user, FileInfo $file): array {
$storage = $file->getStorage();
- if ($storage->instanceOfStorage(SharedStorage::class)) {
+
+ if ($storage->instanceOfStorage(ISharedStorage::class)) {
$owner = $storage->getOwner('');
+ if ($owner === false) {
+ throw new NotFoundException('No owner for ' . $file->getPath());
+ }
+
$user = $this->userManager->get($owner);
+
+ $fileId = $file->getId();
+ if ($fileId === null) {
+ throw new NotFoundException("File not found ($fileId)");
+ }
+
+ if ($user === null) {
+ throw new NotFoundException("User $owner not found for $fileId");
+ }
+
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+
+ $file = $userFolder->getFirstNodeById($fileId);
+
+ if (!$file) {
+ throw new NotFoundException('version file not found for share owner');
+ }
+ } else {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
}
- $userFolder = $this->rootFolder->getUserFolder($user->getUID());
- $nodes = $userFolder->getById($file->getId());
- $file2 = array_pop($nodes);
- $versions = Storage::getVersions($user->getUID(), $userFolder->getRelativePath($file2->getPath()));
-
- return array_map(function (array $data) use ($file, $user) {
- return new Version(
- (int)$data['version'],
- (int)$data['version'],
- $data['name'],
- (int)$data['size'],
- $data['mimetype'],
- $data['path'],
+ $fileId = $file->getId();
+ if ($fileId === null) {
+ throw new NotFoundException("File not found ($fileId)");
+ }
+
+ // Insert entries in the DB for existing versions.
+ $relativePath = $userFolder->getRelativePath($file->getPath());
+ if ($relativePath === null) {
+ throw new NotFoundException("Relative path not found for file $fileId (" . $file->getPath() . ')');
+ }
+
+ $currentVersion = [
+ 'version' => (string)$file->getMtime(),
+ 'size' => $file->getSize(),
+ 'mimetype' => $file->getMimetype(),
+ ];
+
+ $versionsInDB = $this->versionsMapper->findAllVersionsForFileId($file->getId());
+ /** @var array<int, array> */
+ $versionsInFS = array_values(Storage::getVersions($user->getUID(), $relativePath));
+
+ /** @var array<int, array{db: ?VersionEntity, fs: ?mixed}> */
+ $groupedVersions = [];
+ $davVersions = [];
+
+ foreach ($versionsInDB as $version) {
+ $revisionId = $version->getTimestamp();
+ $groupedVersions[$revisionId] = $groupedVersions[$revisionId] ?? [];
+ $groupedVersions[$revisionId]['db'] = $version;
+ }
+
+ foreach ([$currentVersion, ...$versionsInFS] as $version) {
+ $revisionId = $version['version'];
+ $groupedVersions[$revisionId] = $groupedVersions[$revisionId] ?? [];
+ $groupedVersions[$revisionId]['fs'] = $version;
+ }
+
+ /** @var array<string, array{db: ?VersionEntity, fs: ?mixed}> $groupedVersions */
+ foreach ($groupedVersions as $versions) {
+ if (empty($versions['db']) && !empty($versions['fs'])) {
+ $versions['db'] = new VersionEntity();
+ $versions['db']->setFileId($fileId);
+ $versions['db']->setTimestamp((int)$versions['fs']['version']);
+ $versions['db']->setSize((int)$versions['fs']['size']);
+ $versions['db']->setMimetype($this->mimeTypeLoader->getId($versions['fs']['mimetype']));
+ $versions['db']->setMetadata([]);
+ $this->versionsMapper->insert($versions['db']);
+ } elseif (!empty($versions['db']) && empty($versions['fs'])) {
+ $this->versionsMapper->delete($versions['db']);
+ continue;
+ }
+
+ $version = new Version(
+ $versions['db']->getTimestamp(),
+ $versions['db']->getTimestamp(),
+ $file->getName(),
+ $versions['db']->getSize(),
+ $this->mimeTypeLoader->getMimetypeById($versions['db']->getMimetype()),
+ $userFolder->getRelativePath($file->getPath()),
$file,
$this,
- $user
+ $user,
+ $versions['db']->getMetadata() ?? [],
);
- }, $versions);
+
+ array_push($davVersions, $version);
+ }
+
+ return $davVersions;
}
public function createVersion(IUser $user, FileInfo $file) {
@@ -96,6 +163,10 @@ class LegacyVersionsBackend implements IVersionBackend {
}
public function rollback(IVersion $version) {
+ if (!$this->currentUserHasPermissions($version->getSourceFile(), Constants::PERMISSION_UPDATE)) {
+ throw new Forbidden('You cannot restore this version because you do not have update permissions on the source file.');
+ }
+
return Storage::rollback($version->getVersionPath(), $version->getRevisionId(), $version->getUser());
}
@@ -120,9 +191,205 @@ class LegacyVersionsBackend implements IVersionBackend {
public function getVersionFile(IUser $user, FileInfo $sourceFile, $revision): File {
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $owner = $sourceFile->getOwner();
+ $storage = $sourceFile->getStorage();
+
+ // Shared files have their versions in the owners root folder so we need to obtain them from there
+ if ($storage->instanceOfStorage(ISharedStorage::class) && $owner) {
+ /** @var ISharedStorage $storage */
+ $userFolder = $this->rootFolder->getUserFolder($owner->getUID());
+ $user = $owner;
+ $ownerPathInStorage = $sourceFile->getInternalPath();
+ $sourceFile = $storage->getShare()->getNode();
+ if ($sourceFile instanceof Folder) {
+ $sourceFile = $sourceFile->get($ownerPathInStorage);
+ }
+ }
+
$versionFolder = $this->getVersionFolder($user);
/** @var File $file */
$file = $versionFolder->get($userFolder->getRelativePath($sourceFile->getPath()) . '.v' . $revision);
return $file;
}
+
+ public function getRevision(Node $node): int {
+ return $node->getMTime();
+ }
+
+ public function deleteVersion(IVersion $version): void {
+ if (!$this->currentUserHasPermissions($version->getSourceFile(), Constants::PERMISSION_DELETE)) {
+ throw new Forbidden('You cannot delete this version because you do not have delete permissions on the source file.');
+ }
+
+ Storage::deleteRevision($version->getVersionPath(), $version->getRevisionId());
+ $versionEntity = $this->versionsMapper->findVersionForFileId(
+ $version->getSourceFile()->getId(),
+ $version->getTimestamp(),
+ );
+ $this->versionsMapper->delete($versionEntity);
+ }
+
+ public function createVersionEntity(File $file): ?VersionEntity {
+ $versionEntity = new VersionEntity();
+ $versionEntity->setFileId($file->getId());
+ $versionEntity->setTimestamp($file->getMTime());
+ $versionEntity->setSize($file->getSize());
+ $versionEntity->setMimetype($this->mimeTypeLoader->getId($file->getMimetype()));
+ $versionEntity->setMetadata([]);
+
+ $tries = 1;
+ while ($tries < 5) {
+ try {
+ $this->versionsMapper->insert($versionEntity);
+ return $versionEntity;
+ } catch (\OCP\DB\Exception $e) {
+ if (!in_array($e->getReason(), [
+ \OCP\DB\Exception::REASON_CONSTRAINT_VIOLATION,
+ \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION,
+ ])
+ ) {
+ throw $e;
+ }
+ /* Conflict with another version, increase mtime and try again */
+ $versionEntity->setTimestamp($versionEntity->getTimestamp() + 1);
+ $tries++;
+ $this->logger->warning('Constraint violation while inserting version, retrying with increased timestamp', ['exception' => $e]);
+ }
+ }
+
+ return null;
+ }
+
+ public function updateVersionEntity(File $sourceFile, int $revision, array $properties): void {
+ $versionEntity = $this->versionsMapper->findVersionForFileId($sourceFile->getId(), $revision);
+
+ if (isset($properties['timestamp'])) {
+ $versionEntity->setTimestamp($properties['timestamp']);
+ }
+
+ if (isset($properties['size'])) {
+ $versionEntity->setSize($properties['size']);
+ }
+
+ if (isset($properties['mimetype'])) {
+ $versionEntity->setMimetype($properties['mimetype']);
+ }
+
+ $this->versionsMapper->update($versionEntity);
+ }
+
+ public function deleteVersionsEntity(File $file): void {
+ $this->versionsMapper->deleteAllVersionsForFileId($file->getId());
+ }
+
+ private function currentUserHasPermissions(FileInfo $sourceFile, int $permissions): bool {
+ $currentUserId = $this->userSession->getUser()?->getUID();
+
+ if ($currentUserId === null) {
+ throw new NotFoundException('No user logged in');
+ }
+
+ if ($sourceFile->getOwner()?->getUID() === $currentUserId) {
+ return ($sourceFile->getPermissions() & $permissions) === $permissions;
+ }
+
+ $nodes = $this->rootFolder->getUserFolder($currentUserId)->getById($sourceFile->getId());
+
+ if (count($nodes) === 0) {
+ throw new NotFoundException('Version file not accessible by current user');
+ }
+
+ foreach ($nodes as $node) {
+ if (($node->getPermissions() & $permissions) === $permissions) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function setMetadataValue(Node $node, int $revision, string $key, string $value): void {
+ if (!$this->currentUserHasPermissions($node, Constants::PERMISSION_UPDATE)) {
+ throw new Forbidden('You cannot update the version\'s metadata because you do not have update permissions on the source file.');
+ }
+
+ $versionEntity = $this->versionsMapper->findVersionForFileId($node->getId(), $revision);
+
+ $versionEntity->setMetadataValue($key, $value);
+ $this->versionsMapper->update($versionEntity);
+ }
+
+
+ /**
+ * @inheritdoc
+ */
+ public function importVersionsForFile(IUser $user, Node $source, Node $target, array $versions): void {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $relativePath = $userFolder->getRelativePath($target->getPath());
+
+ if ($relativePath === null) {
+ throw new \Exception('Target does not have a relative path' . $target->getPath());
+ }
+
+ $userView = new View('/' . $user->getUID());
+ // create all parent folders
+ Storage::createMissingDirectories($relativePath, $userView);
+ Storage::scheduleExpire($user->getUID(), $relativePath);
+
+ foreach ($versions as $version) {
+ // 1. Import the file in its new location.
+ // Nothing to do for the current version.
+ if ($version->getTimestamp() !== $source->getMTime()) {
+ $backend = $version->getBackend();
+ $versionFile = $backend->getVersionFile($user, $source, $version->getRevisionId());
+ $newVersionPath = 'files_versions/' . $relativePath . '.v' . $version->getTimestamp();
+
+ $versionContent = $versionFile->fopen('r');
+ if ($versionContent === false) {
+ $this->logger->warning('Fail to open version file.', ['source' => $source, 'version' => $version, 'versionFile' => $versionFile]);
+ continue;
+ }
+
+ $userView->file_put_contents($newVersionPath, $versionContent);
+ // ensure the file is scanned
+ $userView->getFileInfo($newVersionPath);
+ }
+
+ // 2. Create the entity in the database
+ $versionEntity = new VersionEntity();
+ $versionEntity->setFileId($target->getId());
+ $versionEntity->setTimestamp($version->getTimestamp());
+ $versionEntity->setSize($version->getSize());
+ $versionEntity->setMimetype($this->mimeTypeLoader->getId($version->getMimetype()));
+ if ($version instanceof IMetadataVersion) {
+ $versionEntity->setMetadata($version->getMetadata());
+ }
+ $this->versionsMapper->insert($versionEntity);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function clearVersionsForFile(IUser $user, Node $source, Node $target): void {
+ $userId = $user->getUID();
+ $userFolder = $this->rootFolder->getUserFolder($userId);
+
+ $relativePath = $userFolder->getRelativePath($source->getPath());
+ if ($relativePath === null) {
+ throw new Exception('Relative path not found for node with path: ' . $source->getPath());
+ }
+
+ $versionFolder = $this->rootFolder->get($userId . '/files_versions');
+ if (!$versionFolder instanceof Folder) {
+ throw new Exception('User versions folder does not exist');
+ }
+
+ $versions = Storage::getVersions($userId, $relativePath);
+ foreach ($versions as $version) {
+ $versionFolder->get($version['path'] . '.v' . (int)$version['version'])->delete();
+ }
+
+ $this->versionsMapper->deleteAllVersionsForFileId($target->getId());
+ }
}
diff --git a/apps/files_versions/lib/Versions/Version.php b/apps/files_versions/lib/Versions/Version.php
index 9979933ebc5..e202a69b7d7 100644
--- a/apps/files_versions/lib/Versions/Version.php
+++ b/apps/files_versions/lib/Versions/Version.php
@@ -3,79 +3,27 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Versions;
use OCP\Files\FileInfo;
use OCP\IUser;
-class Version implements IVersion {
- /** @var int */
- private $timestamp;
-
- /** @var int|string */
- private $revisionId;
-
- /** @var string */
- private $name;
-
- /** @var int */
- private $size;
-
- /** @var string */
- private $mimetype;
-
- /** @var string */
- private $path;
-
- /** @var FileInfo */
- private $sourceFileInfo;
-
- /** @var IVersionBackend */
- private $backend;
-
- /** @var IUser */
- private $user;
-
+class Version implements IVersion, IMetadataVersion {
public function __construct(
- int $timestamp,
- $revisionId,
- string $name,
- int $size,
- string $mimetype,
- string $path,
- FileInfo $sourceFileInfo,
- IVersionBackend $backend,
- IUser $user
+ private int $timestamp,
+ private int|string $revisionId,
+ private string $name,
+ private int|float $size,
+ private string $mimetype,
+ private string $path,
+ private FileInfo $sourceFileInfo,
+ private IVersionBackend $backend,
+ private IUser $user,
+ private array $metadata = [],
) {
- $this->timestamp = $timestamp;
- $this->revisionId = $revisionId;
- $this->name = $name;
- $this->size = $size;
- $this->mimetype = $mimetype;
- $this->path = $path;
- $this->sourceFileInfo = $sourceFileInfo;
- $this->backend = $backend;
- $this->user = $user;
}
public function getBackend(): IVersionBackend {
@@ -94,7 +42,7 @@ class Version implements IVersion {
return $this->timestamp;
}
- public function getSize(): int {
+ public function getSize(): int|float {
return $this->size;
}
@@ -113,4 +61,12 @@ class Version implements IVersion {
public function getUser(): IUser {
return $this->user;
}
+
+ public function getMetadata(): array {
+ return $this->metadata;
+ }
+
+ public function getMetadataValue(string $key): ?string {
+ return $this->metadata[$key] ?? null;
+ }
}
diff --git a/apps/files_versions/lib/Versions/VersionManager.php b/apps/files_versions/lib/Versions/VersionManager.php
index 4700f1b208b..9acea8c6513 100644
--- a/apps/files_versions/lib/Versions/VersionManager.php
+++ b/apps/files_versions/lib/Versions/VersionManager.php
@@ -3,37 +3,37 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Versions;
+use OCA\Files_Versions\Db\VersionEntity;
+use OCA\Files_Versions\Events\VersionCreatedEvent;
+use OCA\Files_Versions\Events\VersionRestoredEvent;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
use OCP\Files\FileInfo;
+use OCP\Files\IRootFolder;
+use OCP\Files\Lock\ILock;
+use OCP\Files\Lock\ILockManager;
+use OCP\Files\Lock\LockContext;
+use OCP\Files\Node;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
+use OCP\Lock\ManuallyLockedException;
+use OCP\Server;
+
+class VersionManager implements IVersionManager, IDeletableVersionBackend, INeedSyncVersionBackend, IMetadataVersionBackend {
-class VersionManager implements IVersionManager {
/** @var (IVersionBackend[])[] */
private $backends = [];
+ public function __construct(
+ private IEventDispatcher $dispatcher,
+ ) {
+ }
+
public function registerBackend(string $storageType, IVersionBackend $backend) {
if (!isset($this->backends[$storageType])) {
$this->backends[$storageType] = [];
@@ -62,8 +62,8 @@ class VersionManager implements IVersionManager {
foreach ($backends as $type => $backendsForType) {
if (
- $storage->instanceOfStorage($type) &&
- ($foundType === '' || is_subclass_of($type, $foundType))
+ $storage->instanceOfStorage($type)
+ && ($foundType === '' || is_subclass_of($type, $foundType))
) {
foreach ($backendsForType as $backend) {
/** @var IVersionBackend $backend */
@@ -94,7 +94,12 @@ class VersionManager implements IVersionManager {
public function rollback(IVersion $version) {
$backend = $version->getBackend();
- return $backend->rollback($version);
+ $result = self::handleAppLocks(fn (): ?bool => $backend->rollback($version));
+ // rollback doesn't have a return type yet and some implementations don't return anything
+ if ($result === null || $result === true) {
+ $this->dispatcher->dispatchTyped(new VersionRestoredEvent($version));
+ }
+ return $result;
}
public function read(IVersion $version) {
@@ -107,7 +112,99 @@ class VersionManager implements IVersionManager {
return $backend->getVersionFile($user, $sourceFile, $revision);
}
+ public function getRevision(Node $node): int {
+ $backend = $this->getBackendForStorage($node->getStorage());
+ return $backend->getRevision($node);
+ }
+
public function useBackendForStorage(IStorage $storage): bool {
return false;
}
+
+ public function deleteVersion(IVersion $version): void {
+ $backend = $version->getBackend();
+ if ($backend instanceof IDeletableVersionBackend) {
+ $backend->deleteVersion($version);
+ }
+ }
+
+ public function createVersionEntity(File $file): void {
+ $backend = $this->getBackendForStorage($file->getStorage());
+ if ($backend instanceof INeedSyncVersionBackend) {
+ $versionEntity = $backend->createVersionEntity($file);
+
+ if ($versionEntity instanceof VersionEntity) {
+ foreach ($backend->getVersionsForFile($file->getOwner(), $file) as $version) {
+ if ($version->getRevisionId() === $versionEntity->getTimestamp()) {
+ $this->dispatcher->dispatchTyped(new VersionCreatedEvent($file, $version));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public function updateVersionEntity(File $sourceFile, int $revision, array $properties): void {
+ $backend = $this->getBackendForStorage($sourceFile->getStorage());
+ if ($backend instanceof INeedSyncVersionBackend) {
+ $backend->updateVersionEntity($sourceFile, $revision, $properties);
+ }
+ }
+
+ public function deleteVersionsEntity(File $file): void {
+ $backend = $this->getBackendForStorage($file->getStorage());
+ if ($backend instanceof INeedSyncVersionBackend) {
+ $backend->deleteVersionsEntity($file);
+ }
+ }
+
+ public function setMetadataValue(Node $node, int $revision, string $key, string $value): void {
+ $backend = $this->getBackendForStorage($node->getStorage());
+ if ($backend instanceof IMetadataVersionBackend) {
+ $backend->setMetadataValue($node, $revision, $key, $value);
+ }
+ }
+
+ /**
+ * Catch ManuallyLockedException and retry in app context if possible.
+ *
+ * Allow users to go back to old versions via the versions tab in the sidebar
+ * even when the file is opened in the viewer next to it.
+ *
+ * Context: If a file is currently opened for editing
+ * the files_lock app will throw ManuallyLockedExceptions.
+ * This prevented the user from rolling an opened file back to a previous version.
+ *
+ * Text and Richdocuments can handle changes of open files.
+ * So we execute the rollback under their lock context
+ * to let them handle the conflict.
+ *
+ * @param callable $callback function to run with app locks handled
+ * @return bool|null
+ * @throws ManuallyLockedException
+ *
+ */
+ private static function handleAppLocks(callable $callback): ?bool {
+ try {
+ return $callback();
+ } catch (ManuallyLockedException $e) {
+ $owner = (string)$e->getOwner();
+ $appsThatHandleUpdates = ['text', 'richdocuments'];
+ if (!in_array($owner, $appsThatHandleUpdates)) {
+ throw $e;
+ }
+ // The LockWrapper in the files_lock app only compares the lock type and owner
+ // when checking the lock against the current scope.
+ // So we do not need to get the actual node here
+ // and use the root node instead.
+ $root = Server::get(IRootFolder::class);
+ $lockContext = new LockContext($root, ILock::TYPE_APP, $owner);
+ $lockManager = Server::get(ILockManager::class);
+ $result = null;
+ $lockManager->runInScope($lockContext, function () use ($callback, &$result): void {
+ $result = $callback();
+ });
+ return $result;
+ }
+ }
}
diff --git a/apps/files_versions/openapi.json b/apps/files_versions/openapi.json
new file mode 100644
index 00000000000..aea18edf3ec
--- /dev/null
+++ b/apps/files_versions/openapi.json
@@ -0,0 +1,164 @@
+{
+ "openapi": "3.0.3",
+ "info": {
+ "title": "files_versions",
+ "version": "0.0.1",
+ "description": "This application automatically maintains older versions of files that are changed.",
+ "license": {
+ "name": "agpl"
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "basic_auth": {
+ "type": "http",
+ "scheme": "basic"
+ },
+ "bearer_auth": {
+ "type": "http",
+ "scheme": "bearer"
+ }
+ },
+ "schemas": {
+ "Capabilities": {
+ "type": "object",
+ "required": [
+ "files"
+ ],
+ "properties": {
+ "files": {
+ "type": "object",
+ "required": [
+ "versioning",
+ "version_labeling",
+ "version_deletion"
+ ],
+ "properties": {
+ "versioning": {
+ "type": "boolean"
+ },
+ "version_labeling": {
+ "type": "boolean"
+ },
+ "version_deletion": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "paths": {
+ "/index.php/apps/files_versions/preview": {
+ "get": {
+ "operationId": "preview-get-preview",
+ "summary": "Get the preview for a file version",
+ "tags": [
+ "preview"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "file",
+ "in": "query",
+ "description": "Path of the file",
+ "schema": {
+ "type": "string",
+ "default": ""
+ }
+ },
+ {
+ "name": "x",
+ "in": "query",
+ "description": "Width of the preview",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 44
+ }
+ },
+ {
+ "name": "y",
+ "in": "query",
+ "description": "Height of the preview",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 44
+ }
+ },
+ {
+ "name": "version",
+ "in": "query",
+ "description": "Version of the file to get the preview for",
+ "schema": {
+ "type": "string",
+ "default": ""
+ }
+ },
+ {
+ "name": "mimeFallback",
+ "in": "query",
+ "description": "Whether to fallback to the mime icon if no preview is available",
+ "schema": {
+ "type": "integer",
+ "default": 0,
+ "enum": [
+ 0,
+ 1
+ ]
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Preview returned",
+ "content": {
+ "*/*": {
+ "schema": {
+ "type": "string",
+ "format": "binary"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Getting preview is not possible",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "404": {
+ "description": "Preview not found",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ },
+ "303": {
+ "description": "Redirect to the mime icon url if mimeFallback is true",
+ "headers": {
+ "Location": {
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/apps/files_versions/openapi.json.license b/apps/files_versions/openapi.json.license
new file mode 100644
index 00000000000..83559daa9dc
--- /dev/null
+++ b/apps/files_versions/openapi.json.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later \ No newline at end of file
diff --git a/apps/files_versions/src/components/Version.vue b/apps/files_versions/src/components/Version.vue
new file mode 100644
index 00000000000..dc36e4134f9
--- /dev/null
+++ b/apps/files_versions/src/components/Version.vue
@@ -0,0 +1,393 @@
+<!--
+ - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<template>
+ <NcListItem class="version"
+ :force-display-actions="true"
+ :actions-aria-label="t('files_versions', 'Actions for version from {versionHumanExplicitDate}', { versionHumanExplicitDate })"
+ :data-files-versions-version="version.fileVersion"
+ @click="click">
+ <!-- Icon -->
+ <template #icon>
+ <div v-if="!(loadPreview || previewLoaded)" class="version__image" />
+ <img v-else-if="version.previewUrl && !previewErrored"
+ :src="version.previewUrl"
+ alt=""
+ decoding="async"
+ fetchpriority="low"
+ loading="lazy"
+ class="version__image"
+ @load="previewLoaded = true"
+ @error="previewErrored = true">
+ <div v-else
+ class="version__image">
+ <ImageOffOutline :size="20" />
+ </div>
+ </template>
+
+ <!-- author -->
+ <template #name>
+ <div class="version__info">
+ <div v-if="versionLabel"
+ class="version__info__label"
+ data-cy-files-version-label
+ :title="versionLabel">
+ {{ versionLabel }}
+ </div>
+ <div v-if="versionAuthor"
+ class="version__info"
+ data-cy-files-version-author-name>
+ <span v-if="versionLabel">•</span>
+ <NcAvatar class="avatar"
+ :user="version.author"
+ :size="20"
+ disable-menu
+ disable-tooltip
+ :show-user-status="false" />
+ <div class="version__info__author_name"
+ :title="versionAuthor">
+ {{ versionAuthor }}
+ </div>
+ </div>
+ </div>
+ </template>
+
+ <!-- Version file size as subline -->
+ <template #subname>
+ <div class="version__info version__info__subline">
+ <NcDateTime class="version__info__date"
+ relative-time="short"
+ :timestamp="version.mtime" />
+ <!-- Separate dot to improve alignment -->
+ <span>•</span>
+ <span>{{ humanReadableSize }}</span>
+ </div>
+ </template>
+
+ <!-- Actions -->
+ <template #actions>
+ <NcActionButton v-if="enableLabeling && hasUpdatePermissions"
+ data-cy-files-versions-version-action="label"
+ :close-after-click="true"
+ @click="labelUpdate">
+ <template #icon>
+ <Pencil :size="22" />
+ </template>
+ {{ version.label === '' ? t('files_versions', 'Name this version') : t('files_versions', 'Edit version name') }}
+ </NcActionButton>
+ <NcActionButton v-if="!isCurrent && canView && canCompare"
+ data-cy-files-versions-version-action="compare"
+ :close-after-click="true"
+ @click="compareVersion">
+ <template #icon>
+ <FileCompare :size="22" />
+ </template>
+ {{ t('files_versions', 'Compare to current version') }}
+ </NcActionButton>
+ <NcActionButton v-if="!isCurrent && hasUpdatePermissions"
+ data-cy-files-versions-version-action="restore"
+ :close-after-click="true"
+ @click="restoreVersion">
+ <template #icon>
+ <BackupRestore :size="22" />
+ </template>
+ {{ t('files_versions', 'Restore version') }}
+ </NcActionButton>
+ <NcActionLink v-if="isDownloadable"
+ data-cy-files-versions-version-action="download"
+ :href="downloadURL"
+ :close-after-click="true"
+ :download="downloadURL">
+ <template #icon>
+ <Download :size="22" />
+ </template>
+ {{ t('files_versions', 'Download version') }}
+ </NcActionLink>
+ <NcActionButton v-if="!isCurrent && enableDeletion && hasDeletePermissions"
+ data-cy-files-versions-version-action="delete"
+ :close-after-click="true"
+ @click="deleteVersion">
+ <template #icon>
+ <Delete :size="22" />
+ </template>
+ {{ t('files_versions', 'Delete version') }}
+ </NcActionButton>
+ </template>
+ </NcListItem>
+</template>
+<script lang="ts">
+import type { PropType } from 'vue'
+import type { Version } from '../utils/versions'
+
+import { getCurrentUser } from '@nextcloud/auth'
+import { Permission, formatFileSize } from '@nextcloud/files'
+import { loadState } from '@nextcloud/initial-state'
+import { t } from '@nextcloud/l10n'
+import { joinPaths } from '@nextcloud/paths'
+import { getRootUrl, generateUrl } from '@nextcloud/router'
+import { defineComponent } from 'vue'
+
+import axios from '@nextcloud/axios'
+import moment from '@nextcloud/moment'
+import logger from '../utils/logger'
+
+import BackupRestore from 'vue-material-design-icons/BackupRestore.vue'
+import Delete from 'vue-material-design-icons/Delete.vue'
+import Download from 'vue-material-design-icons/Download.vue'
+import FileCompare from 'vue-material-design-icons/FileCompare.vue'
+import ImageOffOutline from 'vue-material-design-icons/ImageOffOutline.vue'
+import Pencil from 'vue-material-design-icons/PencilOutline.vue'
+
+import NcActionButton from '@nextcloud/vue/components/NcActionButton'
+import NcActionLink from '@nextcloud/vue/components/NcActionLink'
+import NcAvatar from '@nextcloud/vue/components/NcAvatar'
+import NcDateTime from '@nextcloud/vue/components/NcDateTime'
+import NcListItem from '@nextcloud/vue/components/NcListItem'
+import Tooltip from '@nextcloud/vue/directives/Tooltip'
+
+const hasPermission = (permissions: number, permission: number): boolean => (permissions & permission) !== 0
+
+export default defineComponent({
+ name: 'Version',
+
+ components: {
+ NcActionLink,
+ NcActionButton,
+ NcAvatar,
+ NcDateTime,
+ NcListItem,
+ BackupRestore,
+ Download,
+ FileCompare,
+ Pencil,
+ Delete,
+ ImageOffOutline,
+ },
+
+ directives: {
+ tooltip: Tooltip,
+ },
+
+ props: {
+ version: {
+ type: Object as PropType<Version>,
+ required: true,
+ },
+ fileInfo: {
+ type: Object,
+ required: true,
+ },
+ isCurrent: {
+ type: Boolean,
+ default: false,
+ },
+ isFirstVersion: {
+ type: Boolean,
+ default: false,
+ },
+ loadPreview: {
+ type: Boolean,
+ default: false,
+ },
+ canView: {
+ type: Boolean,
+ default: false,
+ },
+ canCompare: {
+ type: Boolean,
+ default: false,
+ },
+ },
+
+ emits: ['click', 'compare', 'restore', 'delete', 'label-update-request'],
+
+ data() {
+ return {
+ previewLoaded: false,
+ previewErrored: false,
+ capabilities: loadState('core', 'capabilities', { files: { version_labeling: false, version_deletion: false } }),
+ versionAuthor: '' as string | null,
+ }
+ },
+
+ computed: {
+ humanReadableSize() {
+ return formatFileSize(this.version.size)
+ },
+
+ versionLabel(): string {
+ const label = this.version.label ?? ''
+
+ if (this.isCurrent) {
+ if (label === '') {
+ return t('files_versions', 'Current version')
+ } else {
+ return `${label} (${t('files_versions', 'Current version')})`
+ }
+ }
+
+ if (this.isFirstVersion && label === '') {
+ return t('files_versions', 'Initial version')
+ }
+
+ return label
+ },
+
+ versionHumanExplicitDate(): string {
+ return moment(this.version.mtime).format('LLLL')
+ },
+
+ downloadURL(): string {
+ if (this.isCurrent) {
+ return getRootUrl() + joinPaths('/remote.php/webdav', this.fileInfo.path, this.fileInfo.name)
+ } else {
+ return getRootUrl() + this.version.url
+ }
+ },
+
+ enableLabeling(): boolean {
+ return this.capabilities.files.version_labeling === true
+ },
+
+ enableDeletion(): boolean {
+ return this.capabilities.files.version_deletion === true
+ },
+
+ hasDeletePermissions(): boolean {
+ return hasPermission(this.fileInfo.permissions, Permission.DELETE)
+ },
+
+ hasUpdatePermissions(): boolean {
+ return hasPermission(this.fileInfo.permissions, Permission.UPDATE)
+ },
+
+ isDownloadable(): boolean {
+ if ((this.fileInfo.permissions & Permission.READ) === 0) {
+ return false
+ }
+
+ // If the mount type is a share, ensure it got download permissions.
+ if (this.fileInfo.mountType === 'shared') {
+ const downloadAttribute = this.fileInfo.shareAttributes
+ .find((attribute) => attribute.scope === 'permissions' && attribute.key === 'download') || {}
+ // If the download attribute is set to false, the file is not downloadable
+ if (downloadAttribute?.value === false) {
+ return false
+ }
+ }
+
+ return true
+ },
+ },
+
+ created() {
+ this.fetchDisplayName()
+ },
+
+ methods: {
+ labelUpdate() {
+ this.$emit('label-update-request')
+ },
+
+ restoreVersion() {
+ this.$emit('restore', this.version)
+ },
+
+ async deleteVersion() {
+ // Let @nc-vue properly remove the popover before we delete the version.
+ // This prevents @nc-vue from throwing a error.
+ await this.$nextTick()
+ await this.$nextTick()
+ this.$emit('delete', this.version)
+ },
+
+ async fetchDisplayName() {
+ this.versionAuthor = null
+ if (!this.version.author) {
+ return
+ }
+
+ if (this.version.author === getCurrentUser()?.uid) {
+ this.versionAuthor = t('files_versions', 'You')
+ } else {
+ try {
+ const { data } = await axios.post(generateUrl('/displaynames'), { users: [this.version.author] })
+ this.versionAuthor = data.users[this.version.author]
+ } catch (error) {
+ logger.warn('Could not load user display name', { error })
+ }
+ }
+ },
+
+ click() {
+ if (!this.canView) {
+ window.location.href = this.downloadURL
+ return
+ }
+ this.$emit('click', { version: this.version })
+ },
+
+ compareVersion() {
+ if (!this.canView) {
+ throw new Error('Cannot compare version of this file')
+ }
+ this.$emit('compare', { version: this.version })
+ },
+
+ t,
+ },
+})
+</script>
+
+<style scoped lang="scss">
+.version {
+ display: flex;
+ flex-direction: row;
+
+ &__info {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 0.5rem;
+ color: var(--color-main-text);
+ font-weight: 500;
+ overflow: hidden;
+
+ &__label {
+ font-weight: 700;
+ // Fix overflow on narrow screens
+ overflow: hidden;
+ text-overflow: ellipsis;
+ min-width: 110px;
+ }
+
+ &__author_name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &__date {
+ // Fix overflow on narrow screens
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &__subline {
+ color: var(--color-text-maxcontrast)
+ }
+ }
+
+ &__image {
+ width: 3rem;
+ height: 3rem;
+ border: 1px solid var(--color-border);
+ border-radius: var(--border-radius-large);
+
+ // Useful to display no preview icon.
+ display: flex;
+ justify-content: center;
+ color: var(--color-text-light);
+ }
+}
+</style>
diff --git a/apps/files_versions/src/components/VersionLabelDialog.vue b/apps/files_versions/src/components/VersionLabelDialog.vue
new file mode 100644
index 00000000000..760780cae61
--- /dev/null
+++ b/apps/files_versions/src/components/VersionLabelDialog.vue
@@ -0,0 +1,123 @@
+<!--
+ - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<template>
+ <NcDialog :buttons="dialogButtons"
+ content-classes="version-label-modal"
+ is-form
+ :open="open"
+ size="normal"
+ :name="t('files_versions', 'Name this version')"
+ @update:open="$emit('update:open', $event)"
+ @submit="setVersionLabel(editedVersionLabel)">
+ <NcTextField ref="labelInput"
+ class="version-label-modal__input"
+ :label="t('files_versions', 'Version name')"
+ :placeholder="t('files_versions', 'Version name')"
+ :value.sync="editedVersionLabel" />
+
+ <p class="version-label-modal__info">
+ {{ t('files_versions', 'Named versions are persisted, and excluded from automatic cleanups when your storage quota is full.') }}
+ </p>
+ </NcDialog>
+</template>
+
+<script lang="ts">
+import { t } from '@nextcloud/l10n'
+import { defineComponent } from 'vue'
+import svgCheck from '@mdi/svg/svg/check.svg?raw'
+
+import NcDialog from '@nextcloud/vue/components/NcDialog'
+import NcTextField from '@nextcloud/vue/components/NcTextField'
+
+type Focusable = Vue & { focus: () => void }
+
+export default defineComponent({
+ name: 'VersionLabelDialog',
+ components: {
+ NcDialog,
+ NcTextField,
+ },
+ props: {
+ open: {
+ type: Boolean,
+ default: false,
+ },
+ versionLabel: {
+ type: String,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ editedVersionLabel: '',
+ }
+ },
+ computed: {
+ dialogButtons() {
+ const buttons: unknown[] = []
+ if (this.versionLabel.trim() === '') {
+ // If there is no label just offer a cancel action that just closes the dialog
+ buttons.push({
+ label: t('files_versions', 'Cancel'),
+ })
+ } else {
+ // If there is already a label set, offer to remove the version label
+ buttons.push({
+ label: t('files_versions', 'Remove version name'),
+ type: 'error',
+ nativeType: 'reset',
+ callback: () => { this.setVersionLabel('') },
+ })
+ }
+ return [
+ ...buttons,
+ {
+ label: t('files_versions', 'Save version name'),
+ type: 'primary',
+ nativeType: 'submit',
+ icon: svgCheck,
+ },
+ ]
+ },
+ },
+ watch: {
+ versionLabel: {
+ immediate: true,
+ handler(label) {
+ this.editedVersionLabel = label ?? ''
+ },
+ },
+ open: {
+ immediate: true,
+ handler(open) {
+ if (open) {
+ this.$nextTick(() => (this.$refs.labelInput as Focusable).focus())
+ }
+ this.editedVersionLabel = this.versionLabel
+ },
+ },
+ },
+ methods: {
+ setVersionLabel(label: string) {
+ this.$emit('label-update', label)
+ },
+
+ t,
+ },
+})
+</script>
+
+<style scoped lang="scss">
+.version-label-modal {
+ &__info {
+ color: var(--color-text-maxcontrast);
+ margin-block: calc(3 * var(--default-grid-baseline));
+ }
+
+ &__input {
+ margin-block-start: calc(2 * var(--default-grid-baseline));
+ }
+}
+</style>
diff --git a/apps/files_versions/src/components/VirtualScrolling.vue b/apps/files_versions/src/components/VirtualScrolling.vue
new file mode 100644
index 00000000000..5a502036839
--- /dev/null
+++ b/apps/files_versions/src/components/VirtualScrolling.vue
@@ -0,0 +1,346 @@
+<!--
+ - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<template>
+ <div v-if="!useWindow && containerElement === null" ref="container" class="vs-container">
+ <div ref="rowsContainer"
+ class="vs-rows-container"
+ :style="rowsContainerStyle">
+ <slot :visible-sections="visibleSections" />
+ <slot name="loader" />
+ </div>
+ </div>
+ <div v-else
+ ref="rowsContainer"
+ class="vs-rows-container"
+ :style="rowsContainerStyle">
+ <slot :visible-sections="visibleSections" />
+ <slot name="loader" />
+ </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, type PropType } from 'vue'
+
+import logger from '../utils/logger.js'
+
+interface RowItem {
+ id: string // Unique id for the item.
+ key?: string // Unique key for the item.
+}
+
+interface Row {
+ key: string // Unique key for the row.
+ height: number // The height of the row.
+ sectionKey: string // Unique key for the row.
+ items: RowItem[] // List of items in the row.
+}
+
+interface VisibleRow extends Row {
+ distance: number // The distance from the visible viewport
+}
+
+interface Section {
+ key: string, // Unique key for the section.
+ rows: Row[], // The height of the row.
+ height: number, // Height of the section, excluding the header.
+}
+
+interface VisibleSection extends Section {
+ rows: VisibleRow[], // The height of the row.
+}
+
+export default defineComponent({
+ name: 'VirtualScrolling',
+
+ props: {
+ sections: {
+ type: Array as PropType<Section[]>,
+ required: true,
+ },
+
+ containerElement: {
+ type: HTMLElement,
+ default: null,
+ },
+
+ useWindow: {
+ type: Boolean,
+ default: false,
+ },
+
+ headerHeight: {
+ type: Number,
+ default: 75,
+ },
+ renderDistance: {
+ type: Number,
+ default: 0.5,
+ },
+ bottomBufferRatio: {
+ type: Number,
+ default: 2,
+ },
+ scrollToKey: {
+ type: String,
+ default: '',
+ },
+ },
+
+ data() {
+ return {
+ scrollPosition: 0,
+ containerHeight: 0,
+ rowsContainerHeight: 0,
+ resizeObserver: null as ResizeObserver|null,
+ }
+ },
+
+ computed: {
+ visibleSections(): VisibleSection[] {
+ logger.debug('[VirtualScrolling] Computing visible section', { sections: this.sections })
+
+ // Optimization: get those computed properties once to not go through vue's internal every time we need them.
+ const containerHeight = this.containerHeight
+ const containerTop = this.scrollPosition
+ const containerBottom = containerTop + containerHeight
+
+ let currentRowTop = 0
+ let currentRowBottom = 0
+
+ // Compute whether a row should be included in the DOM (shouldRender)
+ // And how visible the row is.
+ const visibleSections = this.sections
+ .map(section => {
+ currentRowBottom += this.headerHeight
+
+ return {
+ ...section,
+ rows: section.rows.reduce((visibleRows, row) => {
+ currentRowTop = currentRowBottom
+ currentRowBottom += row.height
+
+ let distance = 0
+
+ if (currentRowBottom < containerTop) {
+ distance = (containerTop - currentRowBottom) / containerHeight
+ } else if (currentRowTop > containerBottom) {
+ distance = (currentRowTop - containerBottom) / containerHeight
+ }
+
+ if (distance > this.renderDistance) {
+ return visibleRows
+ }
+
+ return [
+ ...visibleRows,
+ {
+ ...row,
+ distance,
+ },
+ ]
+ }, [] as VisibleRow[]),
+ }
+ })
+ .filter(section => section.rows.length > 0)
+
+ // To allow vue to recycle the DOM elements instead of adding and deleting new ones,
+ // we assign a random key to each items. When a item removed, we recycle its key for new items,
+ // so vue can replace the content of removed DOM elements with the content of new items, but keep the other DOM elements untouched.
+ const visibleItems = visibleSections
+ .flatMap(({ rows }) => rows)
+ .flatMap(({ items }) => items)
+
+ const rowIdToKeyMap = this._rowIdToKeyMap as {[key: string]: string}
+
+ visibleItems.forEach(item => (item.key = rowIdToKeyMap[item.id]))
+
+ const usedTokens = visibleItems
+ .map(({ key }) => key)
+ .filter(key => key !== undefined)
+
+ const unusedTokens = Object.values(rowIdToKeyMap).filter(key => !usedTokens.includes(key))
+
+ visibleItems
+ .filter(({ key }) => key === undefined)
+ .forEach(item => (item.key = unusedTokens.pop() ?? Math.random().toString(36).substr(2)))
+
+ // this._rowIdToKeyMap is created in the beforeCreate hook, so value changes are not tracked.
+ // Therefore, we wont trigger the computation of visibleSections again if we alter the value of this._rowIdToKeyMap.
+ // eslint-disable-next-line vue/no-side-effects-in-computed-properties
+ this._rowIdToKeyMap = visibleItems.reduce((finalMapping, { id, key }) => ({ ...finalMapping, [`${id}`]: key }), {})
+
+ return visibleSections
+ },
+
+ /**
+ * Total height of all the rows + some room for the loader.
+ */
+ totalHeight(): number {
+ const loaderHeight = 0
+
+ return this.sections
+ .map(section => this.headerHeight + section.height)
+ .reduce((totalHeight, sectionHeight) => totalHeight + sectionHeight, 0) + loaderHeight
+ },
+
+ paddingTop(): number {
+ if (this.visibleSections.length === 0) {
+ return 0
+ }
+
+ let paddingTop = 0
+
+ for (const section of this.sections) {
+ if (section.key !== this.visibleSections[0].rows[0].sectionKey) {
+ paddingTop += this.headerHeight + section.height
+ continue
+ }
+
+ for (const row of section.rows) {
+ if (row.key === this.visibleSections[0].rows[0].key) {
+ return paddingTop
+ }
+
+ paddingTop += row.height
+ }
+
+ paddingTop += this.headerHeight
+ }
+
+ return paddingTop
+ },
+
+ /**
+ * padding-top is used to replace not included item in the container.
+ */
+ rowsContainerStyle(): { height: string; paddingTop: string } {
+ return {
+ height: `${this.totalHeight}px`,
+ paddingTop: `${this.paddingTop}px`,
+ }
+ },
+
+ /**
+ * Whether the user is near the bottom.
+ * If true, then the need-content event will be emitted.
+ */
+ isNearBottom(): boolean {
+ const buffer = this.containerHeight * this.bottomBufferRatio
+ return this.scrollPosition + this.containerHeight >= this.totalHeight - buffer
+ },
+
+ container() {
+ logger.debug('[VirtualScrolling] Computing container')
+ if (this.containerElement !== null) {
+ return this.containerElement
+ } else if (this.useWindow) {
+ return window
+ } else {
+ return this.$refs.container as Element
+ }
+ },
+ },
+
+ watch: {
+ isNearBottom(value) {
+ logger.debug('[VirtualScrolling] isNearBottom changed', { value })
+ if (value) {
+ this.$emit('need-content')
+ }
+ },
+
+ visibleSections() {
+ // Re-emit need-content when rows is updated and isNearBottom is still true.
+ // If the height of added rows is under `bottomBufferRatio`, `isNearBottom` will still be true so we need more content.
+ if (this.isNearBottom) {
+ this.$emit('need-content')
+ }
+ },
+
+ scrollToKey(key) {
+ let currentRowTopDistanceFromTop = 0
+
+ for (const section of this.sections) {
+ if (section.key !== key) {
+ currentRowTopDistanceFromTop += this.headerHeight + section.height
+ continue
+ }
+
+ break
+ }
+
+ logger.debug('[VirtualScrolling] Scrolling to', { currentRowTopDistanceFromTop })
+ this.container.scrollTo({ top: currentRowTopDistanceFromTop, behavior: 'smooth' })
+ },
+ },
+
+ beforeCreate() {
+ this._rowIdToKeyMap = {}
+ },
+
+ mounted() {
+ this.resizeObserver = new ResizeObserver(entries => {
+ for (const entry of entries) {
+ const cr = entry.contentRect
+ if (entry.target === this.container) {
+ this.containerHeight = cr.height
+ }
+ if (entry.target.classList.contains('vs-rows-container')) {
+ this.rowsContainerHeight = cr.height
+ }
+ }
+ })
+
+ if (this.useWindow) {
+ window.addEventListener('resize', this.updateContainerSize, { passive: true })
+ this.containerHeight = window.innerHeight
+ } else {
+ this.resizeObserver.observe(this.container as HTMLElement|Element)
+ }
+
+ this.resizeObserver.observe(this.$refs.rowsContainer as Element)
+ this.container.addEventListener('scroll', this.updateScrollPosition, { passive: true })
+ },
+
+ beforeDestroy() {
+ if (this.useWindow) {
+ window.removeEventListener('resize', this.updateContainerSize)
+ }
+
+ this.resizeObserver?.disconnect()
+ this.container.removeEventListener('scroll', this.updateScrollPosition)
+ },
+
+ methods: {
+ updateScrollPosition() {
+ this._onScrollHandle ??= requestAnimationFrame(() => {
+ this._onScrollHandle = null
+ if (this.useWindow) {
+ this.scrollPosition = (this.container as Window).scrollY
+ } else {
+ this.scrollPosition = (this.container as HTMLElement|Element).scrollTop
+ }
+ })
+ },
+
+ updateContainerSize() {
+ this.containerHeight = window.innerHeight
+ },
+ },
+})
+</script>
+
+<style scoped lang="scss">
+.vs-container {
+ overflow-y: scroll;
+ height: 100%;
+}
+
+.vs-rows-container {
+ box-sizing: border-box;
+ will-change: scroll-position, padding;
+ contain: layout paint style;
+}
+</style>
diff --git a/apps/files_versions/src/css/versions.css b/apps/files_versions/src/css/versions.css
index 74ab146b051..1637394ef48 100644
--- a/apps/files_versions/src/css/versions.css
+++ b/apps/files_versions/src/css/versions.css
@@ -1,3 +1,8 @@
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2012-2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
.versionsTabView .clear-float {
clear: both;
}
@@ -7,8 +12,9 @@
cursor: default;
height: 56px;
float: left;
- border-bottom: 1px solid rgba(100,100,100,.1);
+ border-bottom: 0;
}
+
.versionsTabView li:last-child {
border-bottom: none;
}
@@ -20,7 +26,7 @@
}
.versionsTabView li a{
- padding: 15px 10px 11px;
+ padding: 19px 10px 7px;
}
.versionsTabView a:hover,
@@ -35,11 +41,16 @@
.versionsTabView img {
cursor: pointer;
- padding-right: 4px;
+ padding-inline-end: 4px;
}
.versionsTabView img.preview {
+ position: relative;
+ top: 6px;
+ inset-inline-start: 10px;
+ border: 1px solid var(--color-border-dark);
cursor: default;
+ padding-inline-end: 0;
}
.versionsTabView .version-container {
@@ -52,7 +63,7 @@
}
.versionsTabView .version-details {
- text-align: left;
+ text-align: start;
}
.versionsTabView .version-details > span {
@@ -62,5 +73,31 @@
.versionsTabView .revertVersion {
cursor: pointer;
float: right;
- margin-right: -10px;
+ margin-inline-end: 0;
+}
+
+.versionsTabView li.active .downloadVersion {
+ opacity: 1;
+}
+
+.versionsTabView li.active .version-details .size {
+ color: var(--color-main-text);
+ opacity: 1;
+}
+
+.versionsTabView li.active {
+ background-color: var(--color-primary-light);
+ border-radius: 16px;
+}
+
+.versionsTabView li.active a.revertVersion {
+ opacity: 1;
+}
+
+.version-container {
+ padding-inline-start: 5px;
+}
+
+.version-details {
+ margin-top: -7px;
}
diff --git a/apps/files_versions/src/files_versions.js b/apps/files_versions/src/files_versions.js
deleted file mode 100644
index 9f4ccc2c1bf..00000000000
--- a/apps/files_versions/src/files_versions.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-import './versionmodel'
-import './versioncollection'
-import './versionstabview'
-import './filesplugin'
-import './css/versions.css'
-
-window.OCA.Versions = OCA.Versions
diff --git a/apps/files_versions/src/files_versions_tab.js b/apps/files_versions/src/files_versions_tab.js
new file mode 100644
index 00000000000..12f36bad24a
--- /dev/null
+++ b/apps/files_versions/src/files_versions_tab.js
@@ -0,0 +1,62 @@
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import Vue from 'vue'
+import { translate as t, translatePlural as n } from '@nextcloud/l10n'
+
+import VersionTab from './views/VersionTab.vue'
+import VTooltipPlugin from 'v-tooltip'
+// eslint-disable-next-line n/no-missing-import, import/no-unresolved
+import BackupRestore from '@mdi/svg/svg/backup-restore.svg?raw'
+
+Vue.prototype.t = t
+Vue.prototype.n = n
+
+Vue.use(VTooltipPlugin)
+
+// Init Sharing tab component
+const View = Vue.extend(VersionTab)
+let TabInstance = null
+
+window.addEventListener('DOMContentLoaded', function() {
+ if (OCA.Files?.Sidebar === undefined) {
+ return
+ }
+
+ OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab({
+ id: 'version_vue',
+ name: t('files_versions', 'Versions'),
+ iconSvg: BackupRestore,
+
+ async mount(el, fileInfo, context) {
+ if (TabInstance) {
+ TabInstance.$destroy()
+ }
+ TabInstance = new View({
+ // Better integration with vue parent component
+ parent: context,
+ })
+ // Only mount after we have all the info we need
+ await TabInstance.update(fileInfo)
+ TabInstance.$mount(el)
+ },
+ update(fileInfo) {
+ TabInstance.update(fileInfo)
+ },
+ setIsActive(isActive) {
+ if (!TabInstance) {
+ return
+ }
+ TabInstance.setIsActive(isActive)
+ },
+ destroy() {
+ TabInstance.$destroy()
+ TabInstance = null
+ },
+ enabled(fileInfo) {
+ return !(fileInfo?.isDirectory() ?? true)
+ },
+ }))
+})
diff --git a/apps/files_versions/src/filesplugin.js b/apps/files_versions/src/filesplugin.js
deleted file mode 100644
index 90dac2024c1..00000000000
--- a/apps/files_versions/src/filesplugin.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-(function() {
- OCA.Versions = OCA.Versions || {}
-
- /**
- * @namespace
- */
- OCA.Versions.Util = {
- /**
- * Initialize the versions plugin.
- *
- * @param {OCA.Files.FileList} fileList file list to be extended
- */
- attach(fileList) {
- if (fileList.id === 'trashbin' || fileList.id === 'files.public') {
- return
- }
-
- fileList.registerTabView(new OCA.Versions.VersionsTabView('versionsTabView', { order: -10 }))
- },
- }
-})()
-
-OC.Plugins.register('OCA.Files.FileList', OCA.Versions.Util)
diff --git a/apps/files_versions/src/templates/item.handlebars b/apps/files_versions/src/templates/item.handlebars
deleted file mode 100644
index 656cab22866..00000000000
--- a/apps/files_versions/src/templates/item.handlebars
+++ /dev/null
@@ -1,22 +0,0 @@
-<li data-revision="{{id}}">
- <div>
- <div class="preview-container">
- <img class="preview" src="{{previewUrl}}" width="44" height="44"/>
- </div>
- <div class="version-container">
- <div>
- <a href="{{downloadUrl}}" class="downloadVersion" download="{{downloadName}}"><img src="{{downloadIconUrl}}" />
- <span class="versiondate has-tooltip live-relative-timestamp" data-timestamp="{{millisecondsTimestamp}}" title="{{formattedTimestamp}}">{{relativeTimestamp}}</span>
- </a>
- </div>
- {{#hasDetails}}
- <div class="version-details">
- <span class="size has-tooltip" title="{{altSize}}">{{humanReadableSize}}</span>
- </div>
- {{/hasDetails}}
- </div>
- {{#canRevert}}
- <a href="#" class="revertVersion" title="{{revertLabel}}"><img src="{{revertIconUrl}}" /></a>
- {{/canRevert}}
- </div>
-</li>
diff --git a/apps/files_versions/src/templates/template.handlebars b/apps/files_versions/src/templates/template.handlebars
deleted file mode 100644
index f01a6f41626..00000000000
--- a/apps/files_versions/src/templates/template.handlebars
+++ /dev/null
@@ -1,10 +0,0 @@
-<ul class="versions"></ul>
-<div class="clear-float"></div>
-<div class="empty hidden">
- <div class="emptycontent">
- <div class="icon-history"></div>
- <p>{{emptyResultLabel}}</p>
- </div>
-</div>
-<input type="button" class="showMoreVersions hidden" value="{{moreVersionsLabel}}" name="show-more-versions" id="show-more-versions" />
-<div class="loading hidden" style="height: 50px"></div>
diff --git a/apps/files_versions/src/utils/davClient.js b/apps/files_versions/src/utils/davClient.js
new file mode 100644
index 00000000000..029373e9193
--- /dev/null
+++ b/apps/files_versions/src/utils/davClient.js
@@ -0,0 +1,29 @@
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { createClient } from 'webdav'
+import { generateRemoteUrl } from '@nextcloud/router'
+import { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
+
+// init webdav client
+const rootPath = 'dav'
+const remote = generateRemoteUrl(rootPath)
+const client = createClient(remote)
+
+// set CSRF token header
+const setHeaders = (token) => {
+ client.setHeaders({
+ // Add this so the server knows it is an request from the browser
+ 'X-Requested-With': 'XMLHttpRequest',
+ // Inject user auth
+ requesttoken: token ?? '',
+ })
+}
+
+// refresh headers when request token changes
+onRequestTokenUpdate(setHeaders)
+setHeaders(getRequestToken())
+
+export default client
diff --git a/apps/files_versions/src/utils/davRequest.js b/apps/files_versions/src/utils/davRequest.js
new file mode 100644
index 00000000000..1dcf620564a
--- /dev/null
+++ b/apps/files_versions/src/utils/davRequest.js
@@ -0,0 +1,20 @@
+/**
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+export default `<?xml version="1.0"?>
+<d:propfind xmlns:d="DAV:"
+ xmlns:oc="http://owncloud.org/ns"
+ xmlns:nc="http://nextcloud.org/ns"
+ xmlns:ocs="http://open-collaboration-services.org/ns">
+ <d:prop>
+ <d:getcontentlength />
+ <d:getcontenttype />
+ <d:getlastmodified />
+ <d:getetag />
+ <nc:version-label />
+ <nc:version-author />
+ <nc:has-preview />
+ </d:prop>
+</d:propfind>`
diff --git a/apps/files_versions/src/utils/logger.js b/apps/files_versions/src/utils/logger.js
new file mode 100644
index 00000000000..f84cb969244
--- /dev/null
+++ b/apps/files_versions/src/utils/logger.js
@@ -0,0 +1,11 @@
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { getLoggerBuilder } from '@nextcloud/logger'
+
+export default getLoggerBuilder()
+ .setApp('files_version')
+ .detectUser()
+ .build()
diff --git a/apps/files_versions/src/utils/versions.ts b/apps/files_versions/src/utils/versions.ts
new file mode 100644
index 00000000000..6d5933f0bd9
--- /dev/null
+++ b/apps/files_versions/src/utils/versions.ts
@@ -0,0 +1,133 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable jsdoc/require-param */
+/* eslint-disable jsdoc/require-jsdoc */
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+import type { FileStat, ResponseDataDetailed } from 'webdav'
+
+import { generateRemoteUrl, generateUrl } from '@nextcloud/router'
+import { getCurrentUser } from '@nextcloud/auth'
+import { joinPaths, encodePath } from '@nextcloud/paths'
+import moment from '@nextcloud/moment'
+
+import client from '../utils/davClient.js'
+import davRequest from '../utils/davRequest.js'
+import logger from '../utils/logger.js'
+
+export interface Version {
+ fileId: string, // The id of the file associated to the version.
+ label: string, // 'Current version' or ''
+ author: string|null, // UID for the author of the version
+ filename: string, // File name relative to the version DAV endpoint
+ basename: string, // A base name generated from the mtime
+ mime: string, // Empty for the current version, else the actual mime type of the version
+ etag: string, // Empty for the current version, else the actual mime type of the version
+ size: string, // Human readable size
+ type: string, // 'file'
+ mtime: number, // Version creation date as a timestamp
+ permissions: string, // Only readable: 'R'
+ previewUrl: string, // Preview URL of the version
+ url: string, // Download URL of the version
+ source: string, // The WebDAV endpoint of the ressource
+ fileVersion: string|null, // The version id, null for the current version
+}
+
+export async function fetchVersions(fileInfo: any): Promise<Version[]> {
+ const path = `/versions/${getCurrentUser()?.uid}/versions/${fileInfo.id}`
+
+ try {
+ const response = await client.getDirectoryContents(path, {
+ data: davRequest,
+ details: true,
+ }) as ResponseDataDetailed<FileStat[]>
+
+ return response.data
+ // Filter out root
+ .filter(({ mime }) => mime !== '')
+ .map(version => formatVersion(version, fileInfo))
+ } catch (exception) {
+ logger.error('Could not fetch version', { exception })
+ throw exception
+ }
+}
+
+/**
+ * Restore the given version
+ */
+export async function restoreVersion(version: Version) {
+ try {
+ logger.debug('Restoring version', { url: version.url })
+ await client.moveFile(
+ `/versions/${getCurrentUser()?.uid}/versions/${version.fileId}/${version.fileVersion}`,
+ `/versions/${getCurrentUser()?.uid}/restore/target`,
+ )
+ } catch (exception) {
+ logger.error('Could not restore version', { exception })
+ throw exception
+ }
+}
+
+/**
+ * Format version
+ */
+function formatVersion(version: any, fileInfo: any): Version {
+ const mtime = moment(version.lastmod).unix() * 1000
+ let previewUrl = ''
+
+ if (mtime === fileInfo.mtime) { // Version is the current one
+ previewUrl = generateUrl('/core/preview?fileId={fileId}&c={fileEtag}&x=250&y=250&forceIcon=0&a=0&forceIcon=1&mimeFallback=1', {
+ fileId: fileInfo.id,
+ fileEtag: fileInfo.etag,
+ })
+ } else {
+ previewUrl = generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}&mimeFallback=1', {
+ file: joinPaths(fileInfo.path, fileInfo.name),
+ fileVersion: version.basename,
+ })
+ }
+
+ return {
+ fileId: fileInfo.id,
+ // If version-label is defined make sure it is a string (prevent issue if the label is a number an PHP returns a number then)
+ label: version.props['version-label'] && String(version.props['version-label']),
+ author: version.props['version-author'] ?? null,
+ filename: version.filename,
+ basename: moment(mtime).format('LLL'),
+ mime: version.mime,
+ etag: `${version.props.getetag}`,
+ size: version.size,
+ type: version.type,
+ mtime,
+ permissions: 'R',
+ previewUrl,
+ url: joinPaths('/remote.php/dav', version.filename),
+ source: generateRemoteUrl('dav') + encodePath(version.filename),
+ fileVersion: version.basename,
+ }
+}
+
+export async function setVersionLabel(version: Version, newLabel: string) {
+ return await client.customRequest(
+ version.filename,
+ {
+ method: 'PROPPATCH',
+ data: `<?xml version="1.0"?>
+ <d:propertyupdate xmlns:d="DAV:"
+ xmlns:oc="http://owncloud.org/ns"
+ xmlns:nc="http://nextcloud.org/ns"
+ xmlns:ocs="http://open-collaboration-services.org/ns">
+ <d:set>
+ <d:prop>
+ <nc:version-label>${newLabel}</nc:version-label>
+ </d:prop>
+ </d:set>
+ </d:propertyupdate>`,
+ },
+ )
+}
+
+export async function deleteVersion(version: Version) {
+ await client.deleteFile(version.filename)
+}
diff --git a/apps/files_versions/src/versioncollection.js b/apps/files_versions/src/versioncollection.js
deleted file mode 100644
index 592b4f8cda2..00000000000
--- a/apps/files_versions/src/versioncollection.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-(function() {
- /**
- * @memberof OCA.Versions
- */
- const VersionCollection = OC.Backbone.Collection.extend({
- model: OCA.Versions.VersionModel,
- sync: OC.Backbone.davSync,
-
- /**
- * @member OCA.Files.FileInfoModel
- */
- _fileInfo: null,
-
- _currentUser: null,
-
- _client: null,
-
- setFileInfo(fileInfo) {
- this._fileInfo = fileInfo
- },
-
- getFileInfo() {
- return this._fileInfo
- },
-
- setCurrentUser(user) {
- this._currentUser = user
- },
-
- getCurrentUser() {
- return this._currentUser || OC.getCurrentUser().uid
- },
-
- setClient(client) {
- this._client = client
- },
-
- getClient() {
- return this._client || new OC.Files.Client({
- host: OC.getHost(),
- root: OC.linkToRemoteBase('dav') + '/versions/' + this.getCurrentUser(),
- useHTTPS: OC.getProtocol() === 'https',
- })
- },
-
- url() {
- return OC.linkToRemoteBase('dav') + '/versions/' + this.getCurrentUser() + '/versions/' + this._fileInfo.get('id')
- },
-
- parse(result) {
- const fullPath = this._fileInfo.getFullPath()
- const fileId = this._fileInfo.get('id')
- const name = this._fileInfo.get('name')
- const user = this.getCurrentUser()
- const client = this.getClient()
- return _.map(result, function(version) {
- version.fullPath = fullPath
- version.fileId = fileId
- version.name = name
- version.timestamp = parseInt(moment(new Date(version.timestamp)).format('X'), 10)
- version.id = OC.basename(version.href)
- version.size = parseInt(version.size, 10)
- version.user = user
- version.client = client
- return version
- })
- },
- })
-
- OCA.Versions = OCA.Versions || {}
-
- OCA.Versions.VersionCollection = VersionCollection
-})()
diff --git a/apps/files_versions/src/versionmodel.js b/apps/files_versions/src/versionmodel.js
deleted file mode 100644
index 01914f702e2..00000000000
--- a/apps/files_versions/src/versionmodel.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-(function() {
- /**
- * @memberof OCA.Versions
- */
- const VersionModel = OC.Backbone.Model.extend({
- sync: OC.Backbone.davSync,
-
- davProperties: {
- size: '{DAV:}getcontentlength',
- mimetype: '{DAV:}getcontenttype',
- timestamp: '{DAV:}getlastmodified',
- },
-
- /**
- * Restores the original file to this revision
- *
- * @param {object} [options] options
- * @return {Promise}
- */
- revert(options) {
- options = options ? _.clone(options) : {}
- const model = this
-
- const client = this.get('client')
-
- return client.move('/versions/' + this.get('fileId') + '/' + this.get('id'), '/restore/target', true)
- .done(function() {
- if (options.success) {
- options.success.call(options.context, model, {}, options)
- }
- model.trigger('revert', model, options)
- })
- .fail(function() {
- if (options.error) {
- options.error.call(options.context, model, {}, options)
- }
- model.trigger('error', model, {}, options)
- })
- },
-
- getFullPath() {
- return this.get('fullPath')
- },
-
- getPreviewUrl() {
- const url = OC.generateUrl('/apps/files_versions/preview')
- const params = {
- file: this.get('fullPath'),
- version: this.get('id'),
- }
- return url + '?' + OC.buildQueryString(params)
- },
-
- getDownloadUrl() {
- return OC.linkToRemoteBase('dav') + '/versions/' + this.get('user') + '/versions/' + this.get('fileId') + '/' + this.get('id')
- },
- })
-
- OCA.Versions = OCA.Versions || {}
-
- OCA.Versions.VersionModel = VersionModel
-})()
diff --git a/apps/files_versions/src/versionstabview.js b/apps/files_versions/src/versionstabview.js
deleted file mode 100644
index 9f76755a582..00000000000
--- a/apps/files_versions/src/versionstabview.js
+++ /dev/null
@@ -1,231 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Michael Jobst <mjobst+github@tecratech.de>
- * @author noveens <noveen.sachdeva@research.iiit.ac.in>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-import ItemTemplate from './templates/item.handlebars'
-import Template from './templates/template.handlebars';
-
-(function() {
- if (!OCA.Files.DetailTabView) {
- // Only register the versions tab within the files app
- return
- }
- /**
- * @memberof OCA.Versions
- */
- const VersionsTabView = OCA.Files.DetailTabView.extend(/** @lends OCA.Versions.VersionsTabView.prototype */{
- id: 'versionsTabView',
- className: 'tab versionsTabView',
-
- _template: null,
-
- $versionsContainer: null,
-
- events: {
- 'click .revertVersion': '_onClickRevertVersion',
- },
-
- initialize() {
- OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments)
- this.collection = new OCA.Versions.VersionCollection()
- this.collection.on('request', this._onRequest, this)
- this.collection.on('sync', this._onEndRequest, this)
- this.collection.on('update', this._onUpdate, this)
- this.collection.on('error', this._onError, this)
- this.collection.on('add', this._onAddModel, this)
- },
-
- getLabel() {
- return t('files_versions', 'Versions')
- },
-
- getIcon() {
- return 'icon-history'
- },
-
- nextPage() {
- if (this._loading) {
- return
- }
-
- if (this.collection.getFileInfo() && this.collection.getFileInfo().isDirectory()) {
- return
- }
- this.collection.fetch()
- },
-
- _onClickRevertVersion(ev) {
- const self = this
- let $target = $(ev.target)
- const fileInfoModel = this.collection.getFileInfo()
- if (!$target.is('li')) {
- $target = $target.closest('li')
- }
-
- ev.preventDefault()
- const revision = $target.attr('data-revision')
-
- const versionModel = this.collection.get(revision)
- versionModel.revert({
- success() {
- // reset and re-fetch the updated collection
- self.$versionsContainer.empty()
- self.collection.setFileInfo(fileInfoModel)
- self.collection.reset([], { silent: true })
- self.collection.fetch()
-
- self.$el.find('.versions').removeClass('hidden')
-
- // update original model
- fileInfoModel.trigger('busy', fileInfoModel, false)
- fileInfoModel.set({
- size: versionModel.get('size'),
- mtime: versionModel.get('timestamp') * 1000,
- // temp dummy, until we can do a PROPFIND
- etag: versionModel.get('id') + versionModel.get('timestamp'),
- })
- },
-
- error() {
- fileInfoModel.trigger('busy', fileInfoModel, false)
- self.$el.find('.versions').removeClass('hidden')
- self._toggleLoading(false)
- OC.Notification.show(t('files_version', 'Failed to revert {file} to revision {timestamp}.',
- {
- file: versionModel.getFullPath(),
- timestamp: OC.Util.formatDate(versionModel.get('timestamp') * 1000),
- }),
- {
- type: 'error',
- }
- )
- },
- })
-
- // spinner
- this._toggleLoading(true)
- fileInfoModel.trigger('busy', fileInfoModel, true)
- },
-
- _toggleLoading(state) {
- this._loading = state
- this.$el.find('.loading').toggleClass('hidden', !state)
- },
-
- _onRequest() {
- this._toggleLoading(true)
- },
-
- _onEndRequest() {
- this._toggleLoading(false)
- this.$el.find('.empty').toggleClass('hidden', !!this.collection.length)
- },
-
- _onAddModel(model) {
- const $el = $(this.itemTemplate(this._formatItem(model)))
- this.$versionsContainer.append($el)
- $el.find('.has-tooltip').tooltip()
- },
-
- template(data) {
- return Template(data)
- },
-
- itemTemplate(data) {
- return ItemTemplate(data)
- },
-
- setFileInfo(fileInfo) {
- if (fileInfo) {
- this.render()
- this.collection.setFileInfo(fileInfo)
- this.collection.reset([], { silent: true })
- this.nextPage()
- } else {
- this.render()
- this.collection.reset()
- }
- },
-
- _formatItem(version) {
- const timestamp = version.get('timestamp') * 1000
- const size = version.has('size') ? version.get('size') : 0
- const preview = OC.MimeType.getIconUrl(version.get('mimetype'))
- const img = new Image()
- img.onload = function() {
- $('li[data-revision=' + version.get('id') + '] .preview').attr('src', version.getPreviewUrl())
- }
- img.src = version.getPreviewUrl()
-
- return _.extend({
- versionId: version.get('id'),
- formattedTimestamp: OC.Util.formatDate(timestamp),
- relativeTimestamp: OC.Util.relativeModifiedDate(timestamp),
- millisecondsTimestamp: timestamp,
- humanReadableSize: OC.Util.humanFileSize(size, true),
- altSize: n('files', '%n byte', '%n bytes', size),
- hasDetails: version.has('size'),
- downloadUrl: version.getDownloadUrl(),
- downloadIconUrl: OC.imagePath('core', 'actions/download'),
- downloadName: version.get('name'),
- revertIconUrl: OC.imagePath('core', 'actions/history'),
- previewUrl: preview,
- revertLabel: t('files_versions', 'Restore'),
- canRevert: (this.collection.getFileInfo().get('permissions') & OC.PERMISSION_UPDATE) !== 0,
- }, version.attributes)
- },
-
- /**
- * Renders this details view
- */
- render() {
- this.$el.html(this.template({
- emptyResultLabel: t('files_versions', 'No other versions available'),
- }))
- this.$el.find('.has-tooltip').tooltip()
- this.$versionsContainer = this.$el.find('ul.versions')
- this.delegateEvents()
- },
-
- /**
- * Returns true for files, false for folders.
- *
- * @param {FileInfo} fileInfo fileInfo
- * @return {boolean} true for files, false for folders
- */
- canDisplay(fileInfo) {
- if (!fileInfo) {
- return false
- }
- return !fileInfo.isDirectory()
- },
- })
-
- OCA.Versions = OCA.Versions || {}
-
- OCA.Versions.VersionsTabView = VersionsTabView
-})()
diff --git a/apps/files_versions/src/views/VersionTab.vue b/apps/files_versions/src/views/VersionTab.vue
new file mode 100644
index 00000000000..a643aef439d
--- /dev/null
+++ b/apps/files_versions/src/views/VersionTab.vue
@@ -0,0 +1,307 @@
+<!--
+ - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<template>
+ <div class="versions-tab__container">
+ <VirtualScrolling v-slot="{ visibleSections }"
+ :sections="sections"
+ :header-height="0">
+ <ul :aria-label="t('files_versions', 'File versions')" data-files-versions-versions-list>
+ <template v-if="visibleSections.length === 1">
+ <Version v-for="(row) of visibleSections[0].rows"
+ :key="row.items[0].mtime"
+ :can-view="canView"
+ :can-compare="canCompare"
+ :load-preview="isActive"
+ :version="row.items[0]"
+ :file-info="fileInfo"
+ :is-current="row.items[0].mtime === fileInfo.mtime"
+ :is-first-version="row.items[0].mtime === initialVersionMtime"
+ @click="openVersion"
+ @compare="compareVersion"
+ @restore="handleRestore"
+ @label-update-request="handleLabelUpdateRequest(row.items[0])"
+ @delete="handleDelete" />
+ </template>
+ </ul>
+ <NcLoadingIcon v-if="loading" slot="loader" class="files-list-viewer__loader" />
+ </VirtualScrolling>
+ <VersionLabelDialog v-if="editedVersion"
+ :open.sync="showVersionLabelForm"
+ :version-label="editedVersion.label"
+ @label-update="handleLabelUpdate" />
+ </div>
+</template>
+
+<script>
+import path from 'path'
+
+import { getCurrentUser } from '@nextcloud/auth'
+import { showError, showSuccess } from '@nextcloud/dialogs'
+import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
+import { useIsMobile } from '@nextcloud/vue/composables/useIsMobile'
+import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
+
+import { fetchVersions, deleteVersion, restoreVersion, setVersionLabel } from '../utils/versions.ts'
+import Version from '../components/Version.vue'
+import VirtualScrolling from '../components/VirtualScrolling.vue'
+import VersionLabelDialog from '../components/VersionLabelDialog.vue'
+
+export default {
+ name: 'VersionTab',
+ components: {
+ Version,
+ VirtualScrolling,
+ VersionLabelDialog,
+ NcLoadingIcon,
+ },
+
+ setup() {
+ return {
+ isMobile: useIsMobile(),
+ }
+ },
+
+ data() {
+ return {
+ fileInfo: null,
+ isActive: false,
+ /** @type {import('../utils/versions.ts').Version[]} */
+ versions: [],
+ loading: false,
+ showVersionLabelForm: false,
+ editedVersion: null,
+ }
+ },
+ computed: {
+ sections() {
+ const rows = this.orderedVersions.map(version => ({ key: version.mtime, height: 68, sectionKey: 'versions', items: [version] }))
+ return [{ key: 'versions', rows, height: 68 * this.orderedVersions.length }]
+ },
+
+ /**
+ * Order versions by mtime.
+ * Put the current version at the top.
+ *
+ * @return {import('../utils/versions.ts').Version[]}
+ */
+ orderedVersions() {
+ return [...this.versions].sort((a, b) => {
+ if (a.mtime === this.fileInfo.mtime) {
+ return -1
+ } else if (b.mtime === this.fileInfo.mtime) {
+ return 1
+ } else {
+ return b.mtime - a.mtime
+ }
+ })
+ },
+
+ /**
+ * Return the mtime of the first version to display "Initial version" label
+ *
+ * @return {number}
+ */
+ initialVersionMtime() {
+ return this.versions
+ .map(version => version.mtime)
+ .reduce((a, b) => Math.min(a, b))
+ },
+
+ viewerFileInfo() {
+ // We need to remap bitmask to dav permissions as the file info we have is converted through client.js
+ let davPermissions = ''
+ if (this.fileInfo.permissions & 1) {
+ davPermissions += 'R'
+ }
+ if (this.fileInfo.permissions & 2) {
+ davPermissions += 'W'
+ }
+ if (this.fileInfo.permissions & 8) {
+ davPermissions += 'D'
+ }
+ return {
+ ...this.fileInfo,
+ mime: this.fileInfo.mimetype,
+ basename: this.fileInfo.name,
+ filename: this.fileInfo.path + '/' + this.fileInfo.name,
+ permissions: davPermissions,
+ fileid: this.fileInfo.id,
+ }
+ },
+
+ /** @return {boolean} */
+ canView() {
+ return window.OCA.Viewer?.mimetypesCompare?.includes(this.fileInfo.mimetype)
+ },
+
+ canCompare() {
+ return !this.isMobile
+ },
+ },
+ mounted() {
+ subscribe('files_versions:restore:restored', this.fetchVersions)
+ },
+ beforeUnmount() {
+ unsubscribe('files_versions:restore:restored', this.fetchVersions)
+ },
+ methods: {
+ /**
+ * Update current fileInfo and fetch new data
+ *
+ * @param {object} fileInfo the current file FileInfo
+ */
+ async update(fileInfo) {
+ this.fileInfo = fileInfo
+ this.resetState()
+ this.fetchVersions()
+ },
+
+ /**
+ * @param {boolean} isActive whether the tab is active
+ */
+ async setIsActive(isActive) {
+ this.isActive = isActive
+ },
+
+ /**
+ * Get the existing versions infos
+ */
+ async fetchVersions() {
+ try {
+ this.loading = true
+ this.versions = await fetchVersions(this.fileInfo)
+ } finally {
+ this.loading = false
+ }
+ },
+
+ /**
+ * Handle restored event from Version.vue
+ *
+ * @param {import('../utils/versions.ts').Version} version The version to restore
+ */
+ async handleRestore(version) {
+ // Update local copy of fileInfo as rendering depends on it.
+ const oldFileInfo = this.fileInfo
+ this.fileInfo = {
+ ...this.fileInfo,
+ size: version.size,
+ mtime: version.mtime,
+ }
+
+ const restoreStartedEventState = {
+ preventDefault: false,
+ fileInfo: this.fileInfo,
+ version,
+ }
+ emit('files_versions:restore:requested', restoreStartedEventState)
+ if (restoreStartedEventState.preventDefault) {
+ return
+ }
+
+ try {
+ await restoreVersion(version)
+ if (version.label) {
+ showSuccess(t('files_versions', `${version.label} restored`))
+ } else if (version.mtime === this.initialVersionMtime) {
+ showSuccess(t('files_versions', 'Initial version restored'))
+ } else {
+ showSuccess(t('files_versions', 'Version restored'))
+ }
+ emit('files_versions:restore:restored', version)
+ } catch (exception) {
+ this.fileInfo = oldFileInfo
+ showError(t('files_versions', 'Could not restore version'))
+ emit('files_versions:restore:failed', version)
+ }
+ },
+
+ /**
+ * Handle label-updated event from Version.vue
+ * @param {import('../utils/versions.ts').Version} version The version to update
+ */
+ handleLabelUpdateRequest(version) {
+ this.showVersionLabelForm = true
+ this.editedVersion = version
+ },
+
+ /**
+ * Handle label-updated event from Version.vue
+ * @param {string} newLabel The new label
+ */
+ async handleLabelUpdate(newLabel) {
+ const oldLabel = this.editedVersion.label
+ this.editedVersion.label = newLabel
+ this.showVersionLabelForm = false
+
+ try {
+ await setVersionLabel(this.editedVersion, newLabel)
+ this.editedVersion = null
+ } catch (exception) {
+ this.editedVersion.label = oldLabel
+ showError(this.t('files_versions', 'Could not set version label'))
+ logger.error('Could not set version label', { exception })
+ }
+ },
+
+ /**
+ * Handle deleted event from Version.vue
+ *
+ * @param {import('../utils/versions.ts').Version} version The version to delete
+ */
+ async handleDelete(version) {
+ const index = this.versions.indexOf(version)
+ this.versions.splice(index, 1)
+
+ try {
+ await deleteVersion(version)
+ } catch (exception) {
+ this.versions.push(version)
+ showError(t('files_versions', 'Could not delete version'))
+ }
+ },
+
+ /**
+ * Reset the current view to its default state
+ */
+ resetState() {
+ this.$set(this, 'versions', [])
+ },
+
+ openVersion({ version }) {
+ // Open current file view instead of read only
+ if (version.mtime === this.fileInfo.mtime) {
+ OCA.Viewer.open({ fileInfo: this.viewerFileInfo })
+ return
+ }
+
+ // Versions previews are too small for our use case, so we override previewUrl
+ // which makes the viewer render the original file.
+ // We also point to the original filename if the version is the current one.
+ const versions = this.versions.map(version => ({
+ ...version,
+ filename: version.mtime === this.fileInfo.mtime ? path.join('files', getCurrentUser()?.uid ?? '', this.fileInfo.path, this.fileInfo.name) : version.filename,
+ previewUrl: undefined,
+ }))
+
+ OCA.Viewer.open({
+ fileInfo: versions.find(v => v.source === version.source),
+ enableSidebar: false,
+ })
+ },
+
+ compareVersion({ version }) {
+ const versions = this.versions.map(version => ({ ...version, previewUrl: undefined }))
+
+ OCA.Viewer.compare(this.viewerFileInfo, versions.find(v => v.source === version.source))
+ },
+ },
+}
+</script>
+<style lang="scss">
+.versions-tab__container {
+ height: 100%;
+}
+</style>
diff --git a/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php b/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php
index a1acffb8543..21e88e86f90 100644
--- a/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php
+++ b/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php
@@ -1,53 +1,27 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright 2021 Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Tests\BackgroundJob;
use OCA\Files_Versions\BackgroundJob\ExpireVersions;
use OCA\Files_Versions\Expiration;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
-use OCP\ILogger;
use OCP\IUserManager;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ExpireVersionsTest extends TestCase {
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var Expiration|MockObject */
- private $expiration;
-
- /** @var IJobList|MockObject */
- private $jobList;
-
- /** @var ILogger|MockObject */
- private $logger;
+ private IConfig&MockObject $config;
+ private IUserManager&MockObject $userManager;
+ private Expiration&MockObject $expiration;
+ private IJobList&MockObject $jobList;
protected function setUp(): void {
parent::setUp();
@@ -56,7 +30,6 @@ class ExpireVersionsTest extends TestCase {
$this->userManager = $this->createMock(IUserManager::class);
$this->expiration = $this->createMock(Expiration::class);
$this->jobList = $this->createMock(IJobList::class);
- $this->logger = $this->createMock(ILogger::class);
$this->jobList->expects($this->once())
->method('setLastRun');
@@ -71,7 +44,12 @@ class ExpireVersionsTest extends TestCase {
$this->expiration->expects($this->never())
->method('getMaxAgeAsTimestamp');
- $job = new ExpireVersions($this->config, $this->userManager, $this->expiration);
- $job->execute($this->jobList, $this->logger);
+ $timeFactory = $this->createMock(ITimeFactory::class);
+ $timeFactory->method('getTime')
+ ->with()
+ ->willReturn(999999999);
+
+ $job = new ExpireVersions($this->config, $this->userManager, $this->expiration, $timeFactory);
+ $job->start($this->jobList);
}
}
diff --git a/apps/files_versions/tests/Command/CleanupTest.php b/apps/files_versions/tests/Command/CleanupTest.php
index b5463aa61db..dd6665f5aef 100644
--- a/apps/files_versions/tests/Command/CleanupTest.php
+++ b/apps/files_versions/tests/Command/CleanupTest.php
@@ -1,33 +1,22 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Tests\Command;
use OC\User\Manager;
use OCA\Files_Versions\Command\CleanUp;
+use OCA\Files_Versions\Db\VersionsMapper;
+use OCP\Files\Cache\ICache;
+use OCP\Files\Folder;
use OCP\Files\IRootFolder;
+use OCP\Files\Storage\IStorage;
+use OCP\UserInterface;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
/**
@@ -38,38 +27,46 @@ use Test\TestCase;
* @package OCA\Files_Versions\Tests\Command
*/
class CleanupTest extends TestCase {
-
- /** @var CleanUp */
- protected $cleanup;
-
- /** @var \PHPUnit\Framework\MockObject\MockObject | Manager */
- protected $userManager;
-
- /** @var \PHPUnit\Framework\MockObject\MockObject | IRootFolder */
- protected $rootFolder;
+ protected Manager&MockObject $userManager;
+ protected IRootFolder&MockObject $rootFolder;
+ protected VersionsMapper&MockObject $versionMapper;
+ protected CleanUp $cleanup;
protected function setUp(): void {
parent::setUp();
- $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')
- ->disableOriginalConstructor()->getMock();
- $this->userManager = $this->getMockBuilder('OC\User\Manager')
- ->disableOriginalConstructor()->getMock();
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+ $this->userManager = $this->createMock(Manager::class);
+ $this->versionMapper = $this->createMock(VersionsMapper::class);
-
- $this->cleanup = new CleanUp($this->rootFolder, $this->userManager);
+ $this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->versionMapper);
}
/**
- * @dataProvider dataTestDeleteVersions
* @param boolean $nodeExists
*/
- public function testDeleteVersions($nodeExists) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestDeleteVersions')]
+ public function testDeleteVersions(bool $nodeExists): void {
$this->rootFolder->expects($this->once())
->method('nodeExists')
->with('/testUser/files_versions')
->willReturn($nodeExists);
+ $userFolder = $this->createMock(Folder::class);
+ $userHomeStorage = $this->createMock(IStorage::class);
+ $userHomeStorageCache = $this->createMock(ICache::class);
+ $this->rootFolder->expects($this->once())
+ ->method('getUserFolder')
+ ->willReturn($userFolder);
+ $userFolder->expects($this->once())
+ ->method('getStorage')
+ ->willReturn($userHomeStorage);
+ $userHomeStorage->expects($this->once())
+ ->method('getCache')
+ ->willReturn($userHomeStorageCache);
+ $userHomeStorageCache->expects($this->once())
+ ->method('getNumericStorageId')
+ ->willReturn(1);
if ($nodeExists) {
$this->rootFolder->expects($this->once())
@@ -88,7 +85,7 @@ class CleanupTest extends TestCase {
$this->invokePrivate($this->cleanup, 'deleteVersions', ['testUser']);
}
- public function dataTestDeleteVersions() {
+ public static function dataTestDeleteVersions(): array {
return [
[true],
[false]
@@ -99,30 +96,28 @@ class CleanupTest extends TestCase {
/**
* test delete versions from users given as parameter
*/
- public function testExecuteDeleteListOfUsers() {
+ public function testExecuteDeleteListOfUsers(): void {
$userIds = ['user1', 'user2', 'user3'];
- $instance = $this->getMockBuilder('OCA\Files_Versions\Command\CleanUp')
- ->setMethods(['deleteVersions'])
- ->setConstructorArgs([$this->rootFolder, $this->userManager])
+ $instance = $this->getMockBuilder(CleanUp::class)
+ ->onlyMethods(['deleteVersions'])
+ ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper])
->getMock();
$instance->expects($this->exactly(count($userIds)))
->method('deleteVersions')
- ->willReturnCallback(function ($user) use ($userIds) {
+ ->willReturnCallback(function ($user) use ($userIds): void {
$this->assertTrue(in_array($user, $userIds));
});
$this->userManager->expects($this->exactly(count($userIds)))
->method('userExists')->willReturn(true);
- $inputInterface = $this->getMockBuilder('\Symfony\Component\Console\Input\InputInterface')
- ->disableOriginalConstructor()->getMock();
+ $inputInterface = $this->createMock(\Symfony\Component\Console\Input\InputInterface::class);
$inputInterface->expects($this->once())->method('getArgument')
->with('user_id')
->willReturn($userIds);
- $outputInterface = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')
- ->disableOriginalConstructor()->getMock();
+ $outputInterface = $this->createMock(\Symfony\Component\Console\Output\OutputInterface::class);
$this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
}
@@ -130,16 +125,16 @@ class CleanupTest extends TestCase {
/**
* test delete versions of all users
*/
- public function testExecuteAllUsers() {
+ public function testExecuteAllUsers(): void {
$userIds = [];
$backendUsers = ['user1', 'user2'];
- $instance = $this->getMockBuilder('OCA\Files_Versions\Command\CleanUp')
- ->setMethods(['deleteVersions'])
- ->setConstructorArgs([$this->rootFolder, $this->userManager])
+ $instance = $this->getMockBuilder(CleanUp::class)
+ ->onlyMethods(['deleteVersions'])
+ ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper])
->getMock();
- $backend = $this->getMockBuilder(\OCP\UserInterface::class)
+ $backend = $this->getMockBuilder(UserInterface::class)
->disableOriginalConstructor()->getMock();
$backend->expects($this->once())->method('getUsers')
->with('', 500, 0)
@@ -147,22 +142,20 @@ class CleanupTest extends TestCase {
$instance->expects($this->exactly(count($backendUsers)))
->method('deleteVersions')
- ->willReturnCallback(function ($user) use ($backendUsers) {
+ ->willReturnCallback(function ($user) use ($backendUsers): void {
$this->assertTrue(in_array($user, $backendUsers));
});
- $inputInterface = $this->getMockBuilder('\Symfony\Component\Console\Input\InputInterface')
- ->disableOriginalConstructor()->getMock();
+ $inputInterface = $this->createMock(\Symfony\Component\Console\Input\InputInterface::class);
$inputInterface->expects($this->once())->method('getArgument')
->with('user_id')
->willReturn($userIds);
- $outputInterface = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')
- ->disableOriginalConstructor()->getMock();
+ $outputInterface = $this->createMock(\Symfony\Component\Console\Output\OutputInterface::class);
$this->userManager->expects($this->once())
- ->method('getBackends')
- ->willReturn([$backend]);
+ ->method('getBackends')
+ ->willReturn([$backend]);
$this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
}
diff --git a/apps/files_versions/tests/Command/ExpireTest.php b/apps/files_versions/tests/Command/ExpireTest.php
index 9b0b68e71ea..b74457a7fd6 100644
--- a/apps/files_versions/tests/Command/ExpireTest.php
+++ b/apps/files_versions/tests/Command/ExpireTest.php
@@ -1,25 +1,10 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Tests\Command;
@@ -34,7 +19,7 @@ use Test\TestCase;
* @package OCA\Files_Versions\Tests\Command
*/
class ExpireTest extends TestCase {
- public function testExpireNonExistingUser() {
+ public function testExpireNonExistingUser(): void {
$command = new Expire($this->getUniqueID('test'), '');
$command->handle();
diff --git a/apps/files_versions/tests/Controller/PreviewControllerTest.php b/apps/files_versions/tests/Controller/PreviewControllerTest.php
index 0457d0d5f24..542ea2b6b34 100644
--- a/apps/files_versions/tests/Controller/PreviewControllerTest.php
+++ b/apps/files_versions/tests/Controller/PreviewControllerTest.php
@@ -1,37 +1,19 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
+
namespace OCA\Files_Versions\Tests\Controller;
use OCA\Files_Versions\Controller\PreviewController;
use OCA\Files_Versions\Versions\IVersionManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
-use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\Files\File;
use OCP\Files\Folder;
-use OCP\Files\IMimeTypeDetector;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
@@ -39,30 +21,19 @@ use OCP\IPreview;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
+use OCP\Preview\IMimeIconProvider;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class PreviewControllerTest extends TestCase {
+ private IRootFolder&MockObject $rootFolder;
+ private string $userId;
+ private IPreview&MockObject $previewManager;
+ private IUserSession&MockObject $userSession;
+ private IVersionManager&MockObject $versionManager;
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var string */
- private $userId;
-
- /** @var IMimeTypeDetector|\PHPUnit\Framework\MockObject\MockObject */
- private $mimeTypeDetector;
-
- /** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */
- private $previewManager;
-
- /** @var PreviewController|\PHPUnit\Framework\MockObject\MockObject */
- private $controller;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- private $userSession;
-
- /** @var IVersionManager|\PHPUnit\Framework\MockObject\MockObject */
- private $versionManager;
+ private IMimeIconProvider&MockObject $mimeIconProvider;
+ private PreviewController $controller;
protected function setUp(): void {
parent::setUp();
@@ -79,6 +50,7 @@ class PreviewControllerTest extends TestCase {
->method('getUser')
->willReturn($user);
$this->versionManager = $this->createMock(IVersionManager::class);
+ $this->mimeIconProvider = $this->createMock(IMimeIconProvider::class);
$this->controller = new PreviewController(
'files_versions',
@@ -86,39 +58,40 @@ class PreviewControllerTest extends TestCase {
$this->rootFolder,
$this->userSession,
$this->versionManager,
- $this->previewManager
+ $this->previewManager,
+ $this->mimeIconProvider,
);
}
- public function testInvalidFile() {
+ public function testInvalidFile(): void {
$res = $this->controller->getPreview('');
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
$this->assertEquals($expected, $res);
}
- public function testInvalidWidth() {
+ public function testInvalidWidth(): void {
$res = $this->controller->getPreview('file', 0);
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
$this->assertEquals($expected, $res);
}
- public function testInvalidHeight() {
+ public function testInvalidHeight(): void {
$res = $this->controller->getPreview('file', 10, 0);
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
$this->assertEquals($expected, $res);
}
- public function testInvalidVersion() {
+ public function testInvalidVersion(): void {
$res = $this->controller->getPreview('file', 10, 0);
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
$this->assertEquals($expected, $res);
}
- public function testValidPreview() {
+ public function testValidPreview(): void {
$userFolder = $this->createMock(Folder::class);
$userRoot = $this->createMock(Folder::class);
@@ -150,12 +123,13 @@ class PreviewControllerTest extends TestCase {
->willReturn('previewMime');
$res = $this->controller->getPreview('file', 10, 10, '42');
- $expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'previewMime']);
- $this->assertEquals($expected, $res);
+ $this->assertEquals('previewMime', $res->getHeaders()['Content-Type']);
+ $this->assertEquals(Http::STATUS_OK, $res->getStatus());
+ $this->assertEquals($preview, $this->invokePrivate($res, 'file'));
}
- public function testVersionNotFound() {
+ public function testVersionNotFound(): void {
$userFolder = $this->createMock(Folder::class);
$userRoot = $this->createMock(Folder::class);
diff --git a/apps/files_versions/tests/ExpirationTest.php b/apps/files_versions/tests/ExpirationTest.php
index 228d1d6830c..8cf412c3fe0 100644
--- a/apps/files_versions/tests/ExpirationTest.php
+++ b/apps/files_versions/tests/ExpirationTest.php
@@ -1,27 +1,10 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Tests;
@@ -34,7 +17,7 @@ use Psr\Log\LoggerInterface;
class ExpirationTest extends \Test\TestCase {
public const SECONDS_PER_DAY = 86400; //60*60*24
- public function expirationData() {
+ public static function expirationData(): array {
$today = 100 * self::SECONDS_PER_DAY;
$back10Days = (100 - 10) * self::SECONDS_PER_DAY;
$back20Days = (100 - 20) * self::SECONDS_PER_DAY;
@@ -98,16 +81,8 @@ class ExpirationTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider expirationData
- *
- * @param string $retentionObligation
- * @param int $timeNow
- * @param int $timestamp
- * @param bool $quotaExceeded
- * @param string $expectedResult
- */
- public function testExpiration($retentionObligation, $timeNow, $timestamp, $quotaExceeded, $expectedResult) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('expirationData')]
+ public function testExpiration(string $retentionObligation, int $timeNow, int $timestamp, bool $quotaExceeded, bool $expectedResult): void {
$mockedConfig = $this->getMockedConfig($retentionObligation);
$mockedTimeFactory = $this->getMockedTimeFactory($timeNow);
$mockedLogger = $this->createMock(LoggerInterface::class);
@@ -119,11 +94,7 @@ class ExpirationTest extends \Test\TestCase {
}
- /**
- * @param int $time
- * @return ITimeFactory|MockObject
- */
- private function getMockedTimeFactory($time) {
+ private function getMockedTimeFactory(int $time): ITimeFactory&MockObject {
$mockedTimeFactory = $this->createMock(ITimeFactory::class);
$mockedTimeFactory->expects($this->any())
->method('getTime')
@@ -132,11 +103,7 @@ class ExpirationTest extends \Test\TestCase {
return $mockedTimeFactory;
}
- /**
- * @param string $returnValue
- * @return IConfig|MockObject
- */
- private function getMockedConfig($returnValue) {
+ private function getMockedConfig(string $returnValue): IConfig&MockObject {
$mockedConfig = $this->createMock(IConfig::class);
$mockedConfig->expects($this->any())
->method('getSystemValue')
diff --git a/apps/files_versions/tests/StorageTest.php b/apps/files_versions/tests/StorageTest.php
index d16b9ecdfd8..443cff3ee06 100644
--- a/apps/files_versions/tests/StorageTest.php
+++ b/apps/files_versions/tests/StorageTest.php
@@ -2,32 +2,17 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\files_versions\tests;
use OCA\Files_Versions\Expiration;
-use OCA\Files_Versions\Hooks;
use OCA\Files_Versions\Storage;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
+use OCP\Server;
use Test\TestCase;
use Test\Traits\UserTrait;
@@ -39,7 +24,7 @@ class StorageTest extends TestCase {
private $versionsRoot;
private $userFolder;
- private $expireTimestamp = 10;
+ private int $expireTimestamp = 10;
protected function setUp(): void {
parent::setUp();
@@ -51,27 +36,27 @@ class StorageTest extends TestCase {
});
$this->overwriteService(Expiration::class, $expiration);
- Hooks::connectHooks();
+ \OC::$server->boot();
$this->createUser('version_test', '');
$this->loginAsUser('version_test');
/** @var IRootFolder $root */
- $root = \OC::$server->get(IRootFolder::class);
+ $root = Server::get(IRootFolder::class);
$this->userFolder = $root->getUserFolder('version_test');
}
- protected function createPastFile(string $path, int $mtime) {
+ protected function createPastFile(string $path, int $mtime): void {
try {
$file = $this->userFolder->get($path);
+ $file->putContent((string)$mtime);
} catch (NotFoundException $e) {
- $file = $this->userFolder->newFile($path);
+ $file = $this->userFolder->newFile($path, (string)$mtime);
}
- $file->putContent((string)$mtime);
$file->touch($mtime);
}
- public function testExpireMaxAge() {
+ public function testExpireMaxAge(): void {
$this->userFolder->newFolder('folder1');
$this->userFolder->newFolder('folder1/sub1');
$this->userFolder->newFolder('folder2');
diff --git a/apps/files_versions/tests/VersioningTest.php b/apps/files_versions/tests/VersioningTest.php
index 952298b3ef9..c9f7d27d7ab 100644
--- a/apps/files_versions/tests/VersioningTest.php
+++ b/apps/files_versions/tests/VersioningTest.php
@@ -1,43 +1,35 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Liam JACK <liamjack@users.noreply.github.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\Tests;
+use OC\AllConfig;
+use OC\Files\Cache\Watcher;
+use OC\Files\Filesystem;
use OC\Files\Storage\Temporary;
+use OC\Files\View;
+use OC\SystemConfig;
+use OC\User\NoUserException;
+use OCA\Files_Sharing\AppInfo\Application;
+use OCA\Files_Versions\Db\VersionEntity;
+use OCA\Files_Versions\Db\VersionsMapper;
+use OCA\Files_Versions\Events\VersionRestoredEvent;
+use OCA\Files_Versions\Storage;
+use OCA\Files_Versions\Versions\IVersionManager;
+use OCP\Constants;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\IMimeTypeLoader;
use OCP\IConfig;
use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Server;
use OCP\Share\IShare;
+use OCP\Util;
/**
* Class Test_Files_versions
@@ -51,16 +43,24 @@ class VersioningTest extends \Test\TestCase {
public const USERS_VERSIONS_ROOT = '/test-versions-user/files_versions';
/**
- * @var \OC\Files\View
+ * @var View
*/
private $rootView;
+ /**
+ * @var VersionsMapper
+ */
+ private $versionsMapper;
+ /**
+ * @var IMimeTypeLoader
+ */
+ private $mimeTypeLoader;
private $user1;
private $user2;
public static function setUpBeforeClass(): void {
parent::setUpBeforeClass();
- $application = new \OCA\Files_Sharing\AppInfo\Application();
+ $application = new Application();
// create test user
self::loginHelper(self::TEST_VERSIONS_USER2, true);
@@ -69,11 +69,11 @@ class VersioningTest extends \Test\TestCase {
public static function tearDownAfterClass(): void {
// cleanup test user
- $user = \OC::$server->getUserManager()->get(self::TEST_VERSIONS_USER);
+ $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER);
if ($user !== null) {
$user->delete();
}
- $user = \OC::$server->getUserManager()->get(self::TEST_VERSIONS_USER2);
+ $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER2);
if ($user !== null) {
$user->delete();
}
@@ -84,30 +84,36 @@ class VersioningTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $config = \OC::$server->getConfig();
- $mockConfig = $this->createMock(IConfig::class);
+ $config = Server::get(IConfig::class);
+ $mockConfig = $this->getMockBuilder(AllConfig::class)
+ ->onlyMethods(['getSystemValue'])
+ ->setConstructorArgs([Server::get(SystemConfig::class)])
+ ->getMock();
$mockConfig->expects($this->any())
->method('getSystemValue')
->willReturnCallback(function ($key, $default) use ($config) {
if ($key === 'filesystem_check_changes') {
- return \OC\Files\Cache\Watcher::CHECK_ONCE;
+ return Watcher::CHECK_ONCE;
} else {
return $config->getSystemValue($key, $default);
}
});
- $this->overwriteService(\OC\AllConfig::class, $mockConfig);
+ $this->overwriteService(AllConfig::class, $mockConfig);
// clear hooks
\OC_Hook::clear();
- \OC::registerShareHooks(\OC::$server->getSystemConfig());
- \OCA\Files_Versions\Hooks::connectHooks();
+ \OC::registerShareHooks(Server::get(SystemConfig::class));
+ \OC::$server->boot();
self::loginHelper(self::TEST_VERSIONS_USER);
- $this->rootView = new \OC\Files\View();
+ $this->rootView = new View();
if (!$this->rootView->file_exists(self::USERS_VERSIONS_ROOT)) {
$this->rootView->mkdir(self::USERS_VERSIONS_ROOT);
}
+ $this->versionsMapper = Server::get(VersionsMapper::class);
+ $this->mimeTypeLoader = Server::get(IMimeTypeLoader::class);
+
$this->user1 = $this->createMock(IUser::class);
$this->user1->method('getUID')
->willReturn(self::TEST_VERSIONS_USER);
@@ -117,7 +123,7 @@ class VersioningTest extends \Test\TestCase {
}
protected function tearDown(): void {
- $this->restoreService(\OC\AllConfig::class);
+ $this->restoreService(AllConfig::class);
if ($this->rootView) {
$this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files/');
@@ -134,9 +140,9 @@ class VersioningTest extends \Test\TestCase {
/**
* @medium
* test expire logic
- * @dataProvider versionsProvider
*/
- public function testGetExpireList($versions, $sizeOfAllDeletedFiles) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('versionsProvider')]
+ public function testGetExpireList($versions, $sizeOfAllDeletedFiles): void {
// last interval end at 2592000
$startTime = 5000000;
@@ -150,61 +156,61 @@ class VersioningTest extends \Test\TestCase {
// the deleted array should only contain versions which should be deleted
foreach ($deleted as $key => $path) {
unset($versions[$key]);
- $this->assertEquals("delete", substr($path, 0, strlen("delete")));
+ $this->assertEquals('delete', substr($path, 0, strlen('delete')));
}
// the versions array should only contain versions which should be kept
foreach ($versions as $version) {
- $this->assertEquals("keep", $version['path']);
+ $this->assertEquals('keep', $version['path']);
}
}
- public function versionsProvider() {
+ public static function versionsProvider(): array {
return [
// first set of versions uniformly distributed versions
[
[
// first slice (10sec) keep one version every 2 seconds
- ["version" => 4999999, "path" => "keep", "size" => 1],
- ["version" => 4999998, "path" => "delete", "size" => 1],
- ["version" => 4999997, "path" => "keep", "size" => 1],
- ["version" => 4999995, "path" => "keep", "size" => 1],
- ["version" => 4999994, "path" => "delete", "size" => 1],
+ ['version' => 4999999, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999998, 'path' => 'delete', 'size' => 1],
+ ['version' => 4999997, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999995, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999994, 'path' => 'delete', 'size' => 1],
//next slice (60sec) starts at 4999990 keep one version every 10 secons
- ["version" => 4999988, "path" => "keep", "size" => 1],
- ["version" => 4999978, "path" => "keep", "size" => 1],
- ["version" => 4999975, "path" => "delete", "size" => 1],
- ["version" => 4999972, "path" => "delete", "size" => 1],
- ["version" => 4999967, "path" => "keep", "size" => 1],
- ["version" => 4999958, "path" => "delete", "size" => 1],
- ["version" => 4999957, "path" => "keep", "size" => 1],
+ ['version' => 4999988, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999978, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999975, 'path' => 'delete', 'size' => 1],
+ ['version' => 4999972, 'path' => 'delete', 'size' => 1],
+ ['version' => 4999967, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999958, 'path' => 'delete', 'size' => 1],
+ ['version' => 4999957, 'path' => 'keep', 'size' => 1],
//next slice (3600sec) start at 4999940 keep one version every 60 seconds
- ["version" => 4999900, "path" => "keep", "size" => 1],
- ["version" => 4999841, "path" => "delete", "size" => 1],
- ["version" => 4999840, "path" => "keep", "size" => 1],
- ["version" => 4999780, "path" => "keep", "size" => 1],
- ["version" => 4996401, "path" => "keep", "size" => 1],
+ ['version' => 4999900, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999841, 'path' => 'delete', 'size' => 1],
+ ['version' => 4999840, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999780, 'path' => 'keep', 'size' => 1],
+ ['version' => 4996401, 'path' => 'keep', 'size' => 1],
// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
- ["version" => 4996350, "path" => "delete", "size" => 1],
- ["version" => 4992800, "path" => "keep", "size" => 1],
- ["version" => 4989800, "path" => "delete", "size" => 1],
- ["version" => 4989700, "path" => "delete", "size" => 1],
- ["version" => 4989200, "path" => "keep", "size" => 1],
+ ['version' => 4996350, 'path' => 'delete', 'size' => 1],
+ ['version' => 4992800, 'path' => 'keep', 'size' => 1],
+ ['version' => 4989800, 'path' => 'delete', 'size' => 1],
+ ['version' => 4989700, 'path' => 'delete', 'size' => 1],
+ ['version' => 4989200, 'path' => 'keep', 'size' => 1],
// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
- ["version" => 4913600, "path" => "keep", "size" => 1],
- ["version" => 4852800, "path" => "delete", "size" => 1],
- ["version" => 4827201, "path" => "delete", "size" => 1],
- ["version" => 4827200, "path" => "keep", "size" => 1],
- ["version" => 4777201, "path" => "delete", "size" => 1],
- ["version" => 4777501, "path" => "delete", "size" => 1],
- ["version" => 4740000, "path" => "keep", "size" => 1],
+ ['version' => 4913600, 'path' => 'keep', 'size' => 1],
+ ['version' => 4852800, 'path' => 'delete', 'size' => 1],
+ ['version' => 4827201, 'path' => 'delete', 'size' => 1],
+ ['version' => 4827200, 'path' => 'keep', 'size' => 1],
+ ['version' => 4777201, 'path' => 'delete', 'size' => 1],
+ ['version' => 4777501, 'path' => 'delete', 'size' => 1],
+ ['version' => 4740000, 'path' => 'keep', 'size' => 1],
// final slice starts at 2408000 keep one version every 604800 secons
- ["version" => 2408000, "path" => "keep", "size" => 1],
- ["version" => 1803201, "path" => "delete", "size" => 1],
- ["version" => 1803200, "path" => "keep", "size" => 1],
- ["version" => 1800199, "path" => "delete", "size" => 1],
- ["version" => 1800100, "path" => "delete", "size" => 1],
- ["version" => 1198300, "path" => "keep", "size" => 1],
+ ['version' => 2408000, 'path' => 'keep', 'size' => 1],
+ ['version' => 1803201, 'path' => 'delete', 'size' => 1],
+ ['version' => 1803200, 'path' => 'keep', 'size' => 1],
+ ['version' => 1800199, 'path' => 'delete', 'size' => 1],
+ ['version' => 1800100, 'path' => 'delete', 'size' => 1],
+ ['version' => 1198300, 'path' => 'keep', 'size' => 1],
],
16 // size of all deleted files (every file has the size 1)
],
@@ -215,28 +221,28 @@ class VersioningTest extends \Test\TestCase {
// next slice (60sec) starts at 4999990 keep one version every 10 secons
// next slice (3600sec) start at 4999940 keep one version every 60 seconds
// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
- ["version" => 4996400, "path" => "keep", "size" => 1],
- ["version" => 4996350, "path" => "delete", "size" => 1],
- ["version" => 4996350, "path" => "delete", "size" => 1],
- ["version" => 4992800, "path" => "keep", "size" => 1],
- ["version" => 4989800, "path" => "delete", "size" => 1],
- ["version" => 4989700, "path" => "delete", "size" => 1],
- ["version" => 4989200, "path" => "keep", "size" => 1],
+ ['version' => 4996400, 'path' => 'keep', 'size' => 1],
+ ['version' => 4996350, 'path' => 'delete', 'size' => 1],
+ ['version' => 4996350, 'path' => 'delete', 'size' => 1],
+ ['version' => 4992800, 'path' => 'keep', 'size' => 1],
+ ['version' => 4989800, 'path' => 'delete', 'size' => 1],
+ ['version' => 4989700, 'path' => 'delete', 'size' => 1],
+ ['version' => 4989200, 'path' => 'keep', 'size' => 1],
// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
- ["version" => 4913600, "path" => "keep", "size" => 1],
- ["version" => 4852800, "path" => "delete", "size" => 1],
- ["version" => 4827201, "path" => "delete", "size" => 1],
- ["version" => 4827200, "path" => "keep", "size" => 1],
- ["version" => 4777201, "path" => "delete", "size" => 1],
- ["version" => 4777501, "path" => "delete", "size" => 1],
- ["version" => 4740000, "path" => "keep", "size" => 1],
+ ['version' => 4913600, 'path' => 'keep', 'size' => 1],
+ ['version' => 4852800, 'path' => 'delete', 'size' => 1],
+ ['version' => 4827201, 'path' => 'delete', 'size' => 1],
+ ['version' => 4827200, 'path' => 'keep', 'size' => 1],
+ ['version' => 4777201, 'path' => 'delete', 'size' => 1],
+ ['version' => 4777501, 'path' => 'delete', 'size' => 1],
+ ['version' => 4740000, 'path' => 'keep', 'size' => 1],
// final slice starts at 2408000 keep one version every 604800 secons
- ["version" => 2408000, "path" => "keep", "size" => 1],
- ["version" => 1803201, "path" => "delete", "size" => 1],
- ["version" => 1803200, "path" => "keep", "size" => 1],
- ["version" => 1800199, "path" => "delete", "size" => 1],
- ["version" => 1800100, "path" => "delete", "size" => 1],
- ["version" => 1198300, "path" => "keep", "size" => 1],
+ ['version' => 2408000, 'path' => 'keep', 'size' => 1],
+ ['version' => 1803201, 'path' => 'delete', 'size' => 1],
+ ['version' => 1803200, 'path' => 'keep', 'size' => 1],
+ ['version' => 1800199, 'path' => 'delete', 'size' => 1],
+ ['version' => 1800100, 'path' => 'delete', 'size' => 1],
+ ['version' => 1198300, 'path' => 'keep', 'size' => 1],
],
11 // size of all deleted files (every file has the size 1)
],
@@ -244,32 +250,32 @@ class VersioningTest extends \Test\TestCase {
[
[
// first slice (10sec) keep one version every 2 seconds
- ["version" => 4999999, "path" => "keep", "size" => 1],
- ["version" => 4999998, "path" => "delete", "size" => 1],
- ["version" => 4999997, "path" => "keep", "size" => 1],
- ["version" => 4999995, "path" => "keep", "size" => 1],
- ["version" => 4999994, "path" => "delete", "size" => 1],
+ ['version' => 4999999, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999998, 'path' => 'delete', 'size' => 1],
+ ['version' => 4999997, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999995, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999994, 'path' => 'delete', 'size' => 1],
//next slice (60sec) starts at 4999990 keep one version every 10 secons
- ["version" => 4999988, "path" => "keep", "size" => 1],
- ["version" => 4999978, "path" => "keep", "size" => 1],
+ ['version' => 4999988, 'path' => 'keep', 'size' => 1],
+ ['version' => 4999978, 'path' => 'keep', 'size' => 1],
//next slice (3600sec) start at 4999940 keep one version every 60 seconds
// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
- ["version" => 4989200, "path" => "keep", "size" => 1],
+ ['version' => 4989200, 'path' => 'keep', 'size' => 1],
// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
- ["version" => 4913600, "path" => "keep", "size" => 1],
- ["version" => 4852800, "path" => "delete", "size" => 1],
- ["version" => 4827201, "path" => "delete", "size" => 1],
- ["version" => 4827200, "path" => "keep", "size" => 1],
- ["version" => 4777201, "path" => "delete", "size" => 1],
- ["version" => 4777501, "path" => "delete", "size" => 1],
- ["version" => 4740000, "path" => "keep", "size" => 1],
+ ['version' => 4913600, 'path' => 'keep', 'size' => 1],
+ ['version' => 4852800, 'path' => 'delete', 'size' => 1],
+ ['version' => 4827201, 'path' => 'delete', 'size' => 1],
+ ['version' => 4827200, 'path' => 'keep', 'size' => 1],
+ ['version' => 4777201, 'path' => 'delete', 'size' => 1],
+ ['version' => 4777501, 'path' => 'delete', 'size' => 1],
+ ['version' => 4740000, 'path' => 'keep', 'size' => 1],
// final slice starts at 2408000 keep one version every 604800 secons
- ["version" => 2408000, "path" => "keep", "size" => 1],
- ["version" => 1803201, "path" => "delete", "size" => 1],
- ["version" => 1803200, "path" => "keep", "size" => 1],
- ["version" => 1800199, "path" => "delete", "size" => 1],
- ["version" => 1800100, "path" => "delete", "size" => 1],
- ["version" => 1198300, "path" => "keep", "size" => 1],
+ ['version' => 2408000, 'path' => 'keep', 'size' => 1],
+ ['version' => 1803201, 'path' => 'delete', 'size' => 1],
+ ['version' => 1803200, 'path' => 'keep', 'size' => 1],
+ ['version' => 1800199, 'path' => 'delete', 'size' => 1],
+ ['version' => 1800100, 'path' => 'delete', 'size' => 1],
+ ['version' => 1198300, 'path' => 'keep', 'size' => 1],
],
9 // size of all deleted files (every file has the size 1)
],
@@ -282,8 +288,8 @@ class VersioningTest extends \Test\TestCase {
];
}
- public function testRename() {
- \OC\Files\Filesystem::file_put_contents("test.txt", "test file");
+ public function testRename(): void {
+ Filesystem::file_put_contents('test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -300,7 +306,7 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// execute rename hook of versions app
- \OC\Files\Filesystem::rename("test.txt", "test2.txt");
+ Filesystem::rename('test.txt', 'test2.txt');
$this->runCommands();
@@ -311,10 +317,10 @@ class VersioningTest extends \Test\TestCase {
$this->assertTrue($this->rootView->file_exists($v2Renamed), 'version 2 of renamed file exists');
}
- public function testRenameInSharedFolder() {
- \OC\Files\Filesystem::mkdir('folder1');
- \OC\Files\Filesystem::mkdir('folder1/folder2');
- \OC\Files\Filesystem::file_put_contents("folder1/test.txt", "test file");
+ public function testRenameInSharedFolder(): void {
+ Filesystem::mkdir('folder1');
+ Filesystem::mkdir('folder1/folder2');
+ Filesystem::file_put_contents('folder1/test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -332,21 +338,21 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_ALL);
- $share = \OC::$server->getShareManager()->createShare($share);
- \OC::$server->getShareManager()->acceptShare($share, self::TEST_VERSIONS_USER2);
+ ->setPermissions(Constants::PERMISSION_ALL);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
self::loginHelper(self::TEST_VERSIONS_USER2);
- $this->assertTrue(\OC\Files\Filesystem::file_exists('folder1/test.txt'));
+ $this->assertTrue(Filesystem::file_exists('folder1/test.txt'));
// execute rename hook of versions app
- \OC\Files\Filesystem::rename('/folder1/test.txt', '/folder1/folder2/test.txt');
+ Filesystem::rename('/folder1/test.txt', '/folder1/folder2/test.txt');
$this->runCommands();
@@ -358,13 +364,13 @@ class VersioningTest extends \Test\TestCase {
$this->assertTrue($this->rootView->file_exists($v1Renamed), 'version 1 of renamed file exists');
$this->assertTrue($this->rootView->file_exists($v2Renamed), 'version 2 of renamed file exists');
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
}
- public function testMoveFolder() {
- \OC\Files\Filesystem::mkdir('folder1');
- \OC\Files\Filesystem::mkdir('folder2');
- \OC\Files\Filesystem::file_put_contents('folder1/test.txt', 'test file');
+ public function testMoveFolder(): void {
+ Filesystem::mkdir('folder1');
+ Filesystem::mkdir('folder2');
+ Filesystem::file_put_contents('folder1/test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -382,7 +388,7 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// execute rename hook of versions app
- \OC\Files\Filesystem::rename('folder1', 'folder2/folder1');
+ Filesystem::rename('folder1', 'folder2/folder1');
$this->runCommands();
@@ -394,23 +400,23 @@ class VersioningTest extends \Test\TestCase {
}
- public function testMoveFileIntoSharedFolderAsRecipient() {
- \OC\Files\Filesystem::mkdir('folder1');
- $fileInfo = \OC\Files\Filesystem::getFileInfo('folder1');
+ public function testMoveFileIntoSharedFolderAsRecipient(): void {
+ Filesystem::mkdir('folder1');
+ $fileInfo = Filesystem::getFileInfo('folder1');
$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_ALL);
- $share = \OC::$server->getShareManager()->createShare($share);
- \OC::$server->getShareManager()->acceptShare($share, self::TEST_VERSIONS_USER2);
+ ->setPermissions(Constants::PERMISSION_ALL);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
self::loginHelper(self::TEST_VERSIONS_USER2);
$versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
- \OC\Files\Filesystem::file_put_contents('test.txt', 'test file');
+ Filesystem::file_put_contents('test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -426,8 +432,9 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// move file into the shared folder as recipient
- \OC\Files\Filesystem::rename('/test.txt', '/folder1/test.txt');
+ $success = Filesystem::rename('/test.txt', '/folder1/test.txt');
+ $this->assertTrue($success);
$this->assertFalse($this->rootView->file_exists($v1));
$this->assertFalse($this->rootView->file_exists($v2));
@@ -441,26 +448,26 @@ class VersioningTest extends \Test\TestCase {
$this->assertTrue($this->rootView->file_exists($v1Renamed));
$this->assertTrue($this->rootView->file_exists($v2Renamed));
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
}
- public function testMoveFolderIntoSharedFolderAsRecipient() {
- \OC\Files\Filesystem::mkdir('folder1');
+ public function testMoveFolderIntoSharedFolderAsRecipient(): void {
+ Filesystem::mkdir('folder1');
$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_ALL);
- $share = \OC::$server->getShareManager()->createShare($share);
- \OC::$server->getShareManager()->acceptShare($share, self::TEST_VERSIONS_USER2);
+ ->setPermissions(Constants::PERMISSION_ALL);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
self::loginHelper(self::TEST_VERSIONS_USER2);
$versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
- \OC\Files\Filesystem::mkdir('folder2');
- \OC\Files\Filesystem::file_put_contents('folder2/test.txt', 'test file');
+ Filesystem::mkdir('folder2');
+ Filesystem::file_put_contents('folder2/test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -477,7 +484,7 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// move file into the shared folder as recipient
- \OC\Files\Filesystem::rename('/folder2', '/folder1/folder2');
+ Filesystem::rename('/folder2', '/folder1/folder2');
$this->assertFalse($this->rootView->file_exists($v1));
$this->assertFalse($this->rootView->file_exists($v2));
@@ -492,11 +499,11 @@ class VersioningTest extends \Test\TestCase {
$this->assertTrue($this->rootView->file_exists($v1Renamed));
$this->assertTrue($this->rootView->file_exists($v2Renamed));
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
}
- public function testRenameSharedFile() {
- \OC\Files\Filesystem::file_put_contents("test.txt", "test file");
+ public function testRenameSharedFile(): void {
+ Filesystem::file_put_contents('test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -515,21 +522,21 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('test.txt');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE);
- $share = \OC::$server->getShareManager()->createShare($share);
- \OC::$server->getShareManager()->acceptShare($share, self::TEST_VERSIONS_USER2);
+ ->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE | Constants::PERMISSION_SHARE);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
self::loginHelper(self::TEST_VERSIONS_USER2);
- $this->assertTrue(\OC\Files\Filesystem::file_exists('test.txt'));
+ $this->assertTrue(Filesystem::file_exists('test.txt'));
// execute rename hook of versions app
- \OC\Files\Filesystem::rename('test.txt', 'test2.txt');
+ Filesystem::rename('test.txt', 'test2.txt');
self::loginHelper(self::TEST_VERSIONS_USER);
@@ -541,11 +548,11 @@ class VersioningTest extends \Test\TestCase {
$this->assertFalse($this->rootView->file_exists($v1Renamed));
$this->assertFalse($this->rootView->file_exists($v2Renamed));
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
}
- public function testCopy() {
- \OC\Files\Filesystem::file_put_contents("test.txt", "test file");
+ public function testCopy(): void {
+ Filesystem::file_put_contents('test.txt', 'test file');
$t1 = time();
// second version is two weeks older, this way we make sure that no
@@ -562,7 +569,7 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// execute copy hook of versions app
- \OC\Files\Filesystem::copy("test.txt", "test2.txt");
+ Filesystem::copy('test.txt', 'test2.txt');
$this->runCommands();
@@ -577,7 +584,7 @@ class VersioningTest extends \Test\TestCase {
* test if we find all versions and if the versions array contain
* the correct 'path' and 'name'
*/
- public function testGetVersions() {
+ public function testGetVersions(): void {
$t1 = time();
// second version is two weeks older, this way we make sure that no
// version will be expired
@@ -593,7 +600,7 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// execute copy hook of versions app
- $versions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, '/subfolder/test.txt');
+ $versions = Storage::getVersions(self::TEST_VERSIONS_USER, '/subfolder/test.txt');
$this->assertCount(2, $versions);
@@ -610,65 +617,65 @@ class VersioningTest extends \Test\TestCase {
* test if we find all versions and if the versions array contain
* the correct 'path' and 'name'
*/
- public function testGetVersionsEmptyFile() {
+ public function testGetVersionsEmptyFile(): void {
// execute copy hook of versions app
- $versions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, '');
+ $versions = Storage::getVersions(self::TEST_VERSIONS_USER, '');
$this->assertCount(0, $versions);
- $versions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, null);
+ $versions = Storage::getVersions(self::TEST_VERSIONS_USER, null);
$this->assertCount(0, $versions);
}
- public function testExpireNonexistingFile() {
+ public function testExpireNonexistingFile(): void {
$this->logout();
// needed to have a FS setup (the background job does this)
\OC_Util::setupFS(self::TEST_VERSIONS_USER);
- $this->assertFalse(\OCA\Files_Versions\Storage::expire('/void/unexist.txt', self::TEST_VERSIONS_USER));
+ $this->assertFalse(Storage::expire('/void/unexist.txt', self::TEST_VERSIONS_USER));
}
- public function testExpireNonexistingUser() {
- $this->expectException(\OC\User\NoUserException::class);
+ public function testExpireNonexistingUser(): void {
+ $this->expectException(NoUserException::class);
$this->logout();
// needed to have a FS setup (the background job does this)
\OC_Util::setupFS(self::TEST_VERSIONS_USER);
- \OC\Files\Filesystem::file_put_contents("test.txt", "test file");
+ Filesystem::file_put_contents('test.txt', 'test file');
- $this->assertFalse(\OCA\Files_Versions\Storage::expire('test.txt', 'unexist'));
+ $this->assertFalse(Storage::expire('test.txt', 'unexist'));
}
- public function testRestoreSameStorage() {
- \OC\Files\Filesystem::mkdir('sub');
+ public function testRestoreSameStorage(): void {
+ Filesystem::mkdir('sub');
$this->doTestRestore();
}
- public function testRestoreCrossStorage() {
+ public function testRestoreCrossStorage(): void {
$storage2 = new Temporary([]);
- \OC\Files\Filesystem::mount($storage2, [], self::TEST_VERSIONS_USER . '/files/sub');
+ Filesystem::mount($storage2, [], self::TEST_VERSIONS_USER . '/files/sub');
$this->doTestRestore();
}
- public function testRestoreNoPermission() {
+ public function testRestoreNoPermission(): void {
$this->loginAsUser(self::TEST_VERSIONS_USER);
$userHome = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER);
$node = $userHome->newFolder('folder');
$file = $node->newFile('test.txt');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_READ);
- $share = \OC::$server->getShareManager()->createShare($share);
- \OC::$server->getShareManager()->acceptShare($share, self::TEST_VERSIONS_USER2);
+ ->setPermissions(Constants::PERMISSION_READ);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
$versions = $this->createAndCheckVersions(
- \OC\Files\Filesystem::getView(),
+ Filesystem::getView(),
'folder/test.txt'
);
@@ -678,15 +685,15 @@ class VersioningTest extends \Test\TestCase {
$firstVersion = current($versions);
- $this->assertFalse(\OCA\Files_Versions\Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user2), 'Revert did not happen');
+ $this->assertFalse(Storage::rollback('folder/test.txt', (int)$firstVersion['version'], $this->user2), 'Revert did not happen');
$this->loginAsUser(self::TEST_VERSIONS_USER);
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
$this->assertEquals('test file', $file->getContent(), 'File content has not changed');
}
- public function testRestoreMovedShare() {
+ public function testRestoreMovedShare(): void {
$this->markTestSkipped('Unreliable test');
$this->loginAsUser(self::TEST_VERSIONS_USER);
@@ -697,21 +704,21 @@ class VersioningTest extends \Test\TestCase {
$userHome2 = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER2);
$userHome2->newFolder('subfolder');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_ALL);
- $share = \OC::$server->getShareManager()->createShare($share);
- $shareManager = \OC::$server->getShareManager();
+ ->setPermissions(Constants::PERMISSION_ALL);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ $shareManager = Server::get(\OCP\Share\IManager::class);
$shareManager->acceptShare($share, self::TEST_VERSIONS_USER2);
- $share->setTarget("subfolder/folder");
+ $share->setTarget('subfolder/folder');
$shareManager->moveShare($share, self::TEST_VERSIONS_USER2);
$versions = $this->createAndCheckVersions(
- \OC\Files\Filesystem::getView(),
+ Filesystem::getView(),
'folder/test.txt'
);
@@ -721,11 +728,11 @@ class VersioningTest extends \Test\TestCase {
$firstVersion = current($versions);
- $this->assertTrue(\OCA\Files_Versions\Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user1));
+ $this->assertTrue(Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user1));
$this->loginAsUser(self::TEST_VERSIONS_USER);
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
$this->assertEquals('version 2', $file->getContent(), 'File content has not changed');
}
@@ -738,19 +745,19 @@ class VersioningTest extends \Test\TestCase {
return;
}
- $eventHandler = $this->getMockBuilder(\stdclass::class)
- ->setMethods(['callback'])
+ $eventHandler = $this->getMockBuilder(DummyHookListener::class)
+ ->onlyMethods(['callback'])
->getMock();
$eventHandler->expects($this->any())
->method('callback')
->willReturnCallback(
- function ($p) use (&$params) {
+ function ($p) use (&$params): void {
$params = $p;
}
);
- \OCP\Util::connectHook(
+ Util::connectHook(
'\OCP\Versions',
$hookName,
$eventHandler,
@@ -758,10 +765,11 @@ class VersioningTest extends \Test\TestCase {
);
}
- private function doTestRestore() {
+ private function doTestRestore(): void {
$filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt';
$this->rootView->file_put_contents($filePath, 'test file');
+ $fileInfo = $this->rootView->getFileInfo($filePath);
$t0 = $this->rootView->filemtime($filePath);
// not exactly the same timestamp as the file
@@ -774,10 +782,28 @@ class VersioningTest extends \Test\TestCase {
$v2 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t2;
$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/sub');
+
$this->rootView->file_put_contents($v1, 'version1');
- $this->rootView->file_put_contents($v2, 'version2');
+ $fileInfoV1 = $this->rootView->getFileInfo($v1);
+ $versionEntity = new VersionEntity();
+ $versionEntity->setFileId($fileInfo->getId());
+ $versionEntity->setTimestamp($t1);
+ $versionEntity->setSize($fileInfoV1->getSize());
+ $versionEntity->setMimetype($this->mimeTypeLoader->getId($fileInfoV1->getMimetype()));
+ $versionEntity->setMetadata([]);
+ $this->versionsMapper->insert($versionEntity);
- $oldVersions = \OCA\Files_Versions\Storage::getVersions(
+ $this->rootView->file_put_contents($v2, 'version2');
+ $fileInfoV2 = $this->rootView->getFileInfo($v2);
+ $versionEntity = new VersionEntity();
+ $versionEntity->setFileId($fileInfo->getId());
+ $versionEntity->setTimestamp($t2);
+ $versionEntity->setSize($fileInfoV2->getSize());
+ $versionEntity->setMimetype($this->mimeTypeLoader->getId($fileInfoV2->getMimetype()));
+ $versionEntity->setMetadata([]);
+ $this->versionsMapper->insert($versionEntity);
+
+ $oldVersions = Storage::getVersions(
self::TEST_VERSIONS_USER, '/sub/test.txt'
);
@@ -786,17 +812,22 @@ class VersioningTest extends \Test\TestCase {
$this->assertEquals('test file', $this->rootView->file_get_contents($filePath));
$info1 = $this->rootView->getFileInfo($filePath);
- $params = [];
- $this->connectMockHooks('rollback', $params);
+ $eventDispatcher = Server::get(IEventDispatcher::class);
+ $eventFired = false;
+ $eventDispatcher->addListener(VersionRestoredEvent::class, function ($event) use (&$eventFired, $t2): void {
+ $eventFired = true;
+ $this->assertEquals('/sub/test.txt', $event->getVersion()->getVersionPath());
+ $this->assertTrue($event->getVersion()->getRevisionId() > 0);
+ });
- $this->assertTrue(\OCA\Files_Versions\Storage::rollback('sub/test.txt', $t2, $this->user1));
- $expectedParams = [
- 'path' => '/sub/test.txt',
- ];
+ $versionManager = Server::get(IVersionManager::class);
+ $versions = $versionManager->getVersionsForFile($this->user1, $info1);
+ $version = array_filter($versions, function ($version) use ($t2) {
+ return $version->getRevisionId() === $t2;
+ });
+ $this->assertTrue($versionManager->rollback(current($version)));
- $this->assertEquals($expectedParams['path'], $params['path']);
- $this->assertTrue(array_key_exists('revision', $params));
- $this->assertTrue($params['revision'] > 0);
+ $this->assertTrue($eventFired, 'VersionRestoredEvent was not fired');
$this->assertEquals('version2', $this->rootView->file_get_contents($filePath));
$info2 = $this->rootView->getFileInfo($filePath);
@@ -817,7 +848,7 @@ class VersioningTest extends \Test\TestCase {
'Restored file has mtime from version'
);
- $newVersions = \OCA\Files_Versions\Storage::getVersions(
+ $newVersions = Storage::getVersions(
self::TEST_VERSIONS_USER, '/sub/test.txt'
);
@@ -853,11 +884,11 @@ class VersioningTest extends \Test\TestCase {
/**
* Test whether versions are created when overwriting as owner
*/
- public function testStoreVersionAsOwner() {
+ public function testStoreVersionAsOwner(): void {
$this->loginAsUser(self::TEST_VERSIONS_USER);
$this->createAndCheckVersions(
- \OC\Files\Filesystem::getView(),
+ Filesystem::getView(),
'test.txt'
);
}
@@ -865,30 +896,30 @@ class VersioningTest extends \Test\TestCase {
/**
* Test whether versions are created when overwriting as share recipient
*/
- public function testStoreVersionAsRecipient() {
+ public function testStoreVersionAsRecipient(): void {
$this->loginAsUser(self::TEST_VERSIONS_USER);
- \OC\Files\Filesystem::mkdir('folder');
- \OC\Files\Filesystem::file_put_contents('folder/test.txt', 'test file');
+ Filesystem::mkdir('folder');
+ Filesystem::file_put_contents('folder/test.txt', 'test file');
$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder');
- $share = \OC::$server->getShareManager()->newShare();
+ $share = Server::get(\OCP\Share\IManager::class)->newShare();
$share->setNode($node)
->setShareType(IShare::TYPE_USER)
->setSharedBy(self::TEST_VERSIONS_USER)
->setSharedWith(self::TEST_VERSIONS_USER2)
- ->setPermissions(\OCP\Constants::PERMISSION_ALL);
- $share = \OC::$server->getShareManager()->createShare($share);
- \OC::$server->getShareManager()->acceptShare($share, self::TEST_VERSIONS_USER2);
+ ->setPermissions(Constants::PERMISSION_ALL);
+ $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
+ Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
$this->loginAsUser(self::TEST_VERSIONS_USER2);
$this->createAndCheckVersions(
- \OC\Files\Filesystem::getView(),
+ Filesystem::getView(),
'folder/test.txt'
);
- \OC::$server->getShareManager()->deleteShare($share);
+ Server::get(\OCP\Share\IManager::class)->deleteShare($share);
}
/**
@@ -898,25 +929,21 @@ class VersioningTest extends \Test\TestCase {
* is logged in. File modification must still be able to find
* the owner and create versions.
*/
- public function testStoreVersionAsAnonymous() {
+ public function testStoreVersionAsAnonymous(): void {
$this->logout();
// note: public link upload does this,
// needed to make the hooks fire
\OC_Util::setupFS(self::TEST_VERSIONS_USER);
- $userView = new \OC\Files\View('/' . self::TEST_VERSIONS_USER . '/files');
+ $userView = new View('/' . self::TEST_VERSIONS_USER . '/files');
$this->createAndCheckVersions(
$userView,
'test.txt'
);
}
- /**
- * @param \OC\Files\View $view
- * @param string $path
- */
- private function createAndCheckVersions(\OC\Files\View $view, $path) {
+ private function createAndCheckVersions(View $view, string $path): array {
$view->file_put_contents($path, 'test file');
$view->file_put_contents($path, 'version 1');
$view->file_put_contents($path, 'version 2');
@@ -927,7 +954,7 @@ class VersioningTest extends \Test\TestCase {
[$rootStorage,] = $this->rootView->resolvePath(self::TEST_VERSIONS_USER . '/files_versions');
$rootStorage->getScanner()->scan('files_versions');
- $versions = \OCA\Files_Versions\Storage::getVersions(
+ $versions = Storage::getVersions(
self::TEST_VERSIONS_USER, '/' . $path
);
@@ -938,34 +965,29 @@ class VersioningTest extends \Test\TestCase {
return $versions;
}
- /**
- * @param string $user
- * @param bool $create
- */
- public static function loginHelper($user, $create = false) {
+ public static function loginHelper(string $user, bool $create = false) {
if ($create) {
$backend = new \Test\Util\User\Dummy();
$backend->createUser($user, $user);
- \OC::$server->getUserManager()->registerBackend($backend);
+ Server::get(IUserManager::class)->registerBackend($backend);
}
- $storage = new \ReflectionClass('\OCA\Files_Sharing\SharedStorage');
- $isInitialized = $storage->getProperty('initialized');
- $isInitialized->setAccessible(true);
- $isInitialized->setValue($storage, false);
- $isInitialized->setAccessible(false);
-
\OC_Util::tearDownFS();
\OC_User::setUserId('');
- \OC\Files\Filesystem::tearDown();
+ Filesystem::tearDown();
\OC_User::setUserId($user);
\OC_Util::setupFS($user);
\OC::$server->getUserFolder($user);
}
}
+class DummyHookListener {
+ public function callback() {
+ }
+}
+
// extend the original class to make it possible to test protected methods
-class VersionStorageToTest extends \OCA\Files_Versions\Storage {
+class VersionStorageToTest extends Storage {
/**
* @param integer $time
diff --git a/apps/files_versions/tests/Versions/VersionManagerTest.php b/apps/files_versions/tests/Versions/VersionManagerTest.php
index f3eb1ee3e4d..79caa65d5f1 100644
--- a/apps/files_versions/tests/Versions/VersionManagerTest.php
+++ b/apps/files_versions/tests/Versions/VersionManagerTest.php
@@ -3,32 +3,19 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
- *
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @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 <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\files_versions\tests\Versions;
+namespace OCA\Files_Versions\Tests\Versions;
use OC\Files\Storage\Local;
+use OCA\Files_Versions\Events\VersionRestoredEvent;
+use OCA\Files_Versions\Versions\IVersion;
use OCA\Files_Versions\Versions\IVersionBackend;
use OCA\Files_Versions\Versions\VersionManager;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Storage\IStorage;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class VersionManagerTest extends TestCase {
@@ -39,23 +26,25 @@ class VersionManagerTest extends TestCase {
return $backend;
}
- private function getStorage(string $class): IStorage {
+ private function getStorage(string $class): IStorage&MockObject {
return $this->getMockBuilder($class)
->disableOriginalConstructor()
- ->setMethodsExcept(['instanceOfStorage'])
+ ->onlyMethods(array_diff(get_class_methods($class), ['instanceOfStorage']))
->getMock();
}
- public function testGetBackendSingle() {
- $manager = new VersionManager();
+ public function testGetBackendSingle(): void {
+ $dispatcher = $this->createMock(IEventDispatcher::class);
+ $manager = new VersionManager($dispatcher);
$backend = $this->getBackend();
$manager->registerBackend(IStorage::class, $backend);
$this->assertEquals($backend, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
- public function testGetBackendMoreSpecific() {
- $manager = new VersionManager();
+ public function testGetBackendMoreSpecific(): void {
+ $dispatcher = $this->createMock(IEventDispatcher::class);
+ $manager = new VersionManager($dispatcher);
$backend1 = $this->getBackend();
$backend2 = $this->getBackend();
$manager->registerBackend(IStorage::class, $backend1);
@@ -64,8 +53,9 @@ class VersionManagerTest extends TestCase {
$this->assertEquals($backend2, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
- public function testGetBackendNoUse() {
- $manager = new VersionManager();
+ public function testGetBackendNoUse(): void {
+ $dispatcher = $this->createMock(IEventDispatcher::class);
+ $manager = new VersionManager($dispatcher);
$backend1 = $this->getBackend();
$backend2 = $this->getBackend(false);
$manager->registerBackend(IStorage::class, $backend1);
@@ -74,8 +64,9 @@ class VersionManagerTest extends TestCase {
$this->assertEquals($backend1, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
- public function testGetBackendMultiple() {
- $manager = new VersionManager();
+ public function testGetBackendMultiple(): void {
+ $dispatcher = $this->createMock(IEventDispatcher::class);
+ $manager = new VersionManager($dispatcher);
$backend1 = $this->getBackend();
$backend2 = $this->getBackend(false);
$backend3 = $this->getBackend();
@@ -85,4 +76,65 @@ class VersionManagerTest extends TestCase {
$this->assertEquals($backend3, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
+
+ public function testRollbackSuccess(): void {
+ $versionMock = $this->createMock(IVersion::class);
+ $backendMock = $this->createMock(IVersionBackend::class);
+
+ $backendMock->expects($this->once())
+ ->method('rollback')
+ ->with($versionMock)
+ ->willReturn(true);
+
+ $versionMock->method('getBackend')->willReturn($backendMock);
+
+ $dispatcherMock = $this->createMock(IEventDispatcher::class);
+ $dispatcherMock->expects($this->once())
+ ->method('dispatchTyped')
+ ->with($this->isInstanceOf(VersionRestoredEvent::class));
+
+ $manager = new VersionManager($dispatcherMock);
+
+ $this->assertTrue($manager->rollback($versionMock));
+ }
+
+ public function testRollbackNull(): void {
+ $versionMock = $this->createMock(IVersion::class);
+ $backendMock = $this->createMock(IVersionBackend::class);
+
+ $backendMock->expects($this->once())
+ ->method('rollback')
+ ->with($versionMock)
+ ->willReturn(null);
+
+ $versionMock->method('getBackend')->willReturn($backendMock);
+
+ $dispatcherMock = $this->createMock(IEventDispatcher::class);
+ $dispatcherMock->expects($this->once())
+ ->method('dispatchTyped')
+ ->with($this->isInstanceOf(VersionRestoredEvent::class));
+
+ $manager = new VersionManager($dispatcherMock);
+
+ $this->assertNull($manager->rollback($versionMock));
+ }
+
+ public function testRollbackFailure(): void {
+ $versionMock = $this->createMock(IVersion::class);
+ $backendMock = $this->createMock(IVersionBackend::class);
+
+ $backendMock->expects($this->once())
+ ->method('rollback')
+ ->with($versionMock)
+ ->willReturn(false);
+
+ $versionMock->method('getBackend')->willReturn($backendMock);
+
+ $dispatcherMock = $this->createMock(IEventDispatcher::class);
+ $dispatcherMock->expects($this->never())->method('dispatchTyped');
+
+ $manager = new VersionManager($dispatcherMock);
+
+ $this->assertFalse($manager->rollback($versionMock));
+ }
}
diff --git a/apps/files_versions/tests/js/versioncollectionSpec.js b/apps/files_versions/tests/js/versioncollectionSpec.js
deleted file mode 100644
index 672515146b7..00000000000
--- a/apps/files_versions/tests/js/versioncollectionSpec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-describe('OCA.Versions.VersionCollection', function() {
- var VersionCollection = OCA.Versions.VersionCollection;
- var collection, fileInfoModel;
-
- beforeEach(function() {
- fileInfoModel = new OCA.Files.FileInfoModel({
- path: '/subdir',
- name: 'some file.txt',
- id: 10,
- });
- collection = new VersionCollection();
- collection.setFileInfo(fileInfoModel);
- collection.setCurrentUser('user');
- });
- it('fetches the versions', function() {
- collection.fetch();
-
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].url).toEqual(
- OC.linkToRemoteBase('dav') + '/versions/user/versions/10'
- );
- fakeServer.requests[0].respond(200);
- });
-});
-
diff --git a/apps/files_versions/tests/js/versionmodelSpec.js b/apps/files_versions/tests/js/versionmodelSpec.js
deleted file mode 100644
index d4b7bec43ae..00000000000
--- a/apps/files_versions/tests/js/versionmodelSpec.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-describe('OCA.Versions.VersionModel', function() {
- var VersionModel = OCA.Versions.VersionModel;
- var model;
- var uid = OC.currentUser = 'user';
-
- beforeEach(function() {
- model = new VersionModel({
- id: 10000000,
- fileId: 10,
- timestamp: 10000000,
- fullPath: '/subdir/some file.txt',
- name: 'some file.txt',
- size: 150,
- user: 'user',
- client: new OC.Files.Client({
- host: 'localhost',
- port: 80,
- root: '/remote.php/dav/versions/user',
- useHTTPS: OC.getProtocol() === 'https'
- })
- });
- });
-
- it('returns the full path', function() {
- expect(model.getFullPath()).toEqual('/subdir/some file.txt');
- });
- it('returns the preview url', function() {
- expect(model.getPreviewUrl())
- .toEqual(OC.generateUrl('/apps/files_versions/preview') +
- '?file=%2Fsubdir%2Fsome%20file.txt&version=10000000'
- );
- });
- it('returns the download url', function() {
- expect(model.getDownloadUrl())
- .toEqual(OC.linkToRemoteBase('dav') + '/versions/' + uid +
- '/versions/10/10000000'
- );
- });
- describe('reverting', function() {
- var revertEventStub;
- var successStub;
- var errorStub;
-
- beforeEach(function() {
- revertEventStub = sinon.stub();
- errorStub = sinon.stub();
- successStub = sinon.stub();
-
- model.on('revert', revertEventStub);
- model.on('error', errorStub);
- });
- it('tells the server to revert when calling the revert method', function(done) {
- var promise = model.revert({
- success: successStub
- });
-
- expect(fakeServer.requests.length).toEqual(1);
- var request = fakeServer.requests[0];
- expect(request.url)
- .toEqual(
- OC.linkToRemoteBase('dav') + '/versions/user/versions/10/10000000'
- );
- expect(request.requestHeaders.Destination).toEqual(OC.getRootPath() + '/remote.php/dav/versions/user/restore/target');
- request.respond(201);
-
- promise.then(function() {
- expect(revertEventStub.calledOnce).toEqual(true);
- expect(successStub.calledOnce).toEqual(true);
- expect(errorStub.notCalled).toEqual(true);
-
- done();
- });
- });
- it('triggers error event when server returns a failure', function(done) {
- var promise = model.revert({
- success: successStub
- });
-
- expect(fakeServer.requests.length).toEqual(1);
- var responseErrorHeaders = {
- "Content-Type": "application/xml"
- };
- var responseErrorBody =
- '<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">' +
- ' <s:exception>Sabre\\DAV\\Exception\\SomeException</s:exception>' +
- ' <s:message>Some error message</s:message>' +
- '</d:error>';
- fakeServer.requests[0].respond(404, responseErrorHeaders, responseErrorBody);
-
- promise.fail(function() {
- expect(revertEventStub.notCalled).toEqual(true);
- expect(successStub.notCalled).toEqual(true);
- expect(errorStub.calledOnce).toEqual(true);
-
- done();
- });
- });
- });
-});
-
diff --git a/apps/files_versions/tests/js/versionstabviewSpec.js b/apps/files_versions/tests/js/versionstabviewSpec.js
deleted file mode 100644
index f7bec0ab1b5..00000000000
--- a/apps/files_versions/tests/js/versionstabviewSpec.js
+++ /dev/null
@@ -1,193 +0,0 @@
-/**
- * Copyright (c) 2015
- *
- * @author Michael Jobst <mjobst+github@tecratech.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author noveens <noveen.sachdeva@research.iiit.ac.in>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0-or-later
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-describe('OCA.Versions.VersionsTabView', function() {
- var VersionCollection = OCA.Versions.VersionCollection;
- var VersionModel = OCA.Versions.VersionModel;
- var VersionsTabView = OCA.Versions.VersionsTabView;
-
- var fetchStub, fileInfoModel, tabView, testVersions, clock;
-
- beforeEach(function() {
- clock = sinon.useFakeTimers(Date.UTC(2015, 6, 17, 1, 2, 0, 3));
- var time1 = Date.UTC(2015, 6, 17, 1, 2, 0, 3) / 1000;
- var time2 = Date.UTC(2015, 6, 15, 1, 2, 0, 3) / 1000;
-
- var version1 = new VersionModel({
- id: time1,
- timestamp: time1,
- name: 'some file.txt',
- size: 140,
- fullPath: '/subdir/some file.txt',
- mimetype: 'text/plain'
- });
- var version2 = new VersionModel({
- id: time2,
- timestamp: time2,
- name: 'some file.txt',
- size: 150,
- fullPath: '/subdir/some file.txt',
- mimetype: 'text/plain'
- });
-
- testVersions = [version1, version2];
-
- fetchStub = sinon.stub(VersionCollection.prototype, 'fetch');
- fileInfoModel = new OCA.Files.FileInfoModel({
- id: 123,
- name: 'test.txt',
- permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE
- });
- tabView = new VersionsTabView();
- tabView.render();
- });
-
- afterEach(function() {
- fetchStub.restore();
- tabView.remove();
- clock.restore();
- });
-
- describe('rendering', function() {
- it('reloads matching versions when setting file info model', function() {
- tabView.setFileInfo(fileInfoModel);
- expect(fetchStub.calledOnce).toEqual(true);
- });
-
- it('renders loading icon while fetching versions', function() {
- tabView.setFileInfo(fileInfoModel);
- tabView.collection.trigger('request');
-
- expect(tabView.$el.find('.loading').length).toEqual(1);
- expect(tabView.$el.find('.versions li').length).toEqual(0);
- });
-
- it('renders versions', function() {
-
- tabView.setFileInfo(fileInfoModel);
- tabView.collection.set(testVersions);
-
- var version1 = testVersions[0];
- var version2 = testVersions[1];
- var $versions = tabView.$el.find('.versions>li');
- expect($versions.length).toEqual(2);
- var $item = $versions.eq(0);
- expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl());
- expect($item.find('.versiondate').text()).toEqual('seconds ago');
- expect($item.find('.size').text()).toEqual('< 1 KB');
- expect($item.find('.revertVersion').length).toEqual(1);
-
- $item = $versions.eq(1);
- expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl());
- expect($item.find('.versiondate').text()).toEqual('2 days ago');
- expect($item.find('.size').text()).toEqual('< 1 KB');
- expect($item.find('.revertVersion').length).toEqual(1);
- });
-
- it('does not render revert button when no update permissions', function() {
-
- fileInfoModel.set('permissions', OC.PERMISSION_READ);
- tabView.setFileInfo(fileInfoModel);
- tabView.collection.set(testVersions);
-
- var version1 = testVersions[0];
- var version2 = testVersions[1];
- var $versions = tabView.$el.find('.versions>li');
- expect($versions.length).toEqual(2);
- var $item = $versions.eq(0);
- expect($item.find('.downloadVersion').attr('href')).toEqual(version1.getDownloadUrl());
- expect($item.find('.versiondate').text()).toEqual('seconds ago');
- expect($item.find('.revertVersion').length).toEqual(0);
-
- $item = $versions.eq(1);
- expect($item.find('.downloadVersion').attr('href')).toEqual(version2.getDownloadUrl());
- expect($item.find('.versiondate').text()).toEqual('2 days ago');
- expect($item.find('.revertVersion').length).toEqual(0);
- });
- });
-
- describe('Reverting', function() {
- var revertStub;
-
- beforeEach(function() {
- revertStub = sinon.stub(VersionModel.prototype, 'revert');
- tabView.setFileInfo(fileInfoModel);
- tabView.collection.set(testVersions);
- });
-
- afterEach(function() {
- revertStub.restore();
- });
-
- it('tells the model to revert when clicking "Revert"', function() {
- tabView.$el.find('.revertVersion').eq(1).click();
-
- expect(revertStub.calledOnce).toEqual(true);
- });
- it('triggers busy state during revert', function() {
- var busyStub = sinon.stub();
- fileInfoModel.on('busy', busyStub);
-
- tabView.$el.find('.revertVersion').eq(1).click();
-
- expect(busyStub.calledOnce).toEqual(true);
- expect(busyStub.calledWith(fileInfoModel, true)).toEqual(true);
-
- busyStub.reset();
- revertStub.getCall(0).args[0].success();
-
- expect(busyStub.calledOnce).toEqual(true);
- expect(busyStub.calledWith(fileInfoModel, false)).toEqual(true);
- });
- it('updates the file info model with the information from the reverted revision', function() {
- var changeStub = sinon.stub();
- fileInfoModel.on('change', changeStub);
-
- tabView.$el.find('.revertVersion').eq(1).click();
-
- expect(changeStub.notCalled).toEqual(true);
-
- revertStub.getCall(0).args[0].success();
-
- expect(changeStub.calledOnce).toEqual(true);
- var changes = changeStub.getCall(0).args[0].changed;
- expect(changes.size).toEqual(150);
- expect(changes.mtime).toEqual(testVersions[1].get('timestamp') * 1000);
- expect(changes.etag).toBeDefined();
- });
- it('shows notification on revert error', function() {
- var notificationStub = sinon.stub(OC.Notification, 'show');
-
- tabView.$el.find('.revertVersion').eq(1).click();
-
- revertStub.getCall(0).args[0].error();
-
- expect(notificationStub.calledOnce).toEqual(true);
-
- notificationStub.restore();
- });
- });
-});