From 332ffefd5c42d6b387b00834d0d167b3531c173c Mon Sep 17 00:00:00 2001
From: sturlan
Date: Fri, 27 Mar 2026 12:54:00 +0100
Subject: [PATCH 001/228] feat(thread): show per-message To/Cc/Bcc recipients
in thread view
Closes #11305, #9311, #4258. Recipients (To, Cc, Bcc) are already
returned by the API for every message in a thread but were never
displayed in ThreadEnvelope. Add RecipientBubble components in the
expanded message header for each recipient list, following the same
pattern used for per-message subject-change display.
AI-assisted: Claude Code (claude-sonnet-4-6)
Signed-off-by: Darko Sturlan
---
src/components/ThreadEnvelope.vue | 43 +++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/src/components/ThreadEnvelope.vue b/src/components/ThreadEnvelope.vue
index 3078e2e0be..5dd83c8bff 100644
--- a/src/components/ThreadEnvelope.vue
+++ b/src/components/ThreadEnvelope.vue
@@ -68,6 +68,32 @@
{{ envelope.from && envelope.from[0] ? envelope.from[0].email : '' }}
+
+
+ {{ t('mail', 'To:') }}
+
+
+
+ {{ t('mail', 'Cc:') }}
+
+
+
+ {{ t('mail', 'Bcc:') }}
+
+
+
{{ cleanSubject }}
@@ -341,6 +367,7 @@ import IconFavorite from 'vue-material-design-icons/Star.vue'
import StarOutline from 'vue-material-design-icons/StarOutline.vue'
import DeleteIcon from 'vue-material-design-icons/TrashCanOutline.vue'
import Avatar from './Avatar.vue'
+import RecipientBubble from './RecipientBubble.vue'
import ConfirmModal from './ConfirmationModal.vue'
import Error from './Error.vue'
import EventModal from './EventModal.vue'
@@ -389,6 +416,7 @@ export default {
TranslationModal,
ConfirmModal,
Avatar,
+ RecipientBubble,
NcActionButton,
NcButton,
Error,
@@ -1314,6 +1342,21 @@ export default {
white-space: nowrap;
}
+ .recipients {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 4px;
+ margin-block: 2px;
+ margin-inline-start: 8px;
+
+ &__label {
+ color: var(--color-text-maxcontrast);
+ font-weight: bold;
+ white-space: nowrap;
+ }
+ }
+
&--expanded {
min-height: 350px;
}
From 971a59dec9534917cb608c90fd27a9adfe992e83 Mon Sep 17 00:00:00 2001
From: sturlan
Date: Fri, 27 Mar 2026 13:02:41 +0100
Subject: [PATCH 002/228] fix(thread): move recipient bubbles outside
router-link to fix click handling
RecipientBubble uses NcUserBubble which renders as an anchor tag.
Placing it inside the router-link's click handler caused navigation on
click instead of opening the contact popover. Move the recipients
section outside the router-link into its own envelope__recipients div.
AI-assisted: Claude Code (claude-sonnet-4-6)
Signed-off-by: Darko Sturlan
---
src/components/ThreadEnvelope.vue | 92 +++++++++++++++++--------------
1 file changed, 50 insertions(+), 42 deletions(-)
diff --git a/src/components/ThreadEnvelope.vue b/src/components/ThreadEnvelope.vue
index 5dd83c8bff..2dfcd74354 100644
--- a/src/components/ThreadEnvelope.vue
+++ b/src/components/ThreadEnvelope.vue
@@ -68,33 +68,7 @@
{{ envelope.from && envelope.from[0] ? envelope.from[0].email : '' }}
-
-
- {{ t('mail', 'To:') }}
-
-
-
- {{ t('mail', 'Cc:') }}
-
-
-
- {{ t('mail', 'Bcc:') }}
-
-
-
-
+
{{ cleanSubject }}
@@ -297,7 +271,33 @@
-
+
+
+ {{ t('mail', 'To:') }}
+
+
+
+ {{ t('mail', 'Cc:') }}
+
+
+
+ {{ t('mail', 'Bcc:') }}
+
+
+
+
Date: Fri, 27 Mar 2026 13:05:49 +0100
Subject: [PATCH 003/228] feat(thread): match design spec from #4258
Per ChristophWurst's Sept 2023 design spec:
- Hide sender email address in collapsed message state
- Apply --color-text-maxcontrast to sender name when expanded
- Remove thread-level participant bubble header from Thread.vue
along with all associated dead code (participantsToDisplay,
moreParticipantsString, updateParticipantsToDisplay, resize
listener, RecipientBubble/NcPopover imports)
AI-assisted: Claude Code (claude-sonnet-4-6)
Signed-off-by: Darko Sturlan
---
src/components/Thread.vue | 95 +------------------------------
src/components/ThreadEnvelope.vue | 12 ++--
2 files changed, 10 insertions(+), 97 deletions(-)
diff --git a/src/components/Thread.vue b/src/components/Thread.vue
index 2a7aa1d160..3d7d72cf55 100644
--- a/src/components/Thread.vue
+++ b/src/components/Thread.vue
@@ -16,39 +16,7 @@
{{ threadSubject }}
-
+
@@ -73,13 +41,10 @@
+
+
diff --git a/src/components/NavigationAccount.vue b/src/components/NavigationAccount.vue
index 4bedb0027e..5d9ae21c62 100644
--- a/src/components/NavigationAccount.vue
+++ b/src/components/NavigationAccount.vue
@@ -36,6 +36,18 @@
{{ t('mail', 'Account settings') }}
+
+
+
+
+ {{ t('mail', 'Delegate account') }}
+
{{ t('mail', 'Move down') }}
-
+
@@ -85,6 +97,7 @@
+
@@ -92,7 +105,7 @@
import { DialogBuilder, showError } from '@nextcloud/dialogs'
import { formatFileSize } from '@nextcloud/files'
import { generateUrl } from '@nextcloud/router'
-import { NcActionButton as ActionButton, NcActionCheckbox as ActionCheckbox, NcActionInput as ActionInput, NcActionText as ActionText, NcLoadingIcon as IconLoading, NcAppNavigationCaption } from '@nextcloud/vue'
+import { NcActionButton as ActionButton, NcActionCheckbox as ActionCheckbox, NcActionInput as ActionInput, NcActionText as ActionText, NcLoadingIcon as IconLoading, NcAppNavigationCaption, NcIconSvgWrapper } from '@nextcloud/vue'
import { mapStores } from 'pinia'
import { Fragment } from 'vue-frag'
import MenuDown from 'vue-material-design-icons/ChevronDown.vue'
@@ -104,6 +117,7 @@ import IconDelete from 'vue-material-design-icons/TrashCanOutline.vue'
import logger from '../logger.js'
import { fetchQuota } from '../service/AccountService.js'
import useMainStore from '../store/mainStore.js'
+import IconDelegation from './../../img/delegation.svg'
export default {
name: 'NavigationAccount',
@@ -115,8 +129,10 @@ export default {
ActionInput,
ActionText,
AccountSettings: () => import(/* webpackChunkName: "account-settings" */ './AccountSettings.vue'),
+ DelegationModal: () => import(/* webpackChunkName: "delegation-modal" */ './DelegationModal.vue'),
IconInfo,
IconSettings,
+ NcIconSvgWrapper,
IconFolderAdd,
MenuDown,
MenuUp,
@@ -162,6 +178,8 @@ export default {
quota: undefined,
editing: false,
showSaving: false,
+ showDelegationModal: false,
+ IconDelegation,
createMailboxName: '',
showMailboxes: false,
nameInput: false,
@@ -179,6 +197,10 @@ export default {
return this.account.isUnified !== true && this.account.visible !== false
},
+ canDelegate() {
+ return !this.account.isDelegated && !this.account.provisioningId
+ },
+
id() {
return 'account-' + this.account.id
},
@@ -253,6 +275,7 @@ export default {
location.href = generateUrl('/apps/mail')
} catch (error) {
logger.error('could not delete account', { error })
+ showError(t('mail', 'could not delete account'))
} finally {
this.loading.delete = false
}
diff --git a/src/service/DelegationService.js b/src/service/DelegationService.js
new file mode 100644
index 0000000000..919e3e6d00
--- /dev/null
+++ b/src/service/DelegationService.js
@@ -0,0 +1,59 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+import axios from '@nextcloud/axios'
+import { generateUrl } from '@nextcloud/router'
+
+/**
+ * @typedef Delegation
+ * @property {number} id the delegation id
+ * @property {number} accountId the account id
+ * @property {string} userId the delegated user id
+ */
+
+/**
+ * Fetch all users that have delegation for a given account
+ *
+ * @param {number} accountId id of the account
+ * @return {Promise}
+ */
+export async function fetchDelegatedUsers(accountId) {
+ const url = generateUrl('/apps/mail/api/delegations/{accountId}', {
+ accountId,
+ })
+ const { data } = await axios.get(url)
+ return data
+}
+
+/**
+ * Delegate an account to a user
+ *
+ * @param {number} accountId id of the account
+ * @param {string} userId id of the user to delegate to
+ * @return {Promise}
+ */
+export async function delegate(accountId, userId) {
+ const url = generateUrl('/apps/mail/api/delegations/{accountId}', {
+ accountId,
+ })
+ const { data } = await axios.post(url, { userId })
+ return data
+}
+
+/**
+ * Revoke delegation of an account for a user
+ *
+ * @param {number} accountId id of the account
+ * @param {string} userId id of the user to revoke delegation for
+ * @return {Promise}
+ */
+export async function unDelegate(accountId, userId) {
+ const url = generateUrl('/apps/mail/api/delegations/{accountId}/{userId}', {
+ accountId,
+ userId,
+ })
+
+ const { data } = await axios.delete(url)
+ return data
+}
diff --git a/tests/Integration/MailboxSynchronizationTest.php b/tests/Integration/MailboxSynchronizationTest.php
index aa93fdf616..ba7c5b9a24 100644
--- a/tests/Integration/MailboxSynchronizationTest.php
+++ b/tests/Integration/MailboxSynchronizationTest.php
@@ -16,6 +16,7 @@
use OCA\Mail\Controller\MailboxesController;
use OCA\Mail\Db\MessageMapper as DbMessageMapper;
use OCA\Mail\Service\AccountService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\Sync\ImapToDbSynchronizer;
use OCA\Mail\Service\Sync\SyncService;
use OCA\Mail\Tests\Integration\Framework\ImapTest;
@@ -51,6 +52,7 @@ protected function setUp(): void {
Server::get(SyncService::class),
Server::get(IConfig::class),
Server::get(ITimeFactory::class),
+ Server::get(DelegationService::class),
);
$this->account = $this->createTestAccount('user12345');
diff --git a/tests/Unit/Controller/AccountApiControllerTest.php b/tests/Unit/Controller/AccountApiControllerTest.php
index c560c8e4f5..010c08219c 100644
--- a/tests/Unit/Controller/AccountApiControllerTest.php
+++ b/tests/Unit/Controller/AccountApiControllerTest.php
@@ -16,6 +16,7 @@
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\AliasesService;
+use OCA\Mail\Service\DelegationService;
use OCP\AppFramework\Http;
use OCP\IRequest;
use PHPUnit\Framework\MockObject\MockObject;
@@ -28,6 +29,7 @@ class AccountApiControllerTest extends TestCase {
private IRequest&MockObject $request;
private AccountService&MockObject $accountService;
private AliasesService&MockObject $aliasesService;
+ private DelegationService&MockObject $delegationService;
protected function setUp(): void {
parent::setUp();
@@ -35,6 +37,7 @@ protected function setUp(): void {
$this->request = $this->createMock(IRequest::class);
$this->accountService = $this->createMock(AccountService::class);
$this->aliasesService = $this->createMock(AliasesService::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
$this->controller = new AccountApiController(
'mail',
@@ -42,6 +45,7 @@ protected function setUp(): void {
self::USER_ID,
$this->accountService,
$this->aliasesService,
+ $this->delegationService,
);
}
@@ -52,6 +56,7 @@ public function testListWithoutUser() {
null,
$this->accountService,
$this->aliasesService,
+ $this->delegationService,
);
$this->accountService->expects(self::never())
@@ -68,12 +73,17 @@ public function testList() {
$mailAccount = new MailAccount();
$mailAccount->setId(42);
$mailAccount->setEmail('foo@bar.com');
+ $mailAccount->setUserId(self::USER_ID);
$account = new Account($mailAccount);
$this->accountService->expects(self::once())
->method('findByUserId')
->with(self::USER_ID)
->willReturn([$account]);
+ $this->accountService->expects(self::once())
+ ->method('findDelegatedAccounts')
+ ->with(self::USER_ID)
+ ->willReturn([]);
$alias = new Alias();
$alias->setId(10);
@@ -90,6 +100,7 @@ public function testList() {
[
'id' => 42,
'email' => 'foo@bar.com',
+ 'isDelegated' => false,
'aliases' => [
[
'id' => 10,
@@ -105,12 +116,17 @@ public function testListWithAliasWithoutName() {
$mailAccount = new MailAccount();
$mailAccount->setId(42);
$mailAccount->setEmail('foo@bar.com');
+ $mailAccount->setUserId(self::USER_ID);
$account = new Account($mailAccount);
$this->accountService->expects(self::once())
->method('findByUserId')
->with(self::USER_ID)
->willReturn([$account]);
+ $this->accountService->expects(self::once())
+ ->method('findDelegatedAccounts')
+ ->with(self::USER_ID)
+ ->willReturn([]);
$alias = new Alias();
$alias->setId(10);
@@ -127,6 +143,7 @@ public function testListWithAliasWithoutName() {
[
'id' => 42,
'email' => 'foo@bar.com',
+ 'isDelegated' => false,
'aliases' => [
[
'id' => 10,
@@ -138,16 +155,91 @@ public function testListWithAliasWithoutName() {
], $actual->getData());
}
+ public function testListWithDelegatedAccounts() {
+ $ownMailAccount = new MailAccount();
+ $ownMailAccount->setId(42);
+ $ownMailAccount->setEmail('foo@bar.com');
+ $ownMailAccount->setUserId(self::USER_ID);
+ $ownAccount = new Account($ownMailAccount);
+
+
+ $delegatedMailAccount = new MailAccount();
+ $delegatedMailAccount->setId(99);
+ $delegatedMailAccount->setEmail('shared@bar.com');
+ $delegatedMailAccount->setUserId('owner');
+ $delegatedAccount = new Account($delegatedMailAccount);
+
+ $this->accountService->expects(self::once())
+ ->method('findByUserId')
+ ->with(self::USER_ID)
+ ->willReturn([$ownAccount]);
+ $this->accountService->expects(self::once())
+ ->method('findDelegatedAccounts')
+ ->with(self::USER_ID)
+ ->willReturn([$delegatedAccount]);
+
+ $ownAlias = new Alias();
+ $ownAlias->setId(10);
+ $ownAlias->setName('Baz');
+ $ownAlias->setAlias('baz@bar.com');
+
+ $delegatedAlias = new Alias();
+ $delegatedAlias->setId(20);
+ $delegatedAlias->setName('Shared Alias');
+ $delegatedAlias->setAlias('shared-alias@bar.com');
+
+ $this->aliasesService->expects(self::exactly(2))
+ ->method('findAll')
+ ->willReturnMap([
+ [42, self::USER_ID, [$ownAlias]],
+ [99, 'owner', [$delegatedAlias]],
+ ]);
+
+ $actual = $this->controller->list();
+ $this->assertEquals(Http::STATUS_OK, $actual->getStatus());
+ $this->assertEquals([
+ [
+ 'id' => 42,
+ 'email' => 'foo@bar.com',
+ 'isDelegated' => false,
+ 'aliases' => [
+ [
+ 'id' => 10,
+ 'email' => 'baz@bar.com',
+ 'name' => 'Baz',
+ ],
+ ],
+ ],
+ [
+ 'id' => 99,
+ 'email' => 'shared@bar.com',
+ 'isDelegated' => true,
+ 'aliases' => [
+ [
+ 'id' => 20,
+ 'email' => 'shared-alias@bar.com',
+ 'name' => 'Shared Alias',
+ ],
+ ],
+ ],
+ ], $actual->getData());
+ }
+
public function testListWithoutAliases() {
$mailAccount = new MailAccount();
$mailAccount->setId(42);
$mailAccount->setEmail('foo@bar.com');
+ $mailAccount->setUserId(self::USER_ID);
$account = new Account($mailAccount);
$this->accountService->expects(self::once())
->method('findByUserId')
->with(self::USER_ID)
->willReturn([$account]);
+ $this->accountService->expects(self::once())
+ ->method('findDelegatedAccounts')
+ ->with(self::USER_ID)
+ ->willReturn([]);
$this->aliasesService->expects(self::once())
->method('findAll')
@@ -160,6 +252,7 @@ public function testListWithoutAliases() {
[
'id' => 42,
'email' => 'foo@bar.com',
+ 'isDelegated' => false,
'aliases' => [],
]
], $actual->getData());
diff --git a/tests/Unit/Controller/AccountsControllerTest.php b/tests/Unit/Controller/AccountsControllerTest.php
index b659555d3c..234ca139a6 100644
--- a/tests/Unit/Controller/AccountsControllerTest.php
+++ b/tests/Unit/Controller/AccountsControllerTest.php
@@ -21,6 +21,7 @@
use OCA\Mail\IMAP\Sync\Response;
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\AliasesService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\SetupService;
use OCA\Mail\Service\Sync\SyncService;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -85,6 +86,9 @@ class AccountsControllerTest extends TestCase {
/** @var IConfig|(IConfig&MockObject)|MockObject */
private IConfig|MockObject $config;
+
+ /** @var DelegationService|MockObject */
+ private $delegationService;
/** @var IRemoteHostValidator|MockObject */
private $hostValidator;
@@ -107,6 +111,9 @@ protected function setUp(): void {
$this->hostValidator = $this->createMock(IRemoteHostValidator::class);
$this->hostValidator->method('isValid')->willReturn(true);
$this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')
+ ->willReturn($this->userId);
$this->controller = new AccountsController(
$this->appName,
@@ -124,6 +131,7 @@ protected function setUp(): void {
$this->hostValidator,
$this->mailboxSync,
$this->timeFactory,
+ $this->delegationService,
);
$this->account = $this->createMock(Account::class);
$this->accountId = 123;
@@ -143,6 +151,10 @@ public function testIndex(): void {
->method('findAll')
->with(self::equalTo($this->accountId), self::equalTo($this->userId))
->will(self::returnValue(['a1', 'a2']));
+ $this->accountService->expects(self::once())
+ ->method('findDelegatedAccounts')
+ ->with(self::equalTo($this->userId))
+ ->willReturn([]);
$response = $this->controller->index();
@@ -153,6 +165,7 @@ public function testIndex(): void {
'a1',
'a2',
],
+ 'isDelegated' => false,
]
]);
self::assertEquals($expectedResponse, $response);
diff --git a/tests/Unit/Controller/AliasesControllerTest.php b/tests/Unit/Controller/AliasesControllerTest.php
index 51e36e7933..067cecda14 100644
--- a/tests/Unit/Controller/AliasesControllerTest.php
+++ b/tests/Unit/Controller/AliasesControllerTest.php
@@ -15,6 +15,7 @@
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\NotImplemented;
use OCA\Mail\Service\AliasesService;
+use OCA\Mail\Service\DelegationService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
@@ -35,6 +36,9 @@ class AliasesControllerTest extends TestCase {
/** @var AliasesService */
private $aliasService;
+ /** @var DelegationService */
+ private $delegationService;
+
public function setUp(): void {
parent::setUp();
$this->request = $this->getMockBuilder('OCP\IRequest')
@@ -48,7 +52,12 @@ public function setUp(): void {
$this->mailAccountMapper = $this->createMock(MailAccountMapper::class);
$this->aliasService = new AliasesService($this->aliasMapper, $this->mailAccountMapper);
- $this->controller = new AliasesController($this->appName, $this->request, $this->aliasService, $this->userId);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')
+ ->willReturn($this->userId);
+ $this->delegationService->method('resolveAliasUserId')
+ ->willReturn($this->userId);
+ $this->controller = new AliasesController($this->appName, $this->request, $this->aliasService, $this->userId, $this->delegationService);
}
public function testIndex(): void {
diff --git a/tests/Unit/Controller/DelegationControllerTest.php b/tests/Unit/Controller/DelegationControllerTest.php
new file mode 100644
index 0000000000..e0a6798c71
--- /dev/null
+++ b/tests/Unit/Controller/DelegationControllerTest.php
@@ -0,0 +1,260 @@
+request = $this->createMock(IRequest::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->accountService = $this->createMock(AccountService::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+
+ $this->controller = new DelegationController(
+ $this->appName,
+ $this->request,
+ $this->delegationService,
+ $this->accountService,
+ $this->userManager,
+ $this->currentUserId,
+ );
+
+ $ownMailAccount = new MailAccount();
+ $ownMailAccount->setId(1);
+ $ownMailAccount->setUserId($this->currentUserId);
+ $ownMailAccount->setEmail('owner@example.com');
+ $this->ownAccount = new Account($ownMailAccount);
+
+ $otherMailAccount = new MailAccount();
+ $otherMailAccount->setId(2);
+ $otherMailAccount->setUserId('other');
+ $otherMailAccount->setEmail('other@example.com');
+ $this->otherAccount = new Account($otherMailAccount);
+ }
+
+ public function testGetDelegatedUsersSuccess(): void {
+ $delegation = new Delegation();
+ $delegation->setId(10);
+ $delegation->setAccountId(1);
+ $delegation->setUserId('delegatee');
+
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(1)
+ ->willReturn($this->ownAccount);
+
+ $this->delegationService->expects($this->once())
+ ->method('findDelegatedToUsersForAccount')
+ ->with(1)
+ ->willReturn([$delegation]);
+
+ $response = $this->controller->getDelegatedUsers(1);
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_OK, $response->getStatus());
+ $this->assertEquals([$delegation], $response->getData());
+ }
+
+ public function testGetDelegatedUsersUnauthorized(): void {
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(2)
+ ->willReturn($this->otherAccount);
+
+ $this->delegationService->expects($this->never())
+ ->method('findDelegatedToUsersForAccount');
+
+ $response = $this->controller->getDelegatedUsers(2);
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
+ }
+
+ public function testDelegateSuccess(): void {
+ $delegation = new Delegation();
+ $delegation->setId(10);
+ $delegation->setAccountId(1);
+ $delegation->setUserId('delegatee');
+
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(1)
+ ->willReturn($this->ownAccount);
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with('delegatee')
+ ->willReturn(true);
+
+ $this->delegationService->expects($this->once())
+ ->method('delegate')
+ ->with(1, 'delegatee')
+ ->willReturn($delegation);
+
+ $response = $this->controller->delegate(1, 'delegatee');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
+ $this->assertEquals($delegation, $response->getData());
+ }
+
+ public function testDelegateUnauthorized(): void {
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(2)
+ ->willReturn($this->otherAccount);
+
+ $this->delegationService->expects($this->never())
+ ->method('delegate');
+
+ $response = $this->controller->delegate(2, 'delegatee');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
+ }
+
+ public function testDelegateProvisionedAccount(): void {
+ $provisionedMailAccount = new MailAccount();
+ $provisionedMailAccount->setId(3);
+ $provisionedMailAccount->setUserId($this->currentUserId);
+ $provisionedMailAccount->setEmail('provisioned@example.com');
+ $provisionedMailAccount->setProvisioningId(42);
+ $provisionedAccount = new Account($provisionedMailAccount);
+
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(3)
+ ->willReturn($provisionedAccount);
+
+ $this->delegationService->expects($this->never())
+ ->method('delegate');
+
+ $response = $this->controller->delegate(3, 'delegatee');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_FORBIDDEN, $response->getStatus());
+ $this->assertEquals(['message' => 'Cannot delegate provisioned accounts'], $response->getData());
+ }
+
+ public function testDelegateToSelf(): void {
+ $this->accountService->expects($this->never())
+ ->method('findById');
+
+ $this->delegationService->expects($this->never())
+ ->method('delegate');
+
+ $response = $this->controller->delegate(1, $this->currentUserId);
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
+ $this->assertEquals(['message' => 'Cannot delegate to yourself'], $response->getData());
+ }
+
+ public function testDelegateUserNotFound(): void {
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(1)
+ ->willReturn($this->ownAccount);
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with('nonexistent')
+ ->willReturn(false);
+
+ $this->delegationService->expects($this->never())
+ ->method('delegate');
+
+ $response = $this->controller->delegate(1, 'nonexistent');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
+ }
+
+ public function testDelegateAlreadyExists(): void {
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(1)
+ ->willReturn($this->ownAccount);
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with('delegatee')
+ ->willReturn(true);
+
+ $this->delegationService->expects($this->once())
+ ->method('delegate')
+ ->with(1, 'delegatee')
+ ->willThrowException(new DelegationExistsException('Delegation already exists'));
+
+ $response = $this->controller->delegate(1, 'delegatee');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_CONFLICT, $response->getStatus());
+ $this->assertEquals(['message' => 'Delegation already exists'], $response->getData());
+ }
+
+ public function testUnDelegateSuccess(): void {
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(1)
+ ->willReturn($this->ownAccount);
+
+ $this->delegationService->expects($this->once())
+ ->method('unDelegate')
+ ->with(1, 'delegatee');
+
+ $response = $this->controller->unDelegate(1, 'delegatee');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_OK, $response->getStatus());
+ }
+
+ public function testUnDelegateUnauthorized(): void {
+ $this->accountService->expects($this->once())
+ ->method('findById')
+ ->with(2)
+ ->willReturn($this->otherAccount);
+
+ $this->delegationService->expects($this->never())
+ ->method('unDelegate');
+
+ $response = $this->controller->unDelegate(2, 'delegatee');
+
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
+ }
+}
diff --git a/tests/Unit/Controller/DraftsControllerTest.php b/tests/Unit/Controller/DraftsControllerTest.php
index e1f672aff1..d9651ff6fa 100644
--- a/tests/Unit/Controller/DraftsControllerTest.php
+++ b/tests/Unit/Controller/DraftsControllerTest.php
@@ -19,6 +19,7 @@
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Http\JsonResponse;
use OCA\Mail\Service\AccountService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\DraftsService;
use OCA\Mail\Service\SmimeService;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -35,6 +36,7 @@ class DraftsControllerTest extends TestCase {
private AccountService $accountService;
private DraftsController $controller;
private SmimeService $smimeService;
+ private DelegationService $delegationService;
protected function setUp(): void {
parent::setUp();
@@ -46,6 +48,11 @@ protected function setUp(): void {
$this->accountService = $this->createMock(AccountService::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->smimeService = $this->createMock(SmimeService::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')
+ ->willReturn($this->userId);
+ $this->delegationService->method('resolveLocalMessageUserId')
+ ->willReturn($this->userId);
$this->controller = new DraftsController(
$this->appName,
@@ -54,7 +61,8 @@ protected function setUp(): void {
$this->service,
$this->accountService,
$this->timeFactory,
- $this->smimeService
+ $this->smimeService,
+ $this->delegationService,
);
}
diff --git a/tests/Unit/Controller/ListControllerTest.php b/tests/Unit/Controller/ListControllerTest.php
index 259ded1d51..b97b9dd482 100644
--- a/tests/Unit/Controller/ListControllerTest.php
+++ b/tests/Unit/Controller/ListControllerTest.php
@@ -34,6 +34,9 @@ protected function setUp(): void {
$this->serviceMock = $this->createServiceMock(ListController::class, [
'userId' => 'user123',
]);
+ $this->serviceMock->getParameter('delegationService')
+ ->method('resolveMessageUserId')
+ ->willReturn('user123');
$this->controller = $this->serviceMock->getService();
}
diff --git a/tests/Unit/Controller/MailboxesApiControllerTest.php b/tests/Unit/Controller/MailboxesApiControllerTest.php
index 221de5de87..f00754af70 100644
--- a/tests/Unit/Controller/MailboxesApiControllerTest.php
+++ b/tests/Unit/Controller/MailboxesApiControllerTest.php
@@ -19,6 +19,7 @@
use OCA\Mail\Db\Message as DbMessage;
use OCA\Mail\Folder;
use OCA\Mail\Service\AccountService;
+use OCA\Mail\Service\DelegationService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\IRequest;
@@ -33,6 +34,7 @@ class MailboxesApiControllerTest extends TestCase {
private IMailManager|MockObject $mailManager;
private AccountService&MockObject $accountService;
private MockObject|IMailSearch $mailSearch;
+ private DelegationService&MockObject $delegationService;
protected function setUp(): void {
parent::setUp();
@@ -41,6 +43,11 @@ protected function setUp(): void {
$this->accountService = $this->createMock(AccountService::class);
$this->mailManager = $this->createMock(IMailManager::class);
$this->mailSearch = $this->createMock(IMailSearch::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')
+ ->willReturn(self::USER_ID);
+ $this->delegationService->method('resolveMailboxUserId')
+ ->willReturn(self::USER_ID);
$this->controller = new MailboxesApiController(
'mail',
@@ -49,7 +56,7 @@ protected function setUp(): void {
$this->mailManager,
$this->accountService,
$this->mailSearch,
-
+ $this->delegationService,
);
}
@@ -61,6 +68,7 @@ public function testListMailboxesWithoutUser() {
$this->mailManager,
$this->accountService,
$this->mailSearch,
+ $this->delegationService,
);
$this->accountService->expects(self::never())
@@ -101,6 +109,7 @@ public function testListMessagesWithoutUser() {
$this->mailManager,
$this->accountService,
$this->mailSearch,
+ $this->delegationService,
);
$this->accountService->expects(self::never())
diff --git a/tests/Unit/Controller/MailboxesControllerTest.php b/tests/Unit/Controller/MailboxesControllerTest.php
index 8dddb381d2..51ffc5d3ef 100644
--- a/tests/Unit/Controller/MailboxesControllerTest.php
+++ b/tests/Unit/Controller/MailboxesControllerTest.php
@@ -18,6 +18,7 @@
use OCA\Mail\Folder;
use OCA\Mail\IMAP\MailboxStats;
use OCA\Mail\Service\AccountService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\Sync\SyncService;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -49,6 +50,7 @@ class MailboxesControllerTest extends TestCase {
private IConfig|MockObject $config;
private ITimeFactory|MockObject $timeFactory;
+ private DelegationService|MockObject $delegationService;
public function setUp(): void {
parent::setUp();
@@ -59,6 +61,9 @@ public function setUp(): void {
$this->syncService = $this->createMock(SyncService::class);
$this->config = $this->createMock(IConfig::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')->willReturn($this->userId);
+ $this->delegationService->method('resolveMailboxUserId')->willReturn($this->userId);
$this->controller = new MailboxesController(
$this->appName,
@@ -68,7 +73,8 @@ public function setUp(): void {
$this->mailManager,
$this->syncService,
$this->config,
- $this->timeFactory
+ $this->timeFactory,
+ $this->delegationService,
);
}
diff --git a/tests/Unit/Controller/MessageApiControllerTest.php b/tests/Unit/Controller/MessageApiControllerTest.php
index 7b06ac01d1..6ab43d2dea 100644
--- a/tests/Unit/Controller/MessageApiControllerTest.php
+++ b/tests/Unit/Controller/MessageApiControllerTest.php
@@ -27,6 +27,7 @@
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\AliasesService;
use OCA\Mail\Service\Attachment\AttachmentService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\DkimService;
use OCA\Mail\Service\ItineraryService;
use OCA\Mail\Service\MailManager;
@@ -58,6 +59,7 @@ class MessageApiControllerTest extends TestCase {
private DkimService|MockObject $dkimService;
private MockObject|ItineraryService $itineraryService;
private TrustedSenderService|MockObject $trustedSenderService;
+ private DelegationService|MockObject $delegationService;
private MessageApiController $controller;
private string $fromEmail = 'john@test.com';
private int $accountId = 1;
@@ -84,6 +86,9 @@ protected function setUp(): void {
$this->dkimService = $this->createMock(DkimService::class);
$this->itineraryService = $this->createMock(ItineraryService::class);
$this->trustedSenderService = $this->createMock(TrustedSenderService::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')->willReturn($this->userId);
+ $this->delegationService->method('resolveMessageUserId')->willReturn($this->userId);
$this->controller = new MessageApiController($this->appName,
$this->userId,
@@ -100,6 +105,7 @@ protected function setUp(): void {
$this->dkimService,
$this->itineraryService,
$this->trustedSenderService,
+ $this->delegationService,
);
$mailAccount = new MailAccount();
diff --git a/tests/Unit/Controller/MessagesControllerTest.php b/tests/Unit/Controller/MessagesControllerTest.php
index 83837b63c6..227a73dc90 100644
--- a/tests/Unit/Controller/MessagesControllerTest.php
+++ b/tests/Unit/Controller/MessagesControllerTest.php
@@ -37,6 +37,7 @@
use OCA\Mail\Model\Message;
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\AiIntegrations\AiIntegrationsService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\ItineraryService;
use OCA\Mail\Service\MailManager;
use OCA\Mail\Service\SmimeService;
@@ -134,6 +135,8 @@ class MessagesControllerTest extends TestCase {
private ICacheFactory&MockObject $cacheFactory;
+ private DelegationService|MockObject $delegationService;
+
protected function setUp(): void {
parent::setUp();
@@ -164,6 +167,10 @@ protected function setUp(): void {
$this->cacheFactory->method('createDistributed')
->willReturn(new NullCache());
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveMessageUserId')->willReturn($this->userId);
+ $this->delegationService->method('resolveMailboxUserId')->willReturn($this->userId);
+
$timeFactory = $this->createMocK(ITimeFactory::class);
$timeFactory->expects($this->any())
->method('getTime')
@@ -194,6 +201,7 @@ protected function setUp(): void {
$this->snoozeService,
$this->aiIntegrationsService,
$this->cacheFactory,
+ $this->delegationService,
);
$this->account = $this->createMock(Account::class);
@@ -1250,6 +1258,7 @@ public function testNeedsTranslationNoUser() {
$this->snoozeService,
$this->aiIntegrationsService,
$this->cacheFactory,
+ $this->delegationService,
);
$actualResponse = $controller->needsTranslation(100);
@@ -1422,6 +1431,7 @@ public function testSmartReplyNoUser(): void {
$this->snoozeService,
$this->aiIntegrationsService,
$this->cacheFactory,
+ $this->delegationService,
);
$actualResponse = $controller->smartReply(100);
diff --git a/tests/Unit/Controller/OutboxControllerTest.php b/tests/Unit/Controller/OutboxControllerTest.php
index 51f25603cf..ff31d91315 100644
--- a/tests/Unit/Controller/OutboxControllerTest.php
+++ b/tests/Unit/Controller/OutboxControllerTest.php
@@ -19,6 +19,7 @@
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Http\JsonResponse;
use OCA\Mail\Service\AccountService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\OutboxService;
use OCA\Mail\Service\SmimeService;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -43,6 +44,8 @@ class OutboxControllerTest extends TestCase {
/** @var SmimeService&MockObject */
private $smimeService;
+ private DelegationService&MockObject $delegationService;
+
private OutboxController $controller;
protected function setUp(): void {
parent::setUp();
@@ -53,6 +56,11 @@ protected function setUp(): void {
$this->request = $this->createMock(IRequest::class);
$this->accountService = $this->createMock(AccountService::class);
$this->smimeService = $this->createMock(SmimeService::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')
+ ->willReturn($this->userId);
+ $this->delegationService->method('resolveLocalMessageUserId')
+ ->willReturn($this->userId);
$this->controller = new OutboxController(
$this->appName,
@@ -61,6 +69,7 @@ protected function setUp(): void {
$this->service,
$this->accountService,
$this->smimeService,
+ $this->delegationService,
);
}
diff --git a/tests/Unit/Controller/PageControllerTest.php b/tests/Unit/Controller/PageControllerTest.php
index 804b9df2ef..9b84226810 100644
--- a/tests/Unit/Controller/PageControllerTest.php
+++ b/tests/Unit/Controller/PageControllerTest.php
@@ -205,6 +205,10 @@ public function testIndex(): void {
$account1,
$account2,
]));
+ $this->accountService->expects($this->once())
+ ->method('findDelegatedAccounts')
+ ->with($this->userId)
+ ->willReturn([]);
$this->mailManager->expects($this->exactly(2))
->method('getMailboxes')
->withConsecutive(
@@ -247,6 +251,7 @@ public function testIndex(): void {
'mailboxes' => [
$mailbox,
],
+ 'isDelegated' => false,
],
[
'accountId' => 2,
@@ -255,6 +260,7 @@ public function testIndex(): void {
'a22',
],
'mailboxes' => [],
+ 'isDelegated' => false,
],
];
diff --git a/tests/Unit/Controller/SieveControllerTest.php b/tests/Unit/Controller/SieveControllerTest.php
index c084c716ab..9a7bde01b9 100644
--- a/tests/Unit/Controller/SieveControllerTest.php
+++ b/tests/Unit/Controller/SieveControllerTest.php
@@ -43,6 +43,9 @@ protected function setUp(): void {
'userId' => '1',
]
);
+ $this->serviceMock->getParameter('delegationService')
+ ->method('resolveAccountUserId')
+ ->willReturn('1');
$this->sieveController = $this->serviceMock->getService();
}
diff --git a/tests/Unit/Controller/ThreadControllerTest.php b/tests/Unit/Controller/ThreadControllerTest.php
index bdd8220b7b..1dcf67c695 100644
--- a/tests/Unit/Controller/ThreadControllerTest.php
+++ b/tests/Unit/Controller/ThreadControllerTest.php
@@ -19,6 +19,7 @@
use OCA\Mail\Model\EventData;
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\AiIntegrations\AiIntegrationsService;
+use OCA\Mail\Service\DelegationService;
use OCA\Mail\Service\SnoozeService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
@@ -54,6 +55,9 @@ class ThreadControllerTest extends TestCase {
/** @var LoggerInterface|MockObject */
private $logger;
+ /** @var DelegationService|MockObject */
+ private $delegationService;
+
protected function setUp(): void {
parent::setUp();
@@ -65,6 +69,9 @@ protected function setUp(): void {
$this->snoozeService = $this->createMock(SnoozeService::class);
$this->aiIntergrationsService = $this->createMock(AiIntegrationsService::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveMessageUserId')->willReturn($this->userId);
+ $this->delegationService->method('resolveMailboxUserId')->willReturn($this->userId);
$this->controller = new ThreadController(
$this->appName,
@@ -75,6 +82,7 @@ protected function setUp(): void {
$this->snoozeService,
$this->aiIntergrationsService,
$this->logger,
+ $this->delegationService,
);
}
diff --git a/tests/Unit/Service/AccountServiceTest.php b/tests/Unit/Service/AccountServiceTest.php
index 05df2f5cd9..d2b9e7f1e5 100644
--- a/tests/Unit/Service/AccountServiceTest.php
+++ b/tests/Unit/Service/AccountServiceTest.php
@@ -13,6 +13,7 @@
use OCA\Mail\Account;
use OCA\Mail\BackgroundJob\QuotaJob;
use OCA\Mail\BackgroundJob\SyncJob;
+use OCA\Mail\Db\DelegationMapper;
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\MailAccountMapper;
use OCA\Mail\Exception\ClientException;
@@ -61,6 +62,7 @@ class AccountServiceTest extends TestCase {
private IConfig&MockObject $config;
private ITimeFactory&MockObject $time;
+ private DelegationMapper&MockObject $delegationMapper;
protected function setUp(): void {
parent::setUp();
@@ -72,6 +74,7 @@ protected function setUp(): void {
$this->imapClientFactory = $this->createMock(IMAPClientFactory::class);
$this->config = $this->createMock(IConfig::class);
$this->time = $this->createMock(ITimeFactory::class);
+ $this->delegationMapper = $this->createMock(DelegationMapper::class);
$this->accountService = new AccountService(
$this->mapper,
$this->aliasesService,
@@ -79,6 +82,7 @@ protected function setUp(): void {
$this->imapClientFactory,
$this->config,
$this->time,
+ $this->delegationMapper,
);
$this->account1 = new MailAccount();
diff --git a/tests/Unit/Service/DelegationServiceTest.php b/tests/Unit/Service/DelegationServiceTest.php
new file mode 100644
index 0000000000..c0ab17becf
--- /dev/null
+++ b/tests/Unit/Service/DelegationServiceTest.php
@@ -0,0 +1,313 @@
+delegationMapper = $this->createMock(DelegationMapper::class);
+ $this->accountService = $this->createMock(AccountService::class);
+ $this->mailboxMapper = $this->createMock(MailboxMapper::class);
+ $this->messageMapper = $this->createMock(MessageMapper::class);
+ $this->aliasMapper = $this->createMock(AliasMapper::class);
+ $this->localMessageMapper = $this->createMock(LocalMessageMapper::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->notificationManager = $this->createMock(IManager::class);
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
+
+ $this->service = new DelegationService(
+ $this->delegationMapper,
+ $this->accountService,
+ $this->mailboxMapper,
+ $this->messageMapper,
+ $this->aliasMapper,
+ $this->localMessageMapper,
+ );
+
+ $mailAccount = new MailAccount();
+ $mailAccount->setId(1);
+ $mailAccount->setUserId('owner');
+ $mailAccount->setEmail('owner@example.com');
+ $this->account = new Account($mailAccount);
+ }
+
+ private function mockNotification(): void {
+ $notification = $this->createMock(INotification::class);
+ $notification->method('setApp')->willReturnSelf();
+ $notification->method('setUser')->willReturnSelf();
+ $notification->method('setObject')->willReturnSelf();
+ $notification->method('setSubject')->willReturnSelf();
+ $notification->method('setDateTime')->willReturnSelf();
+ $notification->method('setMessage')->willReturnSelf();
+
+ $this->notificationManager->method('createNotification')->willReturn($notification);
+
+ $user = $this->createMock(IUser::class);
+ $user->method('getDisplayName')->willReturn('Owner User');
+ $this->userManager->method('get')->with('owner')->willReturn($user);
+ $this->timeFactory->method('getDateTime')->willReturn(new \DateTime());
+ }
+
+ public function testDelegateSuccess(): void {
+ $this->mockNotification();
+
+ $this->delegationMapper->expects($this->once())
+ ->method('find')
+ ->with(1, 'delegatee')
+ ->willThrowException(new DoesNotExistException('Not found'));
+
+ $expected = new Delegation();
+ $expected->setAccountId(1);
+ $expected->setUserId('delegatee');
+
+ $this->delegationMapper->expects($this->once())
+ ->method('insert')
+ ->willReturnCallback(function (Delegation $d) {
+ $d->setId(10);
+ return $d;
+ });
+
+ $result = $this->service->delegate($this->account->getId(), 'delegatee');
+
+ $this->assertEquals(1, $result->getAccountId());
+ $this->assertEquals('delegatee', $result->getUserId());
+ }
+
+ public function testDelegateThrowsWhenAlreadyExists(): void {
+ $existing = new Delegation();
+ $existing->setAccountId(1);
+ $existing->setUserId('delegatee');
+
+ $this->delegationMapper->expects($this->once())
+ ->method('find')
+ ->with(1, 'delegatee')
+ ->willReturn($existing);
+
+ $this->delegationMapper->expects($this->never())
+ ->method('insert');
+
+ $this->expectException(DelegationExistsException::class);
+
+ $this->service->delegate($this->account->getId(), 'delegatee');
+ }
+
+ public function testFindDelegatedToUsersForAccount(): void {
+ $delegation = new Delegation();
+ $delegation->setAccountId(1);
+ $delegation->setUserId('delegatee');
+
+ $this->delegationMapper->expects($this->once())
+ ->method('findDelegatedToUsers')
+ ->with(1)
+ ->willReturn([$delegation]);
+
+ $result = $this->service->findDelegatedToUsersForAccount(1);
+
+ $this->assertCount(1, $result);
+ $this->assertEquals('delegatee', $result[0]->getUserId());
+ }
+
+ public function testUnDelegateSuccess(): void {
+ $this->mockNotification();
+
+ $delegation = new Delegation();
+ $delegation->setId(10);
+ $delegation->setAccountId(1);
+ $delegation->setUserId('delegatee');
+
+ $this->delegationMapper->expects($this->once())
+ ->method('find')
+ ->with(1, 'delegatee')
+ ->willReturn($delegation);
+
+ $this->delegationMapper->expects($this->once())
+ ->method('delete')
+ ->with($delegation);
+
+ $this->service->unDelegate($this->account->getId(), 'delegatee');
+ }
+
+ public function testUnDelegateWhenNotFound(): void {
+ $this->delegationMapper->expects($this->once())
+ ->method('find')
+ ->with(1, 'delegatee')
+ ->willThrowException(new DoesNotExistException('Not found'));
+
+ $this->delegationMapper->expects($this->never())
+ ->method('delete');
+
+ $this->service->unDelegate($this->account->getId(), 'delegatee');
+ }
+
+ public function testResolveAccountUserIdOwner(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId(1);
+ $mailAccount->setUserId('owner');
+
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('owner', 1)
+ ->willReturn(new Account($mailAccount));
+
+ $result = $this->service->resolveAccountUserId(1, 'owner');
+
+ $this->assertEquals('owner', $result);
+ }
+
+ public function testResolveAccountUserIdDelegated(): void {
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('delegatee', 1)
+ ->willThrowException(new ClientException('Not found'));
+
+ $this->delegationMapper->expects($this->once())
+ ->method('findAccountOwnerForDelegatedUser')
+ ->with(1, 'delegatee')
+ ->willReturn('owner');
+
+ $result = $this->service->resolveAccountUserId(1, 'delegatee');
+
+ $this->assertEquals('owner', $result);
+ }
+
+ public function testResolveAccountUserIdNotFound(): void {
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('stranger', 1)
+ ->willThrowException(new ClientException('Not found'));
+
+ $this->delegationMapper->expects($this->once())
+ ->method('findAccountOwnerForDelegatedUser')
+ ->with(1, 'stranger')
+ ->willThrowException(new DoesNotExistException('No delegation found'));
+
+ $this->expectException(ClientException::class);
+
+ $this->service->resolveAccountUserId(1, 'stranger');
+ }
+
+ public function testResolveMailboxUserId(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId(1);
+ $mailAccount->setUserId('owner');
+
+ $this->mailboxMapper->expects($this->once())
+ ->method('findAccountIdForMailbox')
+ ->with(42)
+ ->willReturn(1);
+
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('owner', 1)
+ ->willReturn(new Account($mailAccount));
+
+ $result = $this->service->resolveMailboxUserId(42, 'owner');
+
+ $this->assertEquals('owner', $result);
+ }
+
+ public function testResolveMessageUserId(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId(1);
+ $mailAccount->setUserId('owner');
+
+ $this->messageMapper->expects($this->once())
+ ->method('findAccountIdForMessage')
+ ->with(99)
+ ->willReturn(1);
+
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('owner', 1)
+ ->willReturn(new Account($mailAccount));
+
+ $result = $this->service->resolveMessageUserId(99, 'owner');
+
+ $this->assertEquals('owner', $result);
+ }
+
+ public function testResolveAliasUserId(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId(1);
+ $mailAccount->setUserId('owner');
+
+ $this->aliasMapper->expects($this->once())
+ ->method('findAccountIdForAlias')
+ ->with(7)
+ ->willReturn(1);
+
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('owner', 1)
+ ->willReturn(new Account($mailAccount));
+
+ $result = $this->service->resolveAliasUserId(7, 'owner');
+
+ $this->assertEquals('owner', $result);
+ }
+
+ public function testResolveLocalMessageUserId(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId(1);
+ $mailAccount->setUserId('owner');
+
+ $this->localMessageMapper->expects($this->once())
+ ->method('findAccountIdForLocalMessage')
+ ->with(55)
+ ->willReturn(1);
+
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with('owner', 1)
+ ->willReturn(new Account($mailAccount));
+
+ $result = $this->service->resolveLocalMessageUserId(55, 'owner');
+
+ $this->assertEquals('owner', $result);
+ }
+}
From c6b89edbcbe08ec9d9e7cadf3aa89d148728a4c2 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Fri, 15 May 2026 01:26:52 +0000
Subject: [PATCH 028/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/ar.js | 1 +
l10n/ar.json | 1 +
l10n/ast.js | 1 +
l10n/ast.json | 1 +
l10n/bg.js | 1 +
l10n/bg.json | 1 +
l10n/br.js | 1 +
l10n/br.json | 1 +
l10n/ca.js | 1 +
l10n/ca.json | 1 +
l10n/cs.js | 1 +
l10n/cs.json | 1 +
l10n/da.js | 1 +
l10n/da.json | 1 +
l10n/de.js | 18 +++++++++++++++++
l10n/de.json | 18 +++++++++++++++++
l10n/de_DE.js | 18 +++++++++++++++++
l10n/de_DE.json | 18 +++++++++++++++++
l10n/el.js | 1 +
l10n/el.json | 1 +
l10n/en_GB.js | 1 +
l10n/en_GB.json | 1 +
l10n/eo.js | 1 +
l10n/eo.json | 1 +
l10n/es.js | 1 +
l10n/es.json | 1 +
l10n/es_419.js | 1 +
l10n/es_419.json | 1 +
l10n/es_AR.js | 1 +
l10n/es_AR.json | 1 +
l10n/es_CL.js | 1 +
l10n/es_CL.json | 1 +
l10n/es_CO.js | 1 +
l10n/es_CO.json | 1 +
l10n/es_CR.js | 1 +
l10n/es_CR.json | 1 +
l10n/es_DO.js | 1 +
l10n/es_DO.json | 1 +
l10n/es_EC.js | 1 +
l10n/es_EC.json | 1 +
l10n/es_GT.js | 1 +
l10n/es_GT.json | 1 +
l10n/es_HN.js | 1 +
l10n/es_HN.json | 1 +
l10n/es_MX.js | 1 +
l10n/es_MX.json | 1 +
l10n/es_NI.js | 1 +
l10n/es_NI.json | 1 +
l10n/es_PA.js | 1 +
l10n/es_PA.json | 1 +
l10n/es_PE.js | 1 +
l10n/es_PE.json | 1 +
l10n/es_PR.js | 1 +
l10n/es_PR.json | 1 +
l10n/es_PY.js | 1 +
l10n/es_PY.json | 1 +
l10n/es_SV.js | 1 +
l10n/es_SV.json | 1 +
l10n/es_UY.js | 1 +
l10n/es_UY.json | 1 +
l10n/et_EE.js | 1 +
l10n/et_EE.json | 1 +
l10n/eu.js | 1 +
l10n/eu.json | 1 +
l10n/fa.js | 1 +
l10n/fa.json | 1 +
l10n/fi.js | 1 +
l10n/fi.json | 1 +
l10n/fr.js | 1 +
l10n/fr.json | 1 +
l10n/ga.js | 1 +
l10n/ga.json | 1 +
l10n/gl.js | 1 +
l10n/gl.json | 1 +
l10n/he.js | 1 +
l10n/he.json | 1 +
l10n/hr.js | 1 +
l10n/hr.json | 1 +
l10n/hu.js | 1 +
l10n/hu.json | 1 +
l10n/ia.js | 1 +
l10n/ia.json | 1 +
l10n/id.js | 1 +
l10n/id.json | 1 +
l10n/is.js | 1 +
l10n/is.json | 1 +
l10n/it.js | 1 +
l10n/it.json | 1 +
l10n/ja.js | 1 +
l10n/ja.json | 1 +
l10n/ka.js | 1 +
l10n/ka.json | 1 +
l10n/ka_GE.js | 1 +
l10n/ka_GE.json | 1 +
l10n/ko.js | 1 +
l10n/ko.json | 1 +
l10n/lo.js | 1 +
l10n/lo.json | 1 +
l10n/lt_LT.js | 1 +
l10n/lt_LT.json | 1 +
l10n/lv.js | 1 +
l10n/lv.json | 1 +
l10n/mk.js | 1 +
l10n/mk.json | 1 +
l10n/mn.js | 1 +
l10n/mn.json | 1 +
l10n/nb.js | 1 +
l10n/nb.json | 1 +
l10n/nl.js | 1 +
l10n/nl.json | 1 +
l10n/oc.js | 1 +
l10n/oc.json | 1 +
l10n/pl.js | 1 +
l10n/pl.json | 1 +
l10n/pt_BR.js | 1 +
l10n/pt_BR.json | 1 +
l10n/pt_PT.js | 1 +
l10n/pt_PT.json | 1 +
l10n/ro.js | 1 +
l10n/ro.json | 1 +
l10n/ru.js | 1 +
l10n/ru.json | 1 +
l10n/sc.js | 1 +
l10n/sc.json | 1 +
l10n/sk.js | 1 +
l10n/sk.json | 1 +
l10n/sl.js | 1 +
l10n/sl.json | 1 +
l10n/sq.js | 1 +
l10n/sq.json | 1 +
l10n/sr.js | 1 +
l10n/sr.json | 1 +
l10n/sv.js | 1 +
l10n/sv.json | 1 +
l10n/sw.js | 1 +
l10n/sw.json | 1 +
l10n/ta.js | 50 ------------------------------------------------
l10n/ta.json | 48 ----------------------------------------------
l10n/th.js | 1 +
l10n/th.json | 1 +
l10n/tr.js | 1 +
l10n/tr.json | 1 +
l10n/ug.js | 1 +
l10n/ug.json | 1 +
l10n/uk.js | 1 +
l10n/uk.json | 1 +
l10n/vi.js | 1 +
l10n/vi.json | 1 +
l10n/zh_CN.js | 1 +
l10n/zh_CN.json | 1 +
l10n/zh_HK.js | 23 ++++++++++++++++++++++
l10n/zh_HK.json | 23 ++++++++++++++++++++++
l10n/zh_TW.js | 1 +
l10n/zh_TW.json | 1 +
154 files changed, 264 insertions(+), 98 deletions(-)
delete mode 100644 l10n/ta.js
delete mode 100644 l10n/ta.json
diff --git a/l10n/ar.js b/l10n/ar.js
index ff516d86c1..64976130f3 100644
--- a/l10n/ar.js
+++ b/l10n/ar.js
@@ -207,6 +207,7 @@ OC.L10N.register(
"Expand composer" : "تمديد الناظِم composer",
"Close composer" : "إغلاق الناظِم composer",
"Confirm" : "تأكيد",
+ "Revoke" : "سحب ",
"Tag: {name} deleted" : "تمّ حذف السمة: {name} ",
"An error occurred, unable to delete the tag." : "حدث خطأ؛ تعذّرَ حذف السِّمَة.",
"The tag will be deleted from all messages." : "سوف يتم حذف الوسم من جميع الرسائل.",
diff --git a/l10n/ar.json b/l10n/ar.json
index 4eb99edadc..af0f86b7fd 100644
--- a/l10n/ar.json
+++ b/l10n/ar.json
@@ -205,6 +205,7 @@
"Expand composer" : "تمديد الناظِم composer",
"Close composer" : "إغلاق الناظِم composer",
"Confirm" : "تأكيد",
+ "Revoke" : "سحب ",
"Tag: {name} deleted" : "تمّ حذف السمة: {name} ",
"An error occurred, unable to delete the tag." : "حدث خطأ؛ تعذّرَ حذف السِّمَة.",
"The tag will be deleted from all messages." : "سوف يتم حذف الوسم من جميع الرسائل.",
diff --git a/l10n/ast.js b/l10n/ast.js
index c54fa891d9..20081d83c7 100644
--- a/l10n/ast.js
+++ b/l10n/ast.js
@@ -85,6 +85,7 @@ OC.L10N.register(
"Expand composer" : "Espander el compositor",
"Close composer" : "Zarrar el compositor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"An error occurred, unable to delete the tag." : "Prodúxose un error, nun ye posible desaniciar la etiqueta.",
"Plain text" : "Testu ensin formatu",
"Rich text" : "Testu arriquecíu",
diff --git a/l10n/ast.json b/l10n/ast.json
index cde7c1a61a..b3799ea1d2 100644
--- a/l10n/ast.json
+++ b/l10n/ast.json
@@ -83,6 +83,7 @@
"Expand composer" : "Espander el compositor",
"Close composer" : "Zarrar el compositor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"An error occurred, unable to delete the tag." : "Prodúxose un error, nun ye posible desaniciar la etiqueta.",
"Plain text" : "Testu ensin formatu",
"Rich text" : "Testu arriquecíu",
diff --git a/l10n/bg.js b/l10n/bg.js
index a4bd837ee8..3eafd0b9f6 100644
--- a/l10n/bg.js
+++ b/l10n/bg.js
@@ -164,6 +164,7 @@ OC.L10N.register(
"Choose a file to share as a link" : "Изберете файл, който да споделите като връзка",
"_{count} attachment_::_{count} attachments_" : ["{count} прикачени файлове","{count} прикачени файлове"],
"Confirm" : "Потвърдете",
+ "Revoke" : "Отнемане",
"Plain text" : "Обикновен текст",
"Rich text" : "Форматиран текст",
"No messages in this folder" : "Няма съобщения",
diff --git a/l10n/bg.json b/l10n/bg.json
index c15aab380a..ebebb16e2c 100644
--- a/l10n/bg.json
+++ b/l10n/bg.json
@@ -162,6 +162,7 @@
"Choose a file to share as a link" : "Изберете файл, който да споделите като връзка",
"_{count} attachment_::_{count} attachments_" : ["{count} прикачени файлове","{count} прикачени файлове"],
"Confirm" : "Потвърдете",
+ "Revoke" : "Отнемане",
"Plain text" : "Обикновен текст",
"Rich text" : "Форматиран текст",
"No messages in this folder" : "Няма съобщения",
diff --git a/l10n/br.js b/l10n/br.js
index 9a6e06b7f3..6745c176fc 100644
--- a/l10n/br.js
+++ b/l10n/br.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Refresh" : "Freskaat",
"Choose" : "Dibab",
"Confirm" : "Kadarnañ",
+ "Revoke" : "Digargañ",
"Unfavorite" : "Digaretañ",
"Favorite" : "Pennrollañ",
"Back" : "Distro",
diff --git a/l10n/br.json b/l10n/br.json
index 1abcf90fba..b685e5fba9 100644
--- a/l10n/br.json
+++ b/l10n/br.json
@@ -27,6 +27,7 @@
"Refresh" : "Freskaat",
"Choose" : "Dibab",
"Confirm" : "Kadarnañ",
+ "Revoke" : "Digargañ",
"Unfavorite" : "Digaretañ",
"Favorite" : "Pennrollañ",
"Back" : "Distro",
diff --git a/l10n/ca.js b/l10n/ca.js
index 7be161b4e9..7f738c8917 100644
--- a/l10n/ca.js
+++ b/l10n/ca.js
@@ -206,6 +206,7 @@ OC.L10N.register(
"Expand composer" : "Ampliar el compositor",
"Close composer" : "Tanca finestra del compositor",
"Confirm" : "Confirma",
+ "Revoke" : "Revoca",
"Tag: {name} deleted" : "Etiqueta: {name} suprimida",
"An error occurred, unable to delete the tag." : "S'ha produït un error, no s'ha pogut suprimir l'etiqueta.",
"The tag will be deleted from all messages." : "L'etiqueta se suprimirà de tots els missatges.",
diff --git a/l10n/ca.json b/l10n/ca.json
index 8fdaae5813..dd6a9189ee 100644
--- a/l10n/ca.json
+++ b/l10n/ca.json
@@ -204,6 +204,7 @@
"Expand composer" : "Ampliar el compositor",
"Close composer" : "Tanca finestra del compositor",
"Confirm" : "Confirma",
+ "Revoke" : "Revoca",
"Tag: {name} deleted" : "Etiqueta: {name} suprimida",
"An error occurred, unable to delete the tag." : "S'ha produït un error, no s'ha pogut suprimir l'etiqueta.",
"The tag will be deleted from all messages." : "L'etiqueta se suprimirà de tots els missatges.",
diff --git a/l10n/cs.js b/l10n/cs.js
index 726997d075..19f6dc7be7 100644
--- a/l10n/cs.js
+++ b/l10n/cs.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Rozbalit dialog psaní",
"Close composer" : "Zavřít dialog psaní",
"Confirm" : "Potvrdit",
+ "Revoke" : "Odvolat",
"Tag: {name} deleted" : "Štítek: {name} smazán",
"An error occurred, unable to delete the tag." : "Došlo k chybě, štítek se nepodařilo smazat.",
"The tag will be deleted from all messages." : "Štítek bude smazán ze všech zpráv.",
diff --git a/l10n/cs.json b/l10n/cs.json
index 469f8d5a91..e55d26b08d 100644
--- a/l10n/cs.json
+++ b/l10n/cs.json
@@ -251,6 +251,7 @@
"Expand composer" : "Rozbalit dialog psaní",
"Close composer" : "Zavřít dialog psaní",
"Confirm" : "Potvrdit",
+ "Revoke" : "Odvolat",
"Tag: {name} deleted" : "Štítek: {name} smazán",
"An error occurred, unable to delete the tag." : "Došlo k chybě, štítek se nepodařilo smazat.",
"The tag will be deleted from all messages." : "Štítek bude smazán ze všech zpráv.",
diff --git a/l10n/da.js b/l10n/da.js
index 71aa01cdbe..5be3d62f6a 100644
--- a/l10n/da.js
+++ b/l10n/da.js
@@ -215,6 +215,7 @@ OC.L10N.register(
"Expand composer" : "Udvid composer",
"Close composer" : "Luk composer",
"Confirm" : "Bekræft",
+ "Revoke" : "Tilbagekald",
"Tag: {name} deleted" : "Tag: {name} slettet",
"An error occurred, unable to delete the tag." : "En fejl opstod, kunne ikke slette tagget",
"The tag will be deleted from all messages." : "Tagget bliver slettet fra alle beskeder.",
diff --git a/l10n/da.json b/l10n/da.json
index 672d4f47dc..262589fde3 100644
--- a/l10n/da.json
+++ b/l10n/da.json
@@ -213,6 +213,7 @@
"Expand composer" : "Udvid composer",
"Close composer" : "Luk composer",
"Confirm" : "Bekræft",
+ "Revoke" : "Tilbagekald",
"Tag: {name} deleted" : "Tag: {name} slettet",
"An error occurred, unable to delete the tag." : "En fejl opstod, kunne ikke slette tagget",
"The tag will be deleted from all messages." : "Tagget bliver slettet fra alle beskeder.",
diff --git a/l10n/de.js b/l10n/de.js
index ebd11596ce..c9dde59a99 100644
--- a/l10n/de.js
+++ b/l10n/de.js
@@ -137,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "Mail-Einstellungen",
"General" : "Allgemein",
"Set as default mail app" : "Als Standard-E-Mail-App festlegen",
+ "{email} (delegated)" : "{email} (Delegiert)",
"Add mail account" : "E-Mail-Konto hinzufügen",
"Appearance" : "Aussehen",
"Show all messages in thread" : "Alle Nachrichten der Unterhaltung anzeigen",
@@ -255,6 +256,21 @@ OC.L10N.register(
"Expand composer" : "Erstellungsbereich erweitern",
"Close composer" : "Erstellungsbereich schließen",
"Confirm" : "Bestätigen",
+ "Delegate access" : "Zugriff delegieren",
+ "Revoke" : "Widerrufen",
+ "{userId} will no longer be able to act on your behalf" : "{userId} wird nicht mehr in deinem Namen handeln können",
+ "Could not fetch delegates" : "Delegierte konnten nicht abgerufen werden",
+ "Delegated access to {userId}" : "Zugriff delegiert an {userId}",
+ "Could not delegate access" : "Zugriff konnte nicht delegiert werden",
+ "Revoked access for {userId}" : "Zugriff für {userId} widerrufen",
+ "Could not revoke delegation" : "Delegation konnte nicht widerrufen werden",
+ "Delegation" : "Delegation",
+ "Allow users to send, receive, and delete mail on your behalf" : "Benutzern ermöglichen, in deinem Namen E-Mails zu senden, zu empfangen und zu löschen",
+ "Revoke access" : "Zugriff widerrufen",
+ "Add delegate" : "Delegierten hinzufügen",
+ "Select a user" : "Einen Benutzer auswählen",
+ "They will be able to send, receive, and delete mail on your behalf" : "Diese können in deinem Namen E-Mails senden, empfangen und löschen",
+ "Revoke access?" : "Zugriff widerrufen?",
"Tag: {name} deleted" : "Schlagwort: {name} gelöscht",
"An error occurred, unable to delete the tag." : "Es ist ein Fehler aufgetreten, das Schlagwort konnte nicht gelöscht werden.",
"The tag will be deleted from all messages." : "Das Schlagwort wird aus allen Nachrichten gelöscht.",
@@ -451,8 +467,10 @@ OC.L10N.register(
"Remove account" : "Konto entfernen",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Das Konto für {email} und zwischengespeicherte E-Mail-Daten werden aus Nextcloud entfernt, jedoch nicht von deinem E-Mail-Provider.",
"Remove {email}" : "{email} entfernen",
+ "could not delete account" : "Konto konnte nicht gelöscht werden",
"Provisioned account is disabled" : "Bereitgestelltes Konto ist deaktiviert.",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Bitte melde dich mit einem Passwort an, um dieses Konto zu aktivieren. Die aktuelle Sitzung verwendet eine passwortlose Authentifizierung, z. B. SSO oder WebAuthn.",
+ "Delegate account" : "Konto delegieren",
"Show only subscribed folders" : "Nur abonnierte Ordner anzeigen",
"Add folder" : "Ordner hinzufügen",
"Folder name" : "Ordnername",
diff --git a/l10n/de.json b/l10n/de.json
index 924fb357f4..0b20de310c 100644
--- a/l10n/de.json
+++ b/l10n/de.json
@@ -135,6 +135,7 @@
"Mail settings" : "Mail-Einstellungen",
"General" : "Allgemein",
"Set as default mail app" : "Als Standard-E-Mail-App festlegen",
+ "{email} (delegated)" : "{email} (Delegiert)",
"Add mail account" : "E-Mail-Konto hinzufügen",
"Appearance" : "Aussehen",
"Show all messages in thread" : "Alle Nachrichten der Unterhaltung anzeigen",
@@ -253,6 +254,21 @@
"Expand composer" : "Erstellungsbereich erweitern",
"Close composer" : "Erstellungsbereich schließen",
"Confirm" : "Bestätigen",
+ "Delegate access" : "Zugriff delegieren",
+ "Revoke" : "Widerrufen",
+ "{userId} will no longer be able to act on your behalf" : "{userId} wird nicht mehr in deinem Namen handeln können",
+ "Could not fetch delegates" : "Delegierte konnten nicht abgerufen werden",
+ "Delegated access to {userId}" : "Zugriff delegiert an {userId}",
+ "Could not delegate access" : "Zugriff konnte nicht delegiert werden",
+ "Revoked access for {userId}" : "Zugriff für {userId} widerrufen",
+ "Could not revoke delegation" : "Delegation konnte nicht widerrufen werden",
+ "Delegation" : "Delegation",
+ "Allow users to send, receive, and delete mail on your behalf" : "Benutzern ermöglichen, in deinem Namen E-Mails zu senden, zu empfangen und zu löschen",
+ "Revoke access" : "Zugriff widerrufen",
+ "Add delegate" : "Delegierten hinzufügen",
+ "Select a user" : "Einen Benutzer auswählen",
+ "They will be able to send, receive, and delete mail on your behalf" : "Diese können in deinem Namen E-Mails senden, empfangen und löschen",
+ "Revoke access?" : "Zugriff widerrufen?",
"Tag: {name} deleted" : "Schlagwort: {name} gelöscht",
"An error occurred, unable to delete the tag." : "Es ist ein Fehler aufgetreten, das Schlagwort konnte nicht gelöscht werden.",
"The tag will be deleted from all messages." : "Das Schlagwort wird aus allen Nachrichten gelöscht.",
@@ -449,8 +465,10 @@
"Remove account" : "Konto entfernen",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Das Konto für {email} und zwischengespeicherte E-Mail-Daten werden aus Nextcloud entfernt, jedoch nicht von deinem E-Mail-Provider.",
"Remove {email}" : "{email} entfernen",
+ "could not delete account" : "Konto konnte nicht gelöscht werden",
"Provisioned account is disabled" : "Bereitgestelltes Konto ist deaktiviert.",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Bitte melde dich mit einem Passwort an, um dieses Konto zu aktivieren. Die aktuelle Sitzung verwendet eine passwortlose Authentifizierung, z. B. SSO oder WebAuthn.",
+ "Delegate account" : "Konto delegieren",
"Show only subscribed folders" : "Nur abonnierte Ordner anzeigen",
"Add folder" : "Ordner hinzufügen",
"Folder name" : "Ordnername",
diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index 03b277095e..56a61a1bdd 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -137,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "E-Mail-Einstellungen",
"General" : "Allgemein",
"Set as default mail app" : "Als Standard-E-Mail-App festlegen",
+ "{email} (delegated)" : "{email} (Delegiert)",
"Add mail account" : "E-Mail-Konto hinzufügen",
"Appearance" : "Aussehen",
"Show all messages in thread" : "Alle Nachrichten der Unterhaltung anzeigen",
@@ -255,6 +256,21 @@ OC.L10N.register(
"Expand composer" : "Erstellungsbereich erweitern",
"Close composer" : "Erstellungsbereich schließen",
"Confirm" : "Bestätigen",
+ "Delegate access" : "Zugriff delegieren",
+ "Revoke" : "Widerrufen",
+ "{userId} will no longer be able to act on your behalf" : "{userId} wird nicht mehr in Ihrem Namen handeln können",
+ "Could not fetch delegates" : "Delegierte konnten nicht abgerufen werden",
+ "Delegated access to {userId}" : "Zugriff delegiert an {userId}",
+ "Could not delegate access" : "Zugriff konnte nicht delegiert werden",
+ "Revoked access for {userId}" : "Zugriff für {userId} widerrufen",
+ "Could not revoke delegation" : "Delegation konnte nicht widerrufen werden",
+ "Delegation" : "Delegation",
+ "Allow users to send, receive, and delete mail on your behalf" : "Benutzern ermöglichen, in Ihrem Namen E-Mails zu senden, zu empfangen und zu löschen",
+ "Revoke access" : "Zugriff widerrufen",
+ "Add delegate" : "Delegierten hinzufügen",
+ "Select a user" : "Einen Benutzer auswählen",
+ "They will be able to send, receive, and delete mail on your behalf" : "Diese können in Ihrem Namen E-Mails senden, empfangen und löschen",
+ "Revoke access?" : "Zugriff widerrufen?",
"Tag: {name} deleted" : "Schlagwort: {name} gelöscht",
"An error occurred, unable to delete the tag." : "Es ist ein Fehler aufgetreten, das Schlagwort konnte nicht gelöscht werden.",
"The tag will be deleted from all messages." : "Das Schlagwort wird aus allen Nachrichten gelöscht.",
@@ -451,8 +467,10 @@ OC.L10N.register(
"Remove account" : "Konto entfernen",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Das Konto für {email} und zwischengespeicherte E-Mail-Daten werden aus Nextcloud entfernt, jedoch nicht von Ihrem E-Mail-Provider.",
"Remove {email}" : "{email} entfernen",
+ "could not delete account" : "Konto konnte nicht gelöscht werden",
"Provisioned account is disabled" : "Bereitgestelltes Konto ist deaktiviert",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Bitte melden Sie sich mit einem Passwort an, um dieses Konto zu aktivieren. Die aktuelle Sitzung verwendet eine passwortlose Authentifizierung, z. B. SSO oder WebAuthn.",
+ "Delegate account" : "Konto delegieren",
"Show only subscribed folders" : "Nur abonnierte Ordner anzeigen",
"Add folder" : "Ordner hinzufügen",
"Folder name" : "Ordnername",
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index 7f09d41552..cf774af40c 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -135,6 +135,7 @@
"Mail settings" : "E-Mail-Einstellungen",
"General" : "Allgemein",
"Set as default mail app" : "Als Standard-E-Mail-App festlegen",
+ "{email} (delegated)" : "{email} (Delegiert)",
"Add mail account" : "E-Mail-Konto hinzufügen",
"Appearance" : "Aussehen",
"Show all messages in thread" : "Alle Nachrichten der Unterhaltung anzeigen",
@@ -253,6 +254,21 @@
"Expand composer" : "Erstellungsbereich erweitern",
"Close composer" : "Erstellungsbereich schließen",
"Confirm" : "Bestätigen",
+ "Delegate access" : "Zugriff delegieren",
+ "Revoke" : "Widerrufen",
+ "{userId} will no longer be able to act on your behalf" : "{userId} wird nicht mehr in Ihrem Namen handeln können",
+ "Could not fetch delegates" : "Delegierte konnten nicht abgerufen werden",
+ "Delegated access to {userId}" : "Zugriff delegiert an {userId}",
+ "Could not delegate access" : "Zugriff konnte nicht delegiert werden",
+ "Revoked access for {userId}" : "Zugriff für {userId} widerrufen",
+ "Could not revoke delegation" : "Delegation konnte nicht widerrufen werden",
+ "Delegation" : "Delegation",
+ "Allow users to send, receive, and delete mail on your behalf" : "Benutzern ermöglichen, in Ihrem Namen E-Mails zu senden, zu empfangen und zu löschen",
+ "Revoke access" : "Zugriff widerrufen",
+ "Add delegate" : "Delegierten hinzufügen",
+ "Select a user" : "Einen Benutzer auswählen",
+ "They will be able to send, receive, and delete mail on your behalf" : "Diese können in Ihrem Namen E-Mails senden, empfangen und löschen",
+ "Revoke access?" : "Zugriff widerrufen?",
"Tag: {name} deleted" : "Schlagwort: {name} gelöscht",
"An error occurred, unable to delete the tag." : "Es ist ein Fehler aufgetreten, das Schlagwort konnte nicht gelöscht werden.",
"The tag will be deleted from all messages." : "Das Schlagwort wird aus allen Nachrichten gelöscht.",
@@ -449,8 +465,10 @@
"Remove account" : "Konto entfernen",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Das Konto für {email} und zwischengespeicherte E-Mail-Daten werden aus Nextcloud entfernt, jedoch nicht von Ihrem E-Mail-Provider.",
"Remove {email}" : "{email} entfernen",
+ "could not delete account" : "Konto konnte nicht gelöscht werden",
"Provisioned account is disabled" : "Bereitgestelltes Konto ist deaktiviert",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Bitte melden Sie sich mit einem Passwort an, um dieses Konto zu aktivieren. Die aktuelle Sitzung verwendet eine passwortlose Authentifizierung, z. B. SSO oder WebAuthn.",
+ "Delegate account" : "Konto delegieren",
"Show only subscribed folders" : "Nur abonnierte Ordner anzeigen",
"Add folder" : "Ordner hinzufügen",
"Folder name" : "Ordnername",
diff --git a/l10n/el.js b/l10n/el.js
index be9f34f2f1..5ba84d308c 100644
--- a/l10n/el.js
+++ b/l10n/el.js
@@ -217,6 +217,7 @@ OC.L10N.register(
"Expand composer" : "Ανάπτυξη συντάκτη",
"Close composer" : "Κλείσιμο συντάκτη",
"Confirm" : "Επιβεβαίωση",
+ "Revoke" : "Ανάκληση",
"Tag: {name} deleted" : "Η ετικέτα «{name)» διαγράφηκε",
"An error occurred, unable to delete the tag." : "Προέκυψε σφάλμα, δεν ήταν δυνατή η διαγραφή της ετικέτας.",
"The tag will be deleted from all messages." : "Η ετικέτα θα διαγραφεί από όλα τα μηνύματα.",
diff --git a/l10n/el.json b/l10n/el.json
index 9b8ee6e865..a6a3825c81 100644
--- a/l10n/el.json
+++ b/l10n/el.json
@@ -215,6 +215,7 @@
"Expand composer" : "Ανάπτυξη συντάκτη",
"Close composer" : "Κλείσιμο συντάκτη",
"Confirm" : "Επιβεβαίωση",
+ "Revoke" : "Ανάκληση",
"Tag: {name} deleted" : "Η ετικέτα «{name)» διαγράφηκε",
"An error occurred, unable to delete the tag." : "Προέκυψε σφάλμα, δεν ήταν δυνατή η διαγραφή της ετικέτας.",
"The tag will be deleted from all messages." : "Η ετικέτα θα διαγραφεί από όλα τα μηνύματα.",
diff --git a/l10n/en_GB.js b/l10n/en_GB.js
index 107a7f12a6..70eae8260d 100644
--- a/l10n/en_GB.js
+++ b/l10n/en_GB.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "Confirm",
+ "Revoke" : "Revoke",
"Tag: {name} deleted" : "Tag: {name} deleted",
"An error occurred, unable to delete the tag." : "An error occurred, unable to delete the tag.",
"The tag will be deleted from all messages." : "The tag will be deleted from all messages.",
diff --git a/l10n/en_GB.json b/l10n/en_GB.json
index 326225c0b2..4f9e7a7e70 100644
--- a/l10n/en_GB.json
+++ b/l10n/en_GB.json
@@ -251,6 +251,7 @@
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "Confirm",
+ "Revoke" : "Revoke",
"Tag: {name} deleted" : "Tag: {name} deleted",
"An error occurred, unable to delete the tag." : "An error occurred, unable to delete the tag.",
"The tag will be deleted from all messages." : "The tag will be deleted from all messages.",
diff --git a/l10n/eo.js b/l10n/eo.js
index 997ad9670c..5a451ff7d0 100644
--- a/l10n/eo.js
+++ b/l10n/eo.js
@@ -71,6 +71,7 @@ OC.L10N.register(
"Choose" : "Elekti",
"Choose a file to add as attachment" : "Elektu dosieron aldonotan kiel kunsendaĵon",
"Confirm" : "Konfirmi",
+ "Revoke" : "Senvalidigi",
"Plain text" : "Ebenaĵa teksto",
"No messages in this folder" : "Neniu mesaĝo en tiu dosierujo",
"Blind copy recipients only" : "Nur blindkopiaj ricevontoj",
diff --git a/l10n/eo.json b/l10n/eo.json
index 6a0f656ec1..2111560d83 100644
--- a/l10n/eo.json
+++ b/l10n/eo.json
@@ -69,6 +69,7 @@
"Choose" : "Elekti",
"Choose a file to add as attachment" : "Elektu dosieron aldonotan kiel kunsendaĵon",
"Confirm" : "Konfirmi",
+ "Revoke" : "Senvalidigi",
"Plain text" : "Ebenaĵa teksto",
"No messages in this folder" : "Neniu mesaĝo en tiu dosierujo",
"Blind copy recipients only" : "Nur blindkopiaj ricevontoj",
diff --git a/l10n/es.js b/l10n/es.js
index 508de909a6..eb96be8257 100644
--- a/l10n/es.js
+++ b/l10n/es.js
@@ -217,6 +217,7 @@ OC.L10N.register(
"Expand composer" : "Expandir compositor",
"Close composer" : "Cerrar compositor",
"Confirm" : "Confirmar",
+ "Revoke" : "Anular",
"Tag: {name} deleted" : "Etiqueta: {name} eliminada",
"An error occurred, unable to delete the tag." : "Ha ocurrido un error, no se ha podido borrar la etiqueta.",
"The tag will be deleted from all messages." : "La etiqueta se borrará de todos los mensajes.",
diff --git a/l10n/es.json b/l10n/es.json
index 67a443e20b..b84f1abe7e 100644
--- a/l10n/es.json
+++ b/l10n/es.json
@@ -215,6 +215,7 @@
"Expand composer" : "Expandir compositor",
"Close composer" : "Cerrar compositor",
"Confirm" : "Confirmar",
+ "Revoke" : "Anular",
"Tag: {name} deleted" : "Etiqueta: {name} eliminada",
"An error occurred, unable to delete the tag." : "Ha ocurrido un error, no se ha podido borrar la etiqueta.",
"The tag will be deleted from all messages." : "La etiqueta se borrará de todos los mensajes.",
diff --git a/l10n/es_419.js b/l10n/es_419.js
index b60867703d..e301043462 100644
--- a/l10n/es_419.js
+++ b/l10n/es_419.js
@@ -51,6 +51,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_419.json b/l10n/es_419.json
index 8e4cddc675..45bfa1eb8c 100644
--- a/l10n/es_419.json
+++ b/l10n/es_419.json
@@ -49,6 +49,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_AR.js b/l10n/es_AR.js
index c08b87cb03..0f8996cb97 100644
--- a/l10n/es_AR.js
+++ b/l10n/es_AR.js
@@ -49,6 +49,7 @@ OC.L10N.register(
"Choose" : "Elige",
"Choose a file to add as attachment" : "Seleccione el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Favorite" : "Favorito",
"Read" : "Leer",
"Edit tags" : "Editar etiquetas",
diff --git a/l10n/es_AR.json b/l10n/es_AR.json
index 0ec092aa5e..7d5ca436c3 100644
--- a/l10n/es_AR.json
+++ b/l10n/es_AR.json
@@ -47,6 +47,7 @@
"Choose" : "Elige",
"Choose a file to add as attachment" : "Seleccione el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Favorite" : "Favorito",
"Read" : "Leer",
"Edit tags" : "Editar etiquetas",
diff --git a/l10n/es_CL.js b/l10n/es_CL.js
index bb780d053e..035515089f 100644
--- a/l10n/es_CL.js
+++ b/l10n/es_CL.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_CL.json b/l10n/es_CL.json
index 8c1e270ca0..b422f11d57 100644
--- a/l10n/es_CL.json
+++ b/l10n/es_CL.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_CO.js b/l10n/es_CO.js
index 773f12eda3..c41f133ba3 100644
--- a/l10n/es_CO.js
+++ b/l10n/es_CO.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_CO.json b/l10n/es_CO.json
index 7dc3933674..a04a0288c3 100644
--- a/l10n/es_CO.json
+++ b/l10n/es_CO.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_CR.js b/l10n/es_CR.js
index 0f87362e5e..cb27762992 100644
--- a/l10n/es_CR.js
+++ b/l10n/es_CR.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_CR.json b/l10n/es_CR.json
index 8c98918ba9..83355c605d 100644
--- a/l10n/es_CR.json
+++ b/l10n/es_CR.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_DO.js b/l10n/es_DO.js
index 7dabc09326..2ce7270185 100644
--- a/l10n/es_DO.js
+++ b/l10n/es_DO.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_DO.json b/l10n/es_DO.json
index 5a7b503de0..481db589da 100644
--- a/l10n/es_DO.json
+++ b/l10n/es_DO.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_EC.js b/l10n/es_EC.js
index 5ea0e09048..b80c8dea8f 100644
--- a/l10n/es_EC.js
+++ b/l10n/es_EC.js
@@ -161,6 +161,7 @@ OC.L10N.register(
"Expand composer" : "Expandir redactor",
"Close composer" : "Cerrar redactor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Plain text" : "Texto sin formato",
"Rich text" : "Texto enriquecido",
"No messages in this folder" : "No hay mensajes en esta carpeta",
diff --git a/l10n/es_EC.json b/l10n/es_EC.json
index 04d18c20ed..ff168249cd 100644
--- a/l10n/es_EC.json
+++ b/l10n/es_EC.json
@@ -159,6 +159,7 @@
"Expand composer" : "Expandir redactor",
"Close composer" : "Cerrar redactor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Plain text" : "Texto sin formato",
"Rich text" : "Texto enriquecido",
"No messages in this folder" : "No hay mensajes en esta carpeta",
diff --git a/l10n/es_GT.js b/l10n/es_GT.js
index 7207227b6b..276994808f 100644
--- a/l10n/es_GT.js
+++ b/l10n/es_GT.js
@@ -99,6 +99,7 @@ OC.L10N.register(
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Choose a file to share as a link" : "Selecciona un archivo para compartir como enlace",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Plain text" : "Texto simple",
"Rich text" : "Texto enriquecido",
"No messages in this folder" : "No hay mensajes en esta carpeta",
diff --git a/l10n/es_GT.json b/l10n/es_GT.json
index f6d68bd4e0..363dcaf8b7 100644
--- a/l10n/es_GT.json
+++ b/l10n/es_GT.json
@@ -97,6 +97,7 @@
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Choose a file to share as a link" : "Selecciona un archivo para compartir como enlace",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Plain text" : "Texto simple",
"Rich text" : "Texto enriquecido",
"No messages in this folder" : "No hay mensajes en esta carpeta",
diff --git a/l10n/es_HN.js b/l10n/es_HN.js
index 6b32aad0ff..200fc13d06 100644
--- a/l10n/es_HN.js
+++ b/l10n/es_HN.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_HN.json b/l10n/es_HN.json
index c8c8474b65..aef8970668 100644
--- a/l10n/es_HN.json
+++ b/l10n/es_HN.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_MX.js b/l10n/es_MX.js
index b631f07e10..3577051456 100644
--- a/l10n/es_MX.js
+++ b/l10n/es_MX.js
@@ -195,6 +195,7 @@ OC.L10N.register(
"Expand composer" : "Expandir redactor",
"Close composer" : "Cerrar redactor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Tag: {name} deleted" : "Etiqueta: {name} eliminada",
"An error occurred, unable to delete the tag." : "Ha ocurrido un error, no se ha podido eliminar la etiqueta.",
"The tag will be deleted from all messages." : "La etiqueta se eliminará de todos los mensajes.",
diff --git a/l10n/es_MX.json b/l10n/es_MX.json
index 909b2bed0a..09f570edcf 100644
--- a/l10n/es_MX.json
+++ b/l10n/es_MX.json
@@ -193,6 +193,7 @@
"Expand composer" : "Expandir redactor",
"Close composer" : "Cerrar redactor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Tag: {name} deleted" : "Etiqueta: {name} eliminada",
"An error occurred, unable to delete the tag." : "Ha ocurrido un error, no se ha podido eliminar la etiqueta.",
"The tag will be deleted from all messages." : "La etiqueta se eliminará de todos los mensajes.",
diff --git a/l10n/es_NI.js b/l10n/es_NI.js
index 34bc12c0eb..677e312a29 100644
--- a/l10n/es_NI.js
+++ b/l10n/es_NI.js
@@ -53,6 +53,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_NI.json b/l10n/es_NI.json
index 46b29b57c0..631bca99a2 100644
--- a/l10n/es_NI.json
+++ b/l10n/es_NI.json
@@ -51,6 +51,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PA.js b/l10n/es_PA.js
index bddb75b7e7..3c46130679 100644
--- a/l10n/es_PA.js
+++ b/l10n/es_PA.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PA.json b/l10n/es_PA.json
index d97ef64cf4..536c0be2d3 100644
--- a/l10n/es_PA.json
+++ b/l10n/es_PA.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PE.js b/l10n/es_PE.js
index 438e97ea3a..dd92f0aa29 100644
--- a/l10n/es_PE.js
+++ b/l10n/es_PE.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PE.json b/l10n/es_PE.json
index bfeaa1e0b8..7e07d6ad55 100644
--- a/l10n/es_PE.json
+++ b/l10n/es_PE.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PR.js b/l10n/es_PR.js
index bddb75b7e7..3c46130679 100644
--- a/l10n/es_PR.js
+++ b/l10n/es_PR.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PR.json b/l10n/es_PR.json
index d97ef64cf4..536c0be2d3 100644
--- a/l10n/es_PR.json
+++ b/l10n/es_PR.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PY.js b/l10n/es_PY.js
index bc46def838..5ff25330ad 100644
--- a/l10n/es_PY.js
+++ b/l10n/es_PY.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_PY.json b/l10n/es_PY.json
index 87c604d29a..6e97a51ae2 100644
--- a/l10n/es_PY.json
+++ b/l10n/es_PY.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_SV.js b/l10n/es_SV.js
index 43a23cf751..f9ec6fe138 100644
--- a/l10n/es_SV.js
+++ b/l10n/es_SV.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_SV.json b/l10n/es_SV.json
index b644f16175..789b3a9763 100644
--- a/l10n/es_SV.json
+++ b/l10n/es_SV.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages in this folder" : "No hay mensajes en esta carpeta",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
diff --git a/l10n/es_UY.js b/l10n/es_UY.js
index bdc5a2a022..836984c2ec 100644
--- a/l10n/es_UY.js
+++ b/l10n/es_UY.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/es_UY.json b/l10n/es_UY.json
index faa72f88f2..acc4e5d0a4 100644
--- a/l10n/es_UY.json
+++ b/l10n/es_UY.json
@@ -50,6 +50,7 @@
"Choose" : "Seleccionar",
"Choose a file to add as attachment" : "Selecciona el archivo a agregar como adjunto",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Unfavorite" : "Quitar favorito",
"Favorite" : "Hacer favorito",
"Read" : "Leer",
diff --git a/l10n/et_EE.js b/l10n/et_EE.js
index 723547590a..0176552669 100644
--- a/l10n/et_EE.js
+++ b/l10n/et_EE.js
@@ -248,6 +248,7 @@ OC.L10N.register(
"Expand composer" : "Näita koostamisvaadet laiemana",
"Close composer" : "Sulge koostamisvaade",
"Confirm" : "Kinnita",
+ "Revoke" : "Tühista",
"Tag: {name} deleted" : "Silt: {name} on kustutatud",
"An error occurred, unable to delete the tag." : "Tekkis viga, silti ei õnnestu kustutada",
"The tag will be deleted from all messages." : "See silt saab olema eemaldatud kõikide kirjade juurest.",
diff --git a/l10n/et_EE.json b/l10n/et_EE.json
index b019f6cdea..ea1154c801 100644
--- a/l10n/et_EE.json
+++ b/l10n/et_EE.json
@@ -246,6 +246,7 @@
"Expand composer" : "Näita koostamisvaadet laiemana",
"Close composer" : "Sulge koostamisvaade",
"Confirm" : "Kinnita",
+ "Revoke" : "Tühista",
"Tag: {name} deleted" : "Silt: {name} on kustutatud",
"An error occurred, unable to delete the tag." : "Tekkis viga, silti ei õnnestu kustutada",
"The tag will be deleted from all messages." : "See silt saab olema eemaldatud kõikide kirjade juurest.",
diff --git a/l10n/eu.js b/l10n/eu.js
index f8b2537170..1d8c77eb93 100644
--- a/l10n/eu.js
+++ b/l10n/eu.js
@@ -199,6 +199,7 @@ OC.L10N.register(
"Expand composer" : "Hedatu egilea",
"Close composer" : "Itxi egilea",
"Confirm" : "Berretsi",
+ "Revoke" : "Ezeztatu",
"Tag: {name} deleted" : "Etiketa: {name} ezabatuta",
"An error occurred, unable to delete the tag." : "Errore bat gertatu da, ezin izan da etiketa ezabatu.",
"The tag will be deleted from all messages." : "Mezu guztietako etiketak ezabatuko dira.",
diff --git a/l10n/eu.json b/l10n/eu.json
index 029eb1a83d..99c437fece 100644
--- a/l10n/eu.json
+++ b/l10n/eu.json
@@ -197,6 +197,7 @@
"Expand composer" : "Hedatu egilea",
"Close composer" : "Itxi egilea",
"Confirm" : "Berretsi",
+ "Revoke" : "Ezeztatu",
"Tag: {name} deleted" : "Etiketa: {name} ezabatuta",
"An error occurred, unable to delete the tag." : "Errore bat gertatu da, ezin izan da etiketa ezabatu.",
"The tag will be deleted from all messages." : "Mezu guztietako etiketak ezabatuko dira.",
diff --git a/l10n/fa.js b/l10n/fa.js
index 8c58e67ea7..c28c7d8f0c 100644
--- a/l10n/fa.js
+++ b/l10n/fa.js
@@ -173,6 +173,7 @@ OC.L10N.register(
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "تائید",
+ "Revoke" : "لغو",
"Plain text" : "متن ساده",
"Rich text" : "متن غنی",
"No messages in this folder" : "هیچ پیامی در این پوشه وجود ندارد",
diff --git a/l10n/fa.json b/l10n/fa.json
index 43f8b0c935..67ac3fb0df 100644
--- a/l10n/fa.json
+++ b/l10n/fa.json
@@ -171,6 +171,7 @@
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "تائید",
+ "Revoke" : "لغو",
"Plain text" : "متن ساده",
"Rich text" : "متن غنی",
"No messages in this folder" : "هیچ پیامی در این پوشه وجود ندارد",
diff --git a/l10n/fi.js b/l10n/fi.js
index f3928be9d4..3d8a1a1fba 100644
--- a/l10n/fi.js
+++ b/l10n/fi.js
@@ -184,6 +184,7 @@ OC.L10N.register(
"Expand composer" : "Laajenna lähetysikkunaa",
"Close composer" : "Sulje lähetysikkuna",
"Confirm" : "Vahvista",
+ "Revoke" : "Peru oikeus",
"Plain text" : "Raakateksti",
"Rich text" : "Rikas teksti",
"No messages in this folder" : "Tässä kansiossa ei ole viestejä",
diff --git a/l10n/fi.json b/l10n/fi.json
index ae48043042..092d55d7e6 100644
--- a/l10n/fi.json
+++ b/l10n/fi.json
@@ -182,6 +182,7 @@
"Expand composer" : "Laajenna lähetysikkunaa",
"Close composer" : "Sulje lähetysikkuna",
"Confirm" : "Vahvista",
+ "Revoke" : "Peru oikeus",
"Plain text" : "Raakateksti",
"Rich text" : "Rikas teksti",
"No messages in this folder" : "Tässä kansiossa ei ole viestejä",
diff --git a/l10n/fr.js b/l10n/fr.js
index 99e7d0097e..1d3ac44134 100644
--- a/l10n/fr.js
+++ b/l10n/fr.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Déplier la fenêtre de composition",
"Close composer" : "Fermer la fenêtre de composition",
"Confirm" : "Confirmer",
+ "Revoke" : "Révoquer",
"Tag: {name} deleted" : "Étiquette : {name} supprimée",
"An error occurred, unable to delete the tag." : "Une erreur est survenue, impossible de supprimer l'étiquette.",
"The tag will be deleted from all messages." : "L'étiquette sera supprimée de tous les messages.",
diff --git a/l10n/fr.json b/l10n/fr.json
index 860bf1694e..ed4c50c434 100644
--- a/l10n/fr.json
+++ b/l10n/fr.json
@@ -251,6 +251,7 @@
"Expand composer" : "Déplier la fenêtre de composition",
"Close composer" : "Fermer la fenêtre de composition",
"Confirm" : "Confirmer",
+ "Revoke" : "Révoquer",
"Tag: {name} deleted" : "Étiquette : {name} supprimée",
"An error occurred, unable to delete the tag." : "Une erreur est survenue, impossible de supprimer l'étiquette.",
"The tag will be deleted from all messages." : "L'étiquette sera supprimée de tous les messages.",
diff --git a/l10n/ga.js b/l10n/ga.js
index a52f4d1c26..c2abee9e9e 100644
--- a/l10n/ga.js
+++ b/l10n/ga.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Cumadóir a leathnú",
"Close composer" : "Cumadóir dlúth",
"Confirm" : "Deimhnigh",
+ "Revoke" : "Chúlghairm",
"Tag: {name} deleted" : "Chlib: {name} scriosta",
"An error occurred, unable to delete the tag." : "Tharla earráid, níorbh fhéidir an chlib a scriosadh.",
"The tag will be deleted from all messages." : "Scriosfar an chlib ó gach teachtaireacht.",
diff --git a/l10n/ga.json b/l10n/ga.json
index f2c945866f..f44ac00f7b 100644
--- a/l10n/ga.json
+++ b/l10n/ga.json
@@ -251,6 +251,7 @@
"Expand composer" : "Cumadóir a leathnú",
"Close composer" : "Cumadóir dlúth",
"Confirm" : "Deimhnigh",
+ "Revoke" : "Chúlghairm",
"Tag: {name} deleted" : "Chlib: {name} scriosta",
"An error occurred, unable to delete the tag." : "Tharla earráid, níorbh fhéidir an chlib a scriosadh.",
"The tag will be deleted from all messages." : "Scriosfar an chlib ó gach teachtaireacht.",
diff --git a/l10n/gl.js b/l10n/gl.js
index 8ee6cfeba6..e4a07bb861 100644
--- a/l10n/gl.js
+++ b/l10n/gl.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Estender a xanela de redacción",
"Close composer" : "Pechar a xanela de redacción",
"Confirm" : "Confirmar",
+ "Revoke" : "Revogar",
"Tag: {name} deleted" : "Etiqueta: {name} eliminada",
"An error occurred, unable to delete the tag." : "Produciuse un erro, non é posíbel eliminar a etiqueta.",
"The tag will be deleted from all messages." : "Eliminarase a etiqueta de todas as mensaxes.",
diff --git a/l10n/gl.json b/l10n/gl.json
index a37c637462..e4c54ef0fa 100644
--- a/l10n/gl.json
+++ b/l10n/gl.json
@@ -251,6 +251,7 @@
"Expand composer" : "Estender a xanela de redacción",
"Close composer" : "Pechar a xanela de redacción",
"Confirm" : "Confirmar",
+ "Revoke" : "Revogar",
"Tag: {name} deleted" : "Etiqueta: {name} eliminada",
"An error occurred, unable to delete the tag." : "Produciuse un erro, non é posíbel eliminar a etiqueta.",
"The tag will be deleted from all messages." : "Eliminarase a etiqueta de todas as mensaxes.",
diff --git a/l10n/he.js b/l10n/he.js
index cbb5be3ffd..87ba755204 100644
--- a/l10n/he.js
+++ b/l10n/he.js
@@ -96,6 +96,7 @@ OC.L10N.register(
"Choose a file to add as attachment" : "בחירת קובץ להוספה כקובץ מצורף",
"Choose a file to share as a link" : "נא לבחור קובץ לשיתוף כקישור",
"Confirm" : "אימות",
+ "Revoke" : "שלילה",
"Plain text" : "טקסט פשוט",
"Rich text" : "טקסט עשיר",
"No messages in this folder" : "אין הודעות בתיקייה זו",
diff --git a/l10n/he.json b/l10n/he.json
index 8d3cc0eceb..d9662c5b4d 100644
--- a/l10n/he.json
+++ b/l10n/he.json
@@ -94,6 +94,7 @@
"Choose a file to add as attachment" : "בחירת קובץ להוספה כקובץ מצורף",
"Choose a file to share as a link" : "נא לבחור קובץ לשיתוף כקישור",
"Confirm" : "אימות",
+ "Revoke" : "שלילה",
"Plain text" : "טקסט פשוט",
"Rich text" : "טקסט עשיר",
"No messages in this folder" : "אין הודעות בתיקייה זו",
diff --git a/l10n/hr.js b/l10n/hr.js
index 0cedbdae6e..7465ef45d7 100644
--- a/l10n/hr.js
+++ b/l10n/hr.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Proširi sastavljač poruke",
"Close composer" : "Zatvori sastavljač poruke",
"Confirm" : "Potvrdi",
+ "Revoke" : "Opozovi",
"Tag: {name} deleted" : "Oznaka: {name} je obrisana",
"An error occurred, unable to delete the tag." : "Došlo je do pogreške, nije moguće izbrisati oznaku.",
"The tag will be deleted from all messages." : "Oznaka će biti uklonjena sa svih poruka.",
diff --git a/l10n/hr.json b/l10n/hr.json
index 2469092459..0780afa071 100644
--- a/l10n/hr.json
+++ b/l10n/hr.json
@@ -251,6 +251,7 @@
"Expand composer" : "Proširi sastavljač poruke",
"Close composer" : "Zatvori sastavljač poruke",
"Confirm" : "Potvrdi",
+ "Revoke" : "Opozovi",
"Tag: {name} deleted" : "Oznaka: {name} je obrisana",
"An error occurred, unable to delete the tag." : "Došlo je do pogreške, nije moguće izbrisati oznaku.",
"The tag will be deleted from all messages." : "Oznaka će biti uklonjena sa svih poruka.",
diff --git a/l10n/hu.js b/l10n/hu.js
index e9ddea6c49..13084923d7 100644
--- a/l10n/hu.js
+++ b/l10n/hu.js
@@ -177,6 +177,7 @@ OC.L10N.register(
"Expand composer" : "Szerkesztő kibontása",
"Close composer" : "Szerkesztő bezárása",
"Confirm" : "Megerősítés",
+ "Revoke" : "Visszavonás",
"Plain text" : "Egyszerű szöveg",
"Rich text" : "Formázott szöveg",
"No messages in this folder" : "Nincs üzenet a mappában!",
diff --git a/l10n/hu.json b/l10n/hu.json
index bb892cbc11..7c27372476 100644
--- a/l10n/hu.json
+++ b/l10n/hu.json
@@ -175,6 +175,7 @@
"Expand composer" : "Szerkesztő kibontása",
"Close composer" : "Szerkesztő bezárása",
"Confirm" : "Megerősítés",
+ "Revoke" : "Visszavonás",
"Plain text" : "Egyszerű szöveg",
"Rich text" : "Formázott szöveg",
"No messages in this folder" : "Nincs üzenet a mappában!",
diff --git a/l10n/ia.js b/l10n/ia.js
index 9d0ee0ff3f..d559cf7f16 100644
--- a/l10n/ia.js
+++ b/l10n/ia.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"Refresh" : "Refrescar",
"Choose a file to add as attachment" : "Selectiona un file pro adder como attachamento",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Favorite" : "Favorite",
"Back" : "Retro",
"Attendees" : "Participantes",
diff --git a/l10n/ia.json b/l10n/ia.json
index 15091b4b11..ed40308a58 100644
--- a/l10n/ia.json
+++ b/l10n/ia.json
@@ -22,6 +22,7 @@
"Refresh" : "Refrescar",
"Choose a file to add as attachment" : "Selectiona un file pro adder como attachamento",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"Favorite" : "Favorite",
"Back" : "Retro",
"Attendees" : "Participantes",
diff --git a/l10n/id.js b/l10n/id.js
index 9ef29cb266..d922917375 100644
--- a/l10n/id.js
+++ b/l10n/id.js
@@ -252,6 +252,7 @@ OC.L10N.register(
"Expand composer" : "Perluas penyusun",
"Close composer" : "Tutup penyusun",
"Confirm" : "Konfirmasi",
+ "Revoke" : "Cabut",
"Tag: {name} deleted" : "Tag: {name} dihapus",
"An error occurred, unable to delete the tag." : "Terjadi kesalahan, tidak dapat menghapus tag.",
"The tag will be deleted from all messages." : "Tag akan dihapus dari semua pesan.",
diff --git a/l10n/id.json b/l10n/id.json
index f24f1e8fe6..d66089a72b 100644
--- a/l10n/id.json
+++ b/l10n/id.json
@@ -250,6 +250,7 @@
"Expand composer" : "Perluas penyusun",
"Close composer" : "Tutup penyusun",
"Confirm" : "Konfirmasi",
+ "Revoke" : "Cabut",
"Tag: {name} deleted" : "Tag: {name} dihapus",
"An error occurred, unable to delete the tag." : "Terjadi kesalahan, tidak dapat menghapus tag.",
"The tag will be deleted from all messages." : "Tag akan dihapus dari semua pesan.",
diff --git a/l10n/is.js b/l10n/is.js
index 97aeac7632..912f970d72 100644
--- a/l10n/is.js
+++ b/l10n/is.js
@@ -202,6 +202,7 @@ OC.L10N.register(
"Expand composer" : "Þenja ritil",
"Close composer" : "Loka ritli",
"Confirm" : "Staðfesta",
+ "Revoke" : "Afturkalla",
"Tag: {name} deleted" : "Merki: {name} eytt",
"An error occurred, unable to delete the tag." : "Villa kom upp, gat ekki eytt merkinu.",
"The tag will be deleted from all messages." : "Merkinu verður eytt af öllum skilaboðum.",
diff --git a/l10n/is.json b/l10n/is.json
index 2f4884a804..45ffa9d032 100644
--- a/l10n/is.json
+++ b/l10n/is.json
@@ -200,6 +200,7 @@
"Expand composer" : "Þenja ritil",
"Close composer" : "Loka ritli",
"Confirm" : "Staðfesta",
+ "Revoke" : "Afturkalla",
"Tag: {name} deleted" : "Merki: {name} eytt",
"An error occurred, unable to delete the tag." : "Villa kom upp, gat ekki eytt merkinu.",
"The tag will be deleted from all messages." : "Merkinu verður eytt af öllum skilaboðum.",
diff --git a/l10n/it.js b/l10n/it.js
index a0ba68f0e8..3c3072059d 100644
--- a/l10n/it.js
+++ b/l10n/it.js
@@ -212,6 +212,7 @@ OC.L10N.register(
"Expand composer" : "Espandi compositore",
"Close composer" : "Chiudi compositore",
"Confirm" : "Conferma",
+ "Revoke" : "Revoca",
"Plain text" : "Testo semplice",
"Rich text" : "Testo formattato",
"No messages in this folder" : "Nessun messaggio in questa cartella",
diff --git a/l10n/it.json b/l10n/it.json
index d7b723f622..5b2ae3c409 100644
--- a/l10n/it.json
+++ b/l10n/it.json
@@ -210,6 +210,7 @@
"Expand composer" : "Espandi compositore",
"Close composer" : "Chiudi compositore",
"Confirm" : "Conferma",
+ "Revoke" : "Revoca",
"Plain text" : "Testo semplice",
"Rich text" : "Testo formattato",
"No messages in this folder" : "Nessun messaggio in questa cartella",
diff --git a/l10n/ja.js b/l10n/ja.js
index 870996d036..fb1bc85104 100644
--- a/l10n/ja.js
+++ b/l10n/ja.js
@@ -217,6 +217,7 @@ OC.L10N.register(
"Expand composer" : "コンポーザーを展開する",
"Close composer" : "コンポーザーを閉じる",
"Confirm" : "承認",
+ "Revoke" : "取り消す",
"Tag: {name} deleted" : "タグ:{name}削除済み",
"An error occurred, unable to delete the tag." : "タグ削除を無効にする時エラーが発生しました",
"The tag will be deleted from all messages." : "全てのメッセージからタグが削除されました",
diff --git a/l10n/ja.json b/l10n/ja.json
index 8ca60a8a13..988a442ca5 100644
--- a/l10n/ja.json
+++ b/l10n/ja.json
@@ -215,6 +215,7 @@
"Expand composer" : "コンポーザーを展開する",
"Close composer" : "コンポーザーを閉じる",
"Confirm" : "承認",
+ "Revoke" : "取り消す",
"Tag: {name} deleted" : "タグ:{name}削除済み",
"An error occurred, unable to delete the tag." : "タグ削除を無効にする時エラーが発生しました",
"The tag will be deleted from all messages." : "全てのメッセージからタグが削除されました",
diff --git a/l10n/ka.js b/l10n/ka.js
index 9c5958bb83..73e28b32a9 100644
--- a/l10n/ka.js
+++ b/l10n/ka.js
@@ -174,6 +174,7 @@ OC.L10N.register(
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "Confirm",
+ "Revoke" : "Revoke",
"Tag: {name} deleted" : "Tag: {name} deleted",
"An error occurred, unable to delete the tag." : "An error occurred, unable to delete the tag.",
"The tag will be deleted from all messages." : "The tag will be deleted from all messages.",
diff --git a/l10n/ka.json b/l10n/ka.json
index 325a27f288..d8ab5fbf15 100644
--- a/l10n/ka.json
+++ b/l10n/ka.json
@@ -172,6 +172,7 @@
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "Confirm",
+ "Revoke" : "Revoke",
"Tag: {name} deleted" : "Tag: {name} deleted",
"An error occurred, unable to delete the tag." : "An error occurred, unable to delete the tag.",
"The tag will be deleted from all messages." : "The tag will be deleted from all messages.",
diff --git a/l10n/ka_GE.js b/l10n/ka_GE.js
index 33ce784970..961c83b20b 100644
--- a/l10n/ka_GE.js
+++ b/l10n/ka_GE.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Choose" : "აირჩიეთ",
"Choose a file to add as attachment" : "დანართად დასამატებლად აირჩიეთ ფაილი",
"Confirm" : "დადასტურება",
+ "Revoke" : "წვდომის გაუქმება",
"Unfavorite" : "რჩეულებიდან ამოშლა",
"Favorite" : "რჩეული",
"Read" : "წაკითხვა",
diff --git a/l10n/ka_GE.json b/l10n/ka_GE.json
index c506755e2c..735ae20af1 100644
--- a/l10n/ka_GE.json
+++ b/l10n/ka_GE.json
@@ -50,6 +50,7 @@
"Choose" : "აირჩიეთ",
"Choose a file to add as attachment" : "დანართად დასამატებლად აირჩიეთ ფაილი",
"Confirm" : "დადასტურება",
+ "Revoke" : "წვდომის გაუქმება",
"Unfavorite" : "რჩეულებიდან ამოშლა",
"Favorite" : "რჩეული",
"Read" : "წაკითხვა",
diff --git a/l10n/ko.js b/l10n/ko.js
index f3d0b4421c..c745567553 100644
--- a/l10n/ko.js
+++ b/l10n/ko.js
@@ -179,6 +179,7 @@ OC.L10N.register(
"_{count} attachment_::_{count} attachments_" : ["{count}개의 첨부파일"],
"Untitled message" : "제목 없는 메시지",
"Confirm" : "확인",
+ "Revoke" : "취소",
"Tag: {name} deleted" : "태그: {name}이(가) 삭제됨",
"An error occurred, unable to delete the tag." : "오류가 발생하여 태그를 삭제할 수 없습니다",
"The tag will be deleted from all messages." : "태그가 모든 메시지로부터 삭제됩니다.",
diff --git a/l10n/ko.json b/l10n/ko.json
index 6ee8c76908..bd4f89f573 100644
--- a/l10n/ko.json
+++ b/l10n/ko.json
@@ -177,6 +177,7 @@
"_{count} attachment_::_{count} attachments_" : ["{count}개의 첨부파일"],
"Untitled message" : "제목 없는 메시지",
"Confirm" : "확인",
+ "Revoke" : "취소",
"Tag: {name} deleted" : "태그: {name}이(가) 삭제됨",
"An error occurred, unable to delete the tag." : "오류가 발생하여 태그를 삭제할 수 없습니다",
"The tag will be deleted from all messages." : "태그가 모든 메시지로부터 삭제됩니다.",
diff --git a/l10n/lo.js b/l10n/lo.js
index 6928c32989..3ce045b212 100644
--- a/l10n/lo.js
+++ b/l10n/lo.js
@@ -240,6 +240,7 @@ OC.L10N.register(
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "ຢືນຢັນ",
+ "Revoke" : "Revoke",
"Tag: {name} deleted" : "Tag: {name} deleted",
"An error occurred, unable to delete the tag." : "An error occurred, unable to delete the tag.",
"The tag will be deleted from all messages." : "The tag will be deleted from all messages.",
diff --git a/l10n/lo.json b/l10n/lo.json
index f34f2671d5..daa0c79779 100644
--- a/l10n/lo.json
+++ b/l10n/lo.json
@@ -238,6 +238,7 @@
"Expand composer" : "Expand composer",
"Close composer" : "Close composer",
"Confirm" : "ຢືນຢັນ",
+ "Revoke" : "Revoke",
"Tag: {name} deleted" : "Tag: {name} deleted",
"An error occurred, unable to delete the tag." : "An error occurred, unable to delete the tag.",
"The tag will be deleted from all messages." : "The tag will be deleted from all messages.",
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index f70561ef22..16860f5b3c 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Išskleisti rašymo langą",
"Close composer" : "Uždaryti rašymo langą",
"Confirm" : "Patvirtinti",
+ "Revoke" : "Panaikinti",
"Tag: {name} deleted" : "Žyma: {name} ištrinta",
"An error occurred, unable to delete the tag." : "Įvyko klaida, nepavyko ištrinti žymos.",
"The tag will be deleted from all messages." : "Žymė bus ištrinta iš visų pranešimų.",
diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json
index 9e8e4eafee..9860c7a79b 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -251,6 +251,7 @@
"Expand composer" : "Išskleisti rašymo langą",
"Close composer" : "Uždaryti rašymo langą",
"Confirm" : "Patvirtinti",
+ "Revoke" : "Panaikinti",
"Tag: {name} deleted" : "Žyma: {name} ištrinta",
"An error occurred, unable to delete the tag." : "Įvyko klaida, nepavyko ištrinti žymos.",
"The tag will be deleted from all messages." : "Žymė bus ištrinta iš visų pranešimų.",
diff --git a/l10n/lv.js b/l10n/lv.js
index b7b78589b9..9a10b22237 100644
--- a/l10n/lv.js
+++ b/l10n/lv.js
@@ -71,6 +71,7 @@ OC.L10N.register(
"Choose a file to add as attachment" : "Izvēlēties datni, ko pievienot kā pielikumu",
"Choose a file to share as a link" : "Jāizvēlas datne, ko kopīgot kā saiti",
"Confirm" : "Apstiprināt",
+ "Revoke" : "Atsaukt",
"No messages in this folder" : "Šajā mapē nav neviens ziņojums",
"Later today – {timeLocale}" : "Vēlāk šodien – {timeLocale}",
"Set reminder for later today" : "Iestatīt atgādinājumu vēlākam šodien",
diff --git a/l10n/lv.json b/l10n/lv.json
index d692f5c4c5..6599903b1c 100644
--- a/l10n/lv.json
+++ b/l10n/lv.json
@@ -69,6 +69,7 @@
"Choose a file to add as attachment" : "Izvēlēties datni, ko pievienot kā pielikumu",
"Choose a file to share as a link" : "Jāizvēlas datne, ko kopīgot kā saiti",
"Confirm" : "Apstiprināt",
+ "Revoke" : "Atsaukt",
"No messages in this folder" : "Šajā mapē nav neviens ziņojums",
"Later today – {timeLocale}" : "Vēlāk šodien – {timeLocale}",
"Set reminder for later today" : "Iestatīt atgādinājumu vēlākam šodien",
diff --git a/l10n/mk.js b/l10n/mk.js
index 1a938fcaf3..940398d309 100644
--- a/l10n/mk.js
+++ b/l10n/mk.js
@@ -165,6 +165,7 @@ OC.L10N.register(
"_{count} attachment_::_{count} attachments_" : ["{count} прилог","{count} прилози"],
"Untitled message" : "Неименувана порака",
"Confirm" : "Потврди",
+ "Revoke" : "Одземи",
"Plain text" : "Обичен текст",
"Rich text" : "Богат текст",
"No messages in this folder" : "Нема пораки во оваа папка",
diff --git a/l10n/mk.json b/l10n/mk.json
index 4f17a18059..7fb4e93431 100644
--- a/l10n/mk.json
+++ b/l10n/mk.json
@@ -163,6 +163,7 @@
"_{count} attachment_::_{count} attachments_" : ["{count} прилог","{count} прилози"],
"Untitled message" : "Неименувана порака",
"Confirm" : "Потврди",
+ "Revoke" : "Одземи",
"Plain text" : "Обичен текст",
"Rich text" : "Богат текст",
"No messages in this folder" : "Нема пораки во оваа папка",
diff --git a/l10n/mn.js b/l10n/mn.js
index 97132e95a0..abc9f6a682 100644
--- a/l10n/mn.js
+++ b/l10n/mn.js
@@ -246,6 +246,7 @@ OC.L10N.register(
"Expand composer" : "Бичигчийг өргөжүүлэх",
"Close composer" : "Бичигчийг хаах",
"Confirm" : "–ë–∞—Ç–ª–∞—Ö",
+ "Revoke" : "Цуцлах",
"Tag: {name} deleted" : "Таг: {name} устгагдлаа",
"An error occurred, unable to delete the tag." : "Алдаа гарлаа, таг устгах боломжгүй.",
"The tag will be deleted from all messages." : "Таг бүх зурвасаас устгагдана.",
diff --git a/l10n/mn.json b/l10n/mn.json
index e07dacd6ca..624ff98d66 100644
--- a/l10n/mn.json
+++ b/l10n/mn.json
@@ -244,6 +244,7 @@
"Expand composer" : "Бичигчийг өргөжүүлэх",
"Close composer" : "Бичигчийг хаах",
"Confirm" : "–ë–∞—Ç–ª–∞—Ö",
+ "Revoke" : "Цуцлах",
"Tag: {name} deleted" : "Таг: {name} устгагдлаа",
"An error occurred, unable to delete the tag." : "Алдаа гарлаа, таг устгах боломжгүй.",
"The tag will be deleted from all messages." : "Таг бүх зурвасаас устгагдана.",
diff --git a/l10n/nb.js b/l10n/nb.js
index 39216d26a6..3c07a2ca7d 100644
--- a/l10n/nb.js
+++ b/l10n/nb.js
@@ -205,6 +205,7 @@ OC.L10N.register(
"Expand composer" : "Utvid skrivebehandler",
"Close composer" : "Lukk skrivebehandler",
"Confirm" : "Bekreft",
+ "Revoke" : "Avslå",
"Tag: {name} deleted" : "Merke: {name} slettet",
"An error occurred, unable to delete the tag." : "En feil oppstod, ikke i stand til å slette merkelappen.",
"The tag will be deleted from all messages." : "Merkelappen slettes fra alle meldinger.",
diff --git a/l10n/nb.json b/l10n/nb.json
index b05da10c35..5c145f8bef 100644
--- a/l10n/nb.json
+++ b/l10n/nb.json
@@ -203,6 +203,7 @@
"Expand composer" : "Utvid skrivebehandler",
"Close composer" : "Lukk skrivebehandler",
"Confirm" : "Bekreft",
+ "Revoke" : "Avslå",
"Tag: {name} deleted" : "Merke: {name} slettet",
"An error occurred, unable to delete the tag." : "En feil oppstod, ikke i stand til å slette merkelappen.",
"The tag will be deleted from all messages." : "Merkelappen slettes fra alle meldinger.",
diff --git a/l10n/nl.js b/l10n/nl.js
index 05e87c5d92..e83c9e282d 100644
--- a/l10n/nl.js
+++ b/l10n/nl.js
@@ -243,6 +243,7 @@ OC.L10N.register(
"_{count} attachment_::_{count} attachments_" : ["{count} bijlagen","{count} bijlagen"],
"Untitled message" : "Naamloos bericht",
"Confirm" : "Bevestigen",
+ "Revoke" : "Intrekken",
"Tag: {name} deleted" : "Etiket: {name} verwijderd",
"An error occurred, unable to delete the tag." : "Er is een fout opgetreden, etiket kan niet verwijderd worden.",
"The tag will be deleted from all messages." : "Dit etiket wordt verwijderd uit alle berichten.",
diff --git a/l10n/nl.json b/l10n/nl.json
index b7466e80fb..38492d5475 100644
--- a/l10n/nl.json
+++ b/l10n/nl.json
@@ -241,6 +241,7 @@
"_{count} attachment_::_{count} attachments_" : ["{count} bijlagen","{count} bijlagen"],
"Untitled message" : "Naamloos bericht",
"Confirm" : "Bevestigen",
+ "Revoke" : "Intrekken",
"Tag: {name} deleted" : "Etiket: {name} verwijderd",
"An error occurred, unable to delete the tag." : "Er is een fout opgetreden, etiket kan niet verwijderd worden.",
"The tag will be deleted from all messages." : "Dit etiket wordt verwijderd uit alle berichten.",
diff --git a/l10n/oc.js b/l10n/oc.js
index 413ec978e2..cbebcdc326 100644
--- a/l10n/oc.js
+++ b/l10n/oc.js
@@ -45,6 +45,7 @@ OC.L10N.register(
"Choose" : "Causir",
"Choose a file to add as attachment" : "Causissètz un fichièr de jónher al messatge",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages" : "Cap de messatge",
"Tomorrow – {timeLocale}" : "Deman – {timeLocale}",
"Favorite" : "Favorit",
diff --git a/l10n/oc.json b/l10n/oc.json
index 0e7e7054bf..db7388fcb7 100644
--- a/l10n/oc.json
+++ b/l10n/oc.json
@@ -43,6 +43,7 @@
"Choose" : "Causir",
"Choose a file to add as attachment" : "Causissètz un fichièr de jónher al messatge",
"Confirm" : "Confirmar",
+ "Revoke" : "Revocar",
"No messages" : "Cap de messatge",
"Tomorrow – {timeLocale}" : "Deman – {timeLocale}",
"Favorite" : "Favorit",
diff --git a/l10n/pl.js b/l10n/pl.js
index 59136d9b49..619b5256ab 100644
--- a/l10n/pl.js
+++ b/l10n/pl.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Rozwiń edytor wiadomości",
"Close composer" : "Zamknij edytor wiadomości",
"Confirm" : "Potwierdź",
+ "Revoke" : "Cofnij",
"Tag: {name} deleted" : "Tag: {name} usunięty",
"An error occurred, unable to delete the tag." : "Wystąpił błąd, nie udało się usunąć tagu.",
"The tag will be deleted from all messages." : "Tag zostanie usunięty ze wszystkich wiadomości.",
diff --git a/l10n/pl.json b/l10n/pl.json
index d31c7a79d6..f2545f9208 100644
--- a/l10n/pl.json
+++ b/l10n/pl.json
@@ -251,6 +251,7 @@
"Expand composer" : "Rozwiń edytor wiadomości",
"Close composer" : "Zamknij edytor wiadomości",
"Confirm" : "Potwierdź",
+ "Revoke" : "Cofnij",
"Tag: {name} deleted" : "Tag: {name} usunięty",
"An error occurred, unable to delete the tag." : "Wystąpił błąd, nie udało się usunąć tagu.",
"The tag will be deleted from all messages." : "Tag zostanie usunięty ze wszystkich wiadomości.",
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index ecbd7b0e43..7b93cd8330 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -255,6 +255,7 @@ OC.L10N.register(
"Expand composer" : "Expandir compositor",
"Close composer" : "Fechar compositor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revogar",
"Tag: {name} deleted" : "Etiqueta: {name} excluída",
"An error occurred, unable to delete the tag." : "Ocorreu um erro, não foi possível excluir a etiqueta.",
"The tag will be deleted from all messages." : "A etiqueta será excluída de todas as mensagens.",
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index 887045288c..11c8a206ba 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -253,6 +253,7 @@
"Expand composer" : "Expandir compositor",
"Close composer" : "Fechar compositor",
"Confirm" : "Confirmar",
+ "Revoke" : "Revogar",
"Tag: {name} deleted" : "Etiqueta: {name} excluída",
"An error occurred, unable to delete the tag." : "Ocorreu um erro, não foi possível excluir a etiqueta.",
"The tag will be deleted from all messages." : "A etiqueta será excluída de todas as mensagens.",
diff --git a/l10n/pt_PT.js b/l10n/pt_PT.js
index df611f97a1..4e31e59534 100644
--- a/l10n/pt_PT.js
+++ b/l10n/pt_PT.js
@@ -119,6 +119,7 @@ OC.L10N.register(
"Choose" : "Escolher",
"Choose a file to add as attachment" : "Escolha um ficheiro para adicionar como anexo",
"Confirm" : "Confirmar",
+ "Revoke" : "Revogar",
"Plain text" : "Texto simples",
"No messages" : "Sem mensagens",
"Could not delete message" : "Não foi possível apagar a mensagem",
diff --git a/l10n/pt_PT.json b/l10n/pt_PT.json
index 011241fa6b..fed189a2d7 100644
--- a/l10n/pt_PT.json
+++ b/l10n/pt_PT.json
@@ -117,6 +117,7 @@
"Choose" : "Escolher",
"Choose a file to add as attachment" : "Escolha um ficheiro para adicionar como anexo",
"Confirm" : "Confirmar",
+ "Revoke" : "Revogar",
"Plain text" : "Texto simples",
"No messages" : "Sem mensagens",
"Could not delete message" : "Não foi possível apagar a mensagem",
diff --git a/l10n/ro.js b/l10n/ro.js
index 42778bc2cf..b7e1fe42c6 100644
--- a/l10n/ro.js
+++ b/l10n/ro.js
@@ -158,6 +158,7 @@ OC.L10N.register(
"Expand composer" : "Expandează mesajul",
"Close composer" : "Închide mesajul",
"Confirm" : "Confirmă",
+ "Revoke" : "Revocă",
"Tag: {name} deleted" : "Eticheta: {name} a fost ștearsă",
"An error occurred, unable to delete the tag." : "Eticheta nu a putut fi ștearsă.",
"The tag will be deleted from all messages." : "Eticheta va fi ștearsă pentru toate mesajele.",
diff --git a/l10n/ro.json b/l10n/ro.json
index 18f6b27a04..b44ebdb016 100644
--- a/l10n/ro.json
+++ b/l10n/ro.json
@@ -156,6 +156,7 @@
"Expand composer" : "Expandează mesajul",
"Close composer" : "Închide mesajul",
"Confirm" : "Confirmă",
+ "Revoke" : "Revocă",
"Tag: {name} deleted" : "Eticheta: {name} a fost ștearsă",
"An error occurred, unable to delete the tag." : "Eticheta nu a putut fi ștearsă.",
"The tag will be deleted from all messages." : "Eticheta va fi ștearsă pentru toate mesajele.",
diff --git a/l10n/ru.js b/l10n/ru.js
index 31bbf68bd4..6258d9abe4 100644
--- a/l10n/ru.js
+++ b/l10n/ru.js
@@ -247,6 +247,7 @@ OC.L10N.register(
"_{count} attachment_::_{count} attachments_" : ["{count} вложение","{count} вложения","{count} вложений","{count} вложений"],
"Untitled message" : "Сообщение без названия",
"Confirm" : "Подтвердить",
+ "Revoke" : "Отозвать",
"Tag: {name} deleted" : "Тег: {name} удален",
"An error occurred, unable to delete the tag." : "Произошла ошибка, не удалось удалить тег.",
"The tag will be deleted from all messages." : "Тег будет удален из всех сообщений.",
diff --git a/l10n/ru.json b/l10n/ru.json
index 583658b1ba..7d625faf64 100644
--- a/l10n/ru.json
+++ b/l10n/ru.json
@@ -245,6 +245,7 @@
"_{count} attachment_::_{count} attachments_" : ["{count} вложение","{count} вложения","{count} вложений","{count} вложений"],
"Untitled message" : "Сообщение без названия",
"Confirm" : "Подтвердить",
+ "Revoke" : "Отозвать",
"Tag: {name} deleted" : "Тег: {name} удален",
"An error occurred, unable to delete the tag." : "Произошла ошибка, не удалось удалить тег.",
"The tag will be deleted from all messages." : "Тег будет удален из всех сообщений.",
diff --git a/l10n/sc.js b/l10n/sc.js
index c64c6592dd..283e8b54fe 100644
--- a/l10n/sc.js
+++ b/l10n/sc.js
@@ -96,6 +96,7 @@ OC.L10N.register(
"Choose a file to add as attachment" : "Sèbera un'archìviu de agiùnghere comente alligongiadu",
"Choose a file to share as a link" : "Sèbera un'archìviu de cumpartzire comente ligòngiu",
"Confirm" : "Cunfirma",
+ "Revoke" : "Rèvoca",
"Plain text" : "Testu simple",
"Rich text" : "Testu formatadu",
"No messages" : "Perunu messàgiu",
diff --git a/l10n/sc.json b/l10n/sc.json
index 90456afcaa..b092e9731b 100644
--- a/l10n/sc.json
+++ b/l10n/sc.json
@@ -94,6 +94,7 @@
"Choose a file to add as attachment" : "Sèbera un'archìviu de agiùnghere comente alligongiadu",
"Choose a file to share as a link" : "Sèbera un'archìviu de cumpartzire comente ligòngiu",
"Confirm" : "Cunfirma",
+ "Revoke" : "Rèvoca",
"Plain text" : "Testu simple",
"Rich text" : "Testu formatadu",
"No messages" : "Perunu messàgiu",
diff --git a/l10n/sk.js b/l10n/sk.js
index 8667dc6004..8566e50461 100644
--- a/l10n/sk.js
+++ b/l10n/sk.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Zobraziť editor správ",
"Close composer" : "Zatvoriť editor správ",
"Confirm" : "Potvrdiť",
+ "Revoke" : "Odvolať",
"Tag: {name} deleted" : "Štítok: {name} odstránený",
"An error occurred, unable to delete the tag." : "Vyskytla sa chyba, nie je možné odstrániť štítok.",
"The tag will be deleted from all messages." : "Štítok bude odstránený zo všetkých správ.",
diff --git a/l10n/sk.json b/l10n/sk.json
index 75d7e9acce..d2c98febc3 100644
--- a/l10n/sk.json
+++ b/l10n/sk.json
@@ -251,6 +251,7 @@
"Expand composer" : "Zobraziť editor správ",
"Close composer" : "Zatvoriť editor správ",
"Confirm" : "Potvrdiť",
+ "Revoke" : "Odvolať",
"Tag: {name} deleted" : "Štítok: {name} odstránený",
"An error occurred, unable to delete the tag." : "Vyskytla sa chyba, nie je možné odstrániť štítok.",
"The tag will be deleted from all messages." : "Štítok bude odstránený zo všetkých správ.",
diff --git a/l10n/sl.js b/l10n/sl.js
index 4eaab4a2ab..37adecb804 100644
--- a/l10n/sl.js
+++ b/l10n/sl.js
@@ -160,6 +160,7 @@ OC.L10N.register(
"_{count} attachment_::_{count} attachments_" : ["{count} priloga","{count} prilogi","{count} priloge","{count} prilog"],
"Untitled message" : "Nenaslovljeno sporočilo",
"Confirm" : "Potrdi",
+ "Revoke" : "Prekliči",
"Plain text" : "Besedilno",
"Rich text" : "Obogateno besedilo",
"No messages in this folder" : "V tej mapi ni sporočil",
diff --git a/l10n/sl.json b/l10n/sl.json
index eb78dd72c2..67b39db649 100644
--- a/l10n/sl.json
+++ b/l10n/sl.json
@@ -158,6 +158,7 @@
"_{count} attachment_::_{count} attachments_" : ["{count} priloga","{count} prilogi","{count} priloge","{count} prilog"],
"Untitled message" : "Nenaslovljeno sporočilo",
"Confirm" : "Potrdi",
+ "Revoke" : "Prekliči",
"Plain text" : "Besedilno",
"Rich text" : "Obogateno besedilo",
"No messages in this folder" : "V tej mapi ni sporočil",
diff --git a/l10n/sq.js b/l10n/sq.js
index 6386273ba4..3261e0439b 100644
--- a/l10n/sq.js
+++ b/l10n/sq.js
@@ -53,6 +53,7 @@ OC.L10N.register(
"Choose" : "Zgjidhni",
"Choose a file to add as attachment" : "Zgjidhni një kartelë që të shtohet si bashkëngjitje",
"Confirm" : "Konfirmo",
+ "Revoke" : "Anulo",
"Unfavorite" : "Jo i/e preferuar",
"Favorite" : "I/E Preferuar",
"Read" : "Lexoni",
diff --git a/l10n/sq.json b/l10n/sq.json
index eb723015ff..25492716db 100644
--- a/l10n/sq.json
+++ b/l10n/sq.json
@@ -51,6 +51,7 @@
"Choose" : "Zgjidhni",
"Choose a file to add as attachment" : "Zgjidhni një kartelë që të shtohet si bashkëngjitje",
"Confirm" : "Konfirmo",
+ "Revoke" : "Anulo",
"Unfavorite" : "Jo i/e preferuar",
"Favorite" : "I/E Preferuar",
"Read" : "Lexoni",
diff --git a/l10n/sr.js b/l10n/sr.js
index 6e869de912..a48650a556 100644
--- a/l10n/sr.js
+++ b/l10n/sr.js
@@ -236,6 +236,7 @@ OC.L10N.register(
"Expand composer" : "Развиј састављач",
"Close composer" : "Затвори састављач",
"Confirm" : "Потврди",
+ "Revoke" : "Повуци",
"Tag: {name} deleted" : "Ознака: {name} је обрисана",
"An error occurred, unable to delete the tag." : "Дошло је до грешке, не може да се обрише ознака.",
"The tag will be deleted from all messages." : "Ознака ће се обрисати из свих порука.",
diff --git a/l10n/sr.json b/l10n/sr.json
index 932755bd40..46749abac3 100644
--- a/l10n/sr.json
+++ b/l10n/sr.json
@@ -234,6 +234,7 @@
"Expand composer" : "Развиј састављач",
"Close composer" : "Затвори састављач",
"Confirm" : "Потврди",
+ "Revoke" : "Повуци",
"Tag: {name} deleted" : "Ознака: {name} је обрисана",
"An error occurred, unable to delete the tag." : "Дошло је до грешке, не може да се обрише ознака.",
"The tag will be deleted from all messages." : "Ознака ће се обрисати из свих порука.",
diff --git a/l10n/sv.js b/l10n/sv.js
index c7d075236d..30a878e3d1 100644
--- a/l10n/sv.js
+++ b/l10n/sv.js
@@ -247,6 +247,7 @@ OC.L10N.register(
"_{count} attachment_::_{count} attachments_" : ["{count} bilaga","{count} bilagor"],
"Untitled message" : "Namnlöst meddelande",
"Confirm" : "Bekräfta",
+ "Revoke" : "Återkalla",
"Tag: {name} deleted" : "Tagg: {name} borttagen",
"An error occurred, unable to delete the tag." : "Ett fel uppstod, det gick inte att ta bort taggen.",
"The tag will be deleted from all messages." : "Taggen kommer att raderas från alla meddelanden.",
diff --git a/l10n/sv.json b/l10n/sv.json
index 1fc2770061..d0235ba83b 100644
--- a/l10n/sv.json
+++ b/l10n/sv.json
@@ -245,6 +245,7 @@
"_{count} attachment_::_{count} attachments_" : ["{count} bilaga","{count} bilagor"],
"Untitled message" : "Namnlöst meddelande",
"Confirm" : "Bekräfta",
+ "Revoke" : "Återkalla",
"Tag: {name} deleted" : "Tagg: {name} borttagen",
"An error occurred, unable to delete the tag." : "Ett fel uppstod, det gick inte att ta bort taggen.",
"The tag will be deleted from all messages." : "Taggen kommer att raderas från alla meddelanden.",
diff --git a/l10n/sw.js b/l10n/sw.js
index 396f345a82..d00d0a1f6d 100644
--- a/l10n/sw.js
+++ b/l10n/sw.js
@@ -54,6 +54,7 @@ OC.L10N.register(
"Choose a file to share as a link" : "Chagua faili kushirikisha kama kiungo",
"_{count} attachment_::_{count} attachments_" : ["{count} attachment","{count} attachments"],
"Confirm" : "Thibitisha",
+ "Revoke" : "Revoke",
"No messages" : "Hakuna jumbe",
"Later today – {timeLocale}" : "Baadaye leo-{timeLocale}",
"Set reminder for later today" : "Set reminder for later today",
diff --git a/l10n/sw.json b/l10n/sw.json
index ae37b698fb..a05269e413 100644
--- a/l10n/sw.json
+++ b/l10n/sw.json
@@ -52,6 +52,7 @@
"Choose a file to share as a link" : "Chagua faili kushirikisha kama kiungo",
"_{count} attachment_::_{count} attachments_" : ["{count} attachment","{count} attachments"],
"Confirm" : "Thibitisha",
+ "Revoke" : "Revoke",
"No messages" : "Hakuna jumbe",
"Later today – {timeLocale}" : "Baadaye leo-{timeLocale}",
"Set reminder for later today" : "Set reminder for later today",
diff --git a/l10n/ta.js b/l10n/ta.js
deleted file mode 100644
index 19d5a0ebc5..0000000000
--- a/l10n/ta.js
+++ /dev/null
@@ -1,50 +0,0 @@
-OC.L10N.register(
- "mail",
- {
- "Important" : "முக்கியமான ",
- "Work" : "வேலை",
- "Personal" : "தனிப்பட்ட",
- "Save" : "சேமிக்க ",
- "Connect" : "இணைக்க",
- "Name" : "பெயர்",
- "Password" : "கடவுச்சொல்",
- "None" : "ஒன்றுமில்லை",
- "Cancel" : "இரத்து செய்க",
- "General" : "பொதுவான",
- "Delete" : "நீக்குக",
- "Search" : "Search",
- "Refresh" : "மீள் ஏற்றுக",
- "Ok" : "Ok",
- "Choose" : "தெரிவுசெய்க ",
- "Favorite" : "விருப்பமான",
- "Back" : "பின்னுக்கு",
- "Attendees" : "பங்கேற்பாளர்கள்",
- "Description" : "விவரிப்பு",
- "Create" : "உருவாக்குக",
- "Select" : "Select",
- "Remove" : "அகற்றுக",
- "Today" : "இன்று",
- "Yesterday" : "நேற்று",
- "Favorites" : "விருப்பங்கள்",
- "Other" : "மற்றவை",
- "Translate" : "Translate",
- "Move" : "Move",
- "Folder name" : "கோப்புறை பெயர்",
- "Saving" : "Saving",
- "Rename" : "பெயர்மாற்றம்",
- "Add" : "சேர்க்க",
- "Close" : "மூடுக",
- "Date" : "Date",
- "Tags" : "சீட்டுகள்",
- "To:" : "இற்கு",
- "Help" : "உதவி",
- "Actions" : "செயல்கள்",
- "delete" : "நீக்குக",
- "Edit" : "தொகுக்க",
- "User" : "User",
- "Host" : "ஓம்புனர்",
- "Port" : "துறை ",
- "Group" : "Group",
- "All" : "எல்லாம்"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/l10n/ta.json b/l10n/ta.json
deleted file mode 100644
index 67a9493319..0000000000
--- a/l10n/ta.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{ "translations": {
- "Important" : "முக்கியமான ",
- "Work" : "வேலை",
- "Personal" : "தனிப்பட்ட",
- "Save" : "சேமிக்க ",
- "Connect" : "இணைக்க",
- "Name" : "பெயர்",
- "Password" : "கடவுச்சொல்",
- "None" : "ஒன்றுமில்லை",
- "Cancel" : "இரத்து செய்க",
- "General" : "பொதுவான",
- "Delete" : "நீக்குக",
- "Search" : "Search",
- "Refresh" : "மீள் ஏற்றுக",
- "Ok" : "Ok",
- "Choose" : "தெரிவுசெய்க ",
- "Favorite" : "விருப்பமான",
- "Back" : "பின்னுக்கு",
- "Attendees" : "பங்கேற்பாளர்கள்",
- "Description" : "விவரிப்பு",
- "Create" : "உருவாக்குக",
- "Select" : "Select",
- "Remove" : "அகற்றுக",
- "Today" : "இன்று",
- "Yesterday" : "நேற்று",
- "Favorites" : "விருப்பங்கள்",
- "Other" : "மற்றவை",
- "Translate" : "Translate",
- "Move" : "Move",
- "Folder name" : "கோப்புறை பெயர்",
- "Saving" : "Saving",
- "Rename" : "பெயர்மாற்றம்",
- "Add" : "சேர்க்க",
- "Close" : "மூடுக",
- "Date" : "Date",
- "Tags" : "சீட்டுகள்",
- "To:" : "இற்கு",
- "Help" : "உதவி",
- "Actions" : "செயல்கள்",
- "delete" : "நீக்குக",
- "Edit" : "தொகுக்க",
- "User" : "User",
- "Host" : "ஓம்புனர்",
- "Port" : "துறை ",
- "Group" : "Group",
- "All" : "எல்லாம்"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-}
\ No newline at end of file
diff --git a/l10n/th.js b/l10n/th.js
index 65d7028213..876f997602 100644
--- a/l10n/th.js
+++ b/l10n/th.js
@@ -35,6 +35,7 @@ OC.L10N.register(
"Choose" : "เลือก",
"Choose a file to add as attachment" : "เลือกไฟล์ที่ต้องการแนบ",
"Confirm" : "ยืนยัน",
+ "Revoke" : "เพิกถอน",
"Favorite" : "รายการโปรด",
"Read" : "อ่าน",
"Edit tags" : "แก้ไขแท็ก",
diff --git a/l10n/th.json b/l10n/th.json
index 5b7c7af488..cbdb299707 100644
--- a/l10n/th.json
+++ b/l10n/th.json
@@ -33,6 +33,7 @@
"Choose" : "เลือก",
"Choose a file to add as attachment" : "เลือกไฟล์ที่ต้องการแนบ",
"Confirm" : "ยืนยัน",
+ "Revoke" : "เพิกถอน",
"Favorite" : "รายการโปรด",
"Read" : "อ่าน",
"Edit tags" : "แก้ไขแท็ก",
diff --git a/l10n/tr.js b/l10n/tr.js
index 63f78b068d..47b1741452 100644
--- a/l10n/tr.js
+++ b/l10n/tr.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "Oluşturucuyu genişlet",
"Close composer" : "Oluşturucuyu kapat",
"Confirm" : "Onayla",
+ "Revoke" : "Geçersiz kıl",
"Tag: {name} deleted" : "Etiket: {name} silindi",
"An error occurred, unable to delete the tag." : "Bir sorun çıktı. Etiket silinemedi.",
"The tag will be deleted from all messages." : "Etiket tüm iletilerden silinecek.",
diff --git a/l10n/tr.json b/l10n/tr.json
index 536eb44587..b75501f7d4 100644
--- a/l10n/tr.json
+++ b/l10n/tr.json
@@ -251,6 +251,7 @@
"Expand composer" : "Oluşturucuyu genişlet",
"Close composer" : "Oluşturucuyu kapat",
"Confirm" : "Onayla",
+ "Revoke" : "Geçersiz kıl",
"Tag: {name} deleted" : "Etiket: {name} silindi",
"An error occurred, unable to delete the tag." : "Bir sorun çıktı. Etiket silinemedi.",
"The tag will be deleted from all messages." : "Etiket tüm iletilerden silinecek.",
diff --git a/l10n/ug.js b/l10n/ug.js
index e4a57afe25..6398c1f38e 100644
--- a/l10n/ug.js
+++ b/l10n/ug.js
@@ -250,6 +250,7 @@ OC.L10N.register(
"Expand composer" : "كومپوزىتورنى كېڭەيتىڭ",
"Close composer" : "كومپوزىتورنى تاقاش",
"Confirm" : "جەزملەشتۈرۈڭ",
+ "Revoke" : "بىكار قىلىش",
"Tag: {name} deleted" : "خەتكۈچ: {name} ئۆچۈرۈلدى",
"An error occurred, unable to delete the tag." : "خەتكۈچنى ئۆچۈرەلمەي خاتالىق كۆرۈلدى.",
"The tag will be deleted from all messages." : "خەتكۈچ بارلىق ئۇچۇرلاردىن ئۆچۈرۈلىدۇ.",
diff --git a/l10n/ug.json b/l10n/ug.json
index c960abfc98..60c9af716b 100644
--- a/l10n/ug.json
+++ b/l10n/ug.json
@@ -248,6 +248,7 @@
"Expand composer" : "كومپوزىتورنى كېڭەيتىڭ",
"Close composer" : "كومپوزىتورنى تاقاش",
"Confirm" : "جەزملەشتۈرۈڭ",
+ "Revoke" : "بىكار قىلىش",
"Tag: {name} deleted" : "خەتكۈچ: {name} ئۆچۈرۈلدى",
"An error occurred, unable to delete the tag." : "خەتكۈچنى ئۆچۈرەلمەي خاتالىق كۆرۈلدى.",
"The tag will be deleted from all messages." : "خەتكۈچ بارلىق ئۇچۇرلاردىن ئۆچۈرۈلىدۇ.",
diff --git a/l10n/uk.js b/l10n/uk.js
index 251cb848c3..6e519b6896 100644
--- a/l10n/uk.js
+++ b/l10n/uk.js
@@ -218,6 +218,7 @@ OC.L10N.register(
"Expand composer" : "Розгорнути редактор",
"Close composer" : "Закрити редактор",
"Confirm" : "Підтвердити",
+ "Revoke" : "Відкликати",
"Tag: {name} deleted" : "Мітка: {name} вилучено",
"An error occurred, unable to delete the tag." : "Пимилка під час вилучення мітки.",
"The tag will be deleted from all messages." : "Мітку буде вилучено зі всіх листів.",
diff --git a/l10n/uk.json b/l10n/uk.json
index 0d90caa8e9..3ad8e90c7c 100644
--- a/l10n/uk.json
+++ b/l10n/uk.json
@@ -216,6 +216,7 @@
"Expand composer" : "Розгорнути редактор",
"Close composer" : "Закрити редактор",
"Confirm" : "Підтвердити",
+ "Revoke" : "Відкликати",
"Tag: {name} deleted" : "Мітка: {name} вилучено",
"An error occurred, unable to delete the tag." : "Пимилка під час вилучення мітки.",
"The tag will be deleted from all messages." : "Мітку буде вилучено зі всіх листів.",
diff --git a/l10n/vi.js b/l10n/vi.js
index 0aa249ff40..4855155bbd 100644
--- a/l10n/vi.js
+++ b/l10n/vi.js
@@ -86,6 +86,7 @@ OC.L10N.register(
"Choose a file to add as attachment" : "Chọn một tệp để thêm dưới dạng tệp đính kèm",
"Choose a file to share as a link" : "Chọn một tệp để chia sẻ dưới dạng liên kết",
"Confirm" : "Xác nhận",
+ "Revoke" : "Thu hồi",
"No messages" : "Không có tin nhắn",
"Blind copy recipients only" : "Chỉ người nhận bản sao ẩn",
"Later today – {timeLocale}" : "Sau này - {timeLocale}",
diff --git a/l10n/vi.json b/l10n/vi.json
index 2d08fbde39..0a1ce06310 100644
--- a/l10n/vi.json
+++ b/l10n/vi.json
@@ -84,6 +84,7 @@
"Choose a file to add as attachment" : "Chọn một tệp để thêm dưới dạng tệp đính kèm",
"Choose a file to share as a link" : "Chọn một tệp để chia sẻ dưới dạng liên kết",
"Confirm" : "Xác nhận",
+ "Revoke" : "Thu hồi",
"No messages" : "Không có tin nhắn",
"Blind copy recipients only" : "Chỉ người nhận bản sao ẩn",
"Later today – {timeLocale}" : "Sau này - {timeLocale}",
diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js
index 4d5a03322f..400f7d41d5 100644
--- a/l10n/zh_CN.js
+++ b/l10n/zh_CN.js
@@ -253,6 +253,7 @@ OC.L10N.register(
"Expand composer" : "展开编辑器",
"Close composer" : "关闭编辑器",
"Confirm" : "确认",
+ "Revoke" : "撤销",
"Tag: {name} deleted" : "标签:{name} 已删除",
"An error occurred, unable to delete the tag." : "发生错误,无法删除标签。",
"The tag will be deleted from all messages." : "将从所有邮件中删除此标签。",
diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json
index f5c3d4e193..646b414a99 100644
--- a/l10n/zh_CN.json
+++ b/l10n/zh_CN.json
@@ -251,6 +251,7 @@
"Expand composer" : "展开编辑器",
"Close composer" : "关闭编辑器",
"Confirm" : "确认",
+ "Revoke" : "撤销",
"Tag: {name} deleted" : "标签:{name} 已删除",
"An error occurred, unable to delete the tag." : "发生错误,无法删除标签。",
"The tag will be deleted from all messages." : "将从所有邮件中删除此标签。",
diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js
index d2137e763f..60493ff6ea 100644
--- a/l10n/zh_HK.js
+++ b/l10n/zh_HK.js
@@ -93,6 +93,8 @@ OC.L10N.register(
"SMTP Port" : "SMTP 連接埠",
"SMTP User" : "SMTP 賬號",
"SMTP Password" : "SMTP 密碼",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google 需要 OAuth 驗證。若您的 Nextcloud 管理員尚未設定 Google OAuth,您可以改用 Google 應用程式密碼。",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft 需要 OAuth 驗證。請聯絡您的 Nextcloud 管理員,在管理設定中設定 Microsoft OAuth。",
"Account settings" : "賬號設定",
"Aliases" : "别名",
"Alias to S/MIME certificate mapping" : "别名到 S/MIME 證書映射",
@@ -135,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "電郵設定",
"General" : "一般",
"Set as default mail app" : "設置為默認郵件應用",
+ "{email} (delegated)" : "{email}(已委派)",
"Add mail account" : "添加電郵帳戶",
"Appearance" : "外觀",
"Show all messages in thread" : "顯示線中的所有訊息",
@@ -253,6 +256,21 @@ OC.L10N.register(
"Expand composer" : "展開編輯器",
"Close composer" : "關閉編輯器",
"Confirm" : "確認",
+ "Delegate access" : "委派存取權限",
+ "Revoke" : "撤銷",
+ "{userId} will no longer be able to act on your behalf" : "{userId} 將無法再代表你執行操作",
+ "Could not fetch delegates" : "無法取得委派使用者",
+ "Delegated access to {userId}" : "已向 {userId} 委派存取權限",
+ "Could not delegate access" : "無法委派存取權限",
+ "Revoked access for {userId}" : "已撤銷 {userId} 的存取權限",
+ "Could not revoke delegation" : "無法撤銷委派",
+ "Delegation" : "委派",
+ "Allow users to send, receive, and delete mail on your behalf" : "允許使用者代表你傳送、接收及刪除郵件",
+ "Revoke access" : "撤銷存取權限",
+ "Add delegate" : "新增委派使用者",
+ "Select a user" : "選擇使用者",
+ "They will be able to send, receive, and delete mail on your behalf" : "他們將能代表你傳送、接收及刪除郵件",
+ "Revoke access?" : "撤銷存取權限?",
"Tag: {name} deleted" : "標籤:{name} 已刪除",
"An error occurred, unable to delete the tag." : "發生錯誤,無法刪除標籤。",
"The tag will be deleted from all messages." : "該標籤將從所有訊息刪除。",
@@ -449,8 +467,10 @@ OC.L10N.register(
"Remove account" : "移除賬號",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email} 賬號與已快取的電子郵件將會從 Nextcloud 移除,但不會從您的電子郵件提供商移除。",
"Remove {email}" : "移除 {email}",
+ "could not delete account" : "無法刪除帳戶",
"Provisioned account is disabled" : "預配帳戶已禁用",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "請使用密碼登錄以啟用此帳戶。目前會話正在使用無密碼身份驗證,例如 SSO 或 WebAuthn。",
+ "Delegate account" : "委派帳戶",
"Show only subscribed folders" : "僅顯示已訂閱的資料夾",
"Add folder" : "添加資料夾",
"Folder name" : "資料夾名稱",
@@ -623,6 +643,9 @@ OC.L10N.register(
"Reply to sender only" : "僅回覆寄件人",
"Mark as unfavorite" : "取消標記我的最愛",
"Mark as favorite" : "標記為我的最愛",
+ "To:" : "收件者:",
+ "Cc:" : "副本:",
+ "Bcc:" : "密件副本:",
"Unsubscribe via link" : "透過連結取消訂閱",
"Unsubscribing will stop all messages from the mailing list {sender}" : "取消訂閱將停止來自郵寄名單 {sender} 的所有消息",
"Send unsubscribe email" : "傳送取消訂閱電子郵件",
diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json
index c14f974806..b104c58c4a 100644
--- a/l10n/zh_HK.json
+++ b/l10n/zh_HK.json
@@ -91,6 +91,8 @@
"SMTP Port" : "SMTP 連接埠",
"SMTP User" : "SMTP 賬號",
"SMTP Password" : "SMTP 密碼",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google 需要 OAuth 驗證。若您的 Nextcloud 管理員尚未設定 Google OAuth,您可以改用 Google 應用程式密碼。",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft 需要 OAuth 驗證。請聯絡您的 Nextcloud 管理員,在管理設定中設定 Microsoft OAuth。",
"Account settings" : "賬號設定",
"Aliases" : "别名",
"Alias to S/MIME certificate mapping" : "别名到 S/MIME 證書映射",
@@ -133,6 +135,7 @@
"Mail settings" : "電郵設定",
"General" : "一般",
"Set as default mail app" : "設置為默認郵件應用",
+ "{email} (delegated)" : "{email}(已委派)",
"Add mail account" : "添加電郵帳戶",
"Appearance" : "外觀",
"Show all messages in thread" : "顯示線中的所有訊息",
@@ -251,6 +254,21 @@
"Expand composer" : "展開編輯器",
"Close composer" : "關閉編輯器",
"Confirm" : "確認",
+ "Delegate access" : "委派存取權限",
+ "Revoke" : "撤銷",
+ "{userId} will no longer be able to act on your behalf" : "{userId} 將無法再代表你執行操作",
+ "Could not fetch delegates" : "無法取得委派使用者",
+ "Delegated access to {userId}" : "已向 {userId} 委派存取權限",
+ "Could not delegate access" : "無法委派存取權限",
+ "Revoked access for {userId}" : "已撤銷 {userId} 的存取權限",
+ "Could not revoke delegation" : "無法撤銷委派",
+ "Delegation" : "委派",
+ "Allow users to send, receive, and delete mail on your behalf" : "允許使用者代表你傳送、接收及刪除郵件",
+ "Revoke access" : "撤銷存取權限",
+ "Add delegate" : "新增委派使用者",
+ "Select a user" : "選擇使用者",
+ "They will be able to send, receive, and delete mail on your behalf" : "他們將能代表你傳送、接收及刪除郵件",
+ "Revoke access?" : "撤銷存取權限?",
"Tag: {name} deleted" : "標籤:{name} 已刪除",
"An error occurred, unable to delete the tag." : "發生錯誤,無法刪除標籤。",
"The tag will be deleted from all messages." : "該標籤將從所有訊息刪除。",
@@ -447,8 +465,10 @@
"Remove account" : "移除賬號",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email} 賬號與已快取的電子郵件將會從 Nextcloud 移除,但不會從您的電子郵件提供商移除。",
"Remove {email}" : "移除 {email}",
+ "could not delete account" : "無法刪除帳戶",
"Provisioned account is disabled" : "預配帳戶已禁用",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "請使用密碼登錄以啟用此帳戶。目前會話正在使用無密碼身份驗證,例如 SSO 或 WebAuthn。",
+ "Delegate account" : "委派帳戶",
"Show only subscribed folders" : "僅顯示已訂閱的資料夾",
"Add folder" : "添加資料夾",
"Folder name" : "資料夾名稱",
@@ -621,6 +641,9 @@
"Reply to sender only" : "僅回覆寄件人",
"Mark as unfavorite" : "取消標記我的最愛",
"Mark as favorite" : "標記為我的最愛",
+ "To:" : "收件者:",
+ "Cc:" : "副本:",
+ "Bcc:" : "密件副本:",
"Unsubscribe via link" : "透過連結取消訂閱",
"Unsubscribing will stop all messages from the mailing list {sender}" : "取消訂閱將停止來自郵寄名單 {sender} 的所有消息",
"Send unsubscribe email" : "傳送取消訂閱電子郵件",
diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js
index 079c17847a..471ed796f5 100644
--- a/l10n/zh_TW.js
+++ b/l10n/zh_TW.js
@@ -255,6 +255,7 @@ OC.L10N.register(
"Expand composer" : "展開編輯器",
"Close composer" : "關閉編輯器",
"Confirm" : "確認",
+ "Revoke" : "撤銷",
"Tag: {name} deleted" : "標籤:{name} 已刪除",
"An error occurred, unable to delete the tag." : "遇到錯誤,無法刪除標籤。",
"The tag will be deleted from all messages." : "該標籤將從所有訊息刪除。",
diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json
index 2f4cda4134..2510b5cf9b 100644
--- a/l10n/zh_TW.json
+++ b/l10n/zh_TW.json
@@ -253,6 +253,7 @@
"Expand composer" : "展開編輯器",
"Close composer" : "關閉編輯器",
"Confirm" : "確認",
+ "Revoke" : "撤銷",
"Tag: {name} deleted" : "標籤:{name} 已刪除",
"An error occurred, unable to delete the tag." : "遇到錯誤,無法刪除標籤。",
"The tag will be deleted from all messages." : "該標籤將從所有訊息刪除。",
From 5dd4fd14cf85b420685a3e4915255d7167a40c03 Mon Sep 17 00:00:00 2001
From: Grigory V
Date: Fri, 15 May 2026 08:40:32 +0200
Subject: [PATCH 029/228] feat(Agents.md): add styling instructions
Signed-off-by: Grigory V
---
AGENTS.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/AGENTS.md b/AGENTS.md
index 31b5aed5c8..b91db95b1a 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -142,3 +142,11 @@ fix(deps): Update package dependencies
AI-assisted: OpenCode (Claude Haiku 4.5)
Signed-off-by: Name
```
+
+### Styling
+
+For all CSS colors, spacing, and dimensions, you must use the standard Nextcloud CSS variables.
+
+Do not leave any magic numbers. If you need more specific control over dimensions use `calc(x*var)` when necessary.
+
+You can find the CSS variables already in use in this repository, and the full documentation available at this link: https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/css.html.
From 119a96bec966268116776044c6866dc547a801ff Mon Sep 17 00:00:00 2001
From: nextcloud-command
Date: Fri, 15 May 2026 07:07:58 +0000
Subject: [PATCH 030/228] fix(dns): Update public suffix list
Signed-off-by: GitHub
---
resources/public_suffix_list.dat | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/resources/public_suffix_list.dat b/resources/public_suffix_list.dat
index d30d5c07a0..37e4479c48 100644
--- a/resources/public_suffix_list.dat
+++ b/resources/public_suffix_list.dat
@@ -5,8 +5,8 @@
// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat,
// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported.
-// VERSION: 2026-04-30_05-52-37_UTC
-// COMMIT: 66c9bda3aa96409830cb6fc4396b39eadb889274
+// VERSION: 2026-05-14_08-35-31_UTC
+// COMMIT: e452c7058d6946bd76952b128c12f5ce87a5acb8
// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/.
@@ -6157,7 +6157,6 @@ k12.mo.us
k12.ms.us
k12.mt.us
k12.nc.us
-// k12.nd.us - Bug 1028347 - Removed at request of Travis Rosso
k12.ne.us
k12.nh.us
k12.nj.us
@@ -6239,8 +6238,6 @@ cc.mt.us
lib.mt.us
cc.nc.us
lib.nc.us
-cc.nd.us
-lib.nd.us
cc.ne.us
lib.ne.us
cc.nh.us
@@ -6824,7 +6821,7 @@ org.zw
// newGTLDs
-// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2026-04-15T16:04:02Z
+// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2026-04-30T16:18:08Z
// This list is auto-generated, don't edit it manually.
// aaa : American Automobile Association, Inc.
// https://www.iana.org/domains/root/db/aaa.html
@@ -7010,7 +7007,7 @@ anquan
// https://www.iana.org/domains/root/db/anz.html
anz
-// aol : Yahoo Inc.
+// aol : AOL Media LLC
// https://www.iana.org/domains/root/db/aol.html
aol
@@ -12820,10 +12817,6 @@ craft.me
// Submitted by Ales Krajnik
realm.cz
-// Crisp IM SAS : https://crisp.chat/
-// Submitted by Baptiste Jamin
-on.crisp.email
-
// Cryptonomic : https://cryptonomic.net/
// Submitted by Andrew Cady
*.cryptonomic.net
@@ -14065,6 +14058,10 @@ ltd.ng
ngo.ng
plc.ng
+// Hostinger : https://hostinger.com
+// Submitted by Valentinas Cirba
+hstgr.cloud
+
// HostyHosting : https://hostyhosting.com
hostyhosting.io
@@ -16009,6 +16006,11 @@ reservd.testing.thingdust.io
// Submitted by Christian Franke
tickets.io
+// Tigris Data, Inc. : https://www.tigrisdata.com
+// Submitted by Bo Cao
+t3.storage.dev
+t3.storageapi.dev
+
// Tlon.io : https://tlon.io
// Submitted by Mark Staarink
arvo.network
@@ -16355,6 +16357,8 @@ zeabur.app
// Zerops : https://zerops.io/
// Submitted by Zerops Team
*.zerops.app
+prg1-zerops.zone
+*.zerops.zone
// Zine EOOD : https://zine.bg/
// Submitted by Martin Angelov
From 0eaad6fb1f1408d1b17a3a3ceca27583f5b5fac2 Mon Sep 17 00:00:00 2001
From: greta
Date: Mon, 19 Jan 2026 11:05:12 +0100
Subject: [PATCH 031/228] feat: add html and source editing support
AI-assisted: OpenCode (gpt-5.4)
AI-assisted: Claude Code (Claude Sonnet 4.6)
Signed-off-by: greta
Signed-off-by: Daniel Kesselberg
---
src/components/SignatureSettings.vue | 4 +-
src/components/TextEditor.vue | 81 ++++++++++++++++++--
src/tests/unit/components/TextEditor.spec.js | 74 ++++++++++++++++++
3 files changed, 152 insertions(+), 7 deletions(-)
diff --git a/src/components/SignatureSettings.vue b/src/components/SignatureSettings.vue
index c45f74e066..e5bdc18d27 100644
--- a/src/components/SignatureSettings.vue
+++ b/src/components/SignatureSettings.vue
@@ -257,9 +257,9 @@ export default {
.warning-large-signature {
color: darkorange;
}
-
+/* it's a bit hard to make it work without this max-width in the modal because it overlaps with the sidebar of the modal */
:deep(.ck.ck-toolbar-dropdown>.ck-dropdown__panel) {
- max-width: 34vw;
+ max-width: 19vw;
}
diff --git a/src/components/TextEditor.vue b/src/components/TextEditor.vue
index c7e7889760..9f970fdae1 100644
--- a/src/components/TextEditor.vue
+++ b/src/components/TextEditor.vue
@@ -30,7 +30,7 @@ import {
Base64UploadAdapter,
BlockQuote,
Bold,
- DecoupledEditor,
+ ClassicEditor,
DropdownView,
Essentials,
FindAndReplace,
@@ -46,6 +46,7 @@ import {
Mention,
Paragraph,
RemoveFormat,
+ SourceEditing,
Strikethrough,
Subscript,
Superscript,
@@ -153,6 +154,7 @@ export default {
RemoveFormat,
Base64UploadAdapter,
MailPlugin,
+ SourceEditing,
TextDirectionPlugin,
])
toolbar.unshift(...[
@@ -177,6 +179,7 @@ export default {
'link',
'removeFormat',
'findAndReplace',
+ 'sourceEditing',
])
}
@@ -185,8 +188,11 @@ export default {
emojiTribute: null,
contactMentionQuery: null,
textSmiles: [],
+ sourceEditingInputHandler: null,
+ sourceEditingModeHandler: null,
+ sourceEditingDebounceTimer: null,
ready: false,
- editor: DecoupledEditor,
+ editor: ClassicEditor,
config: {
licenseKey: 'GPL',
placeholder: this.placeholder,
@@ -220,14 +226,28 @@ export default {
htmlSupport: {
allow: [
+ 'table',
+ 'tbody',
+ 'td',
+ 'tfoot',
+ 'th',
+ 'thead',
+ 'tr',
+ 'figure',
+ {
+ name: 'a',
+ attributes: ['title', 'name', 'id'],
+ classes: true,
+ styles: true,
+ },
{
name: 'img',
- attributes: {
- 'data-cid': true,
- },
+ attributes: ['src', 'alt', 'title', 'width', 'height', 'data-cid', 'loading'],
+ styles: true,
},
],
},
+
},
}
},
@@ -236,7 +256,45 @@ export default {
this.loadEditorTranslations(getLanguage())
},
+ beforeDestroy() {
+ this.unregisterSourceEditingInputListener()
+
+ if (this.editorInstance?.plugins.has('SourceEditing') && this.sourceEditingModeHandler) {
+ this.editorInstance.plugins.get('SourceEditing').off('change:isSourceEditingMode', this.sourceEditingModeHandler)
+ }
+ },
+
methods: {
+ registerSourceEditingInputListener() {
+ const textarea = this.editorInstance.ui.getEditableElement('sourceEditing:main')
+
+ if (!textarea || this.sourceEditingInputHandler) {
+ return
+ }
+
+ this.sourceEditingInputHandler = () => {
+ clearTimeout(this.sourceEditingDebounceTimer)
+ this.sourceEditingDebounceTimer = setTimeout(() => {
+ this.editorInstance.plugins.get('SourceEditing').updateEditorData()
+ }, 300)
+ }
+
+ textarea.addEventListener('input', this.sourceEditingInputHandler)
+ },
+
+ unregisterSourceEditingInputListener() {
+ clearTimeout(this.sourceEditingDebounceTimer)
+ this.sourceEditingDebounceTimer = null
+
+ if (!this.sourceEditingInputHandler) {
+ return
+ }
+
+ const textarea = this.editorInstance?.ui.getEditableElement('sourceEditing:main')
+ textarea?.removeEventListener('input', this.sourceEditingInputHandler)
+ this.sourceEditingInputHandler = null
+ },
+
getLink(text) {
const results = searchProvider(text)
if (results.length === 1 && !results[0].title.toLowerCase().includes(text.toLowerCase())) {
@@ -496,6 +554,19 @@ export default {
}
}, { priority: 'high' })
+ if (editor.plugins.has('SourceEditing')) {
+ this.sourceEditingModeHandler = (_event, _name, isSourceEditingMode) => {
+ if (isSourceEditingMode) {
+ this.registerSourceEditingInputListener()
+ return
+ }
+
+ this.unregisterSourceEditingInputListener()
+ }
+
+ editor.plugins.get('SourceEditing').on('change:isSourceEditingMode', this.sourceEditingModeHandler)
+ }
+
editor.keystrokes.set('Ctrl+Enter', (event) => {
logger.debug('Detected Ctrl+Enter/Cmd+Enter', event)
this.$emit('submit', editor)
diff --git a/src/tests/unit/components/TextEditor.spec.js b/src/tests/unit/components/TextEditor.spec.js
index 100b3bc0e7..468d6d30ba 100644
--- a/src/tests/unit/components/TextEditor.spec.js
+++ b/src/tests/unit/components/TextEditor.spec.js
@@ -6,6 +6,7 @@
import { createLocalVue, shallowMount } from '@vue/test-utils'
import { Paragraph } from 'ckeditor5'
import mitt from 'mitt'
+import { vi } from 'vitest'
import TextEditor from '../../../components/TextEditor.vue'
import MailPlugin from '../../../ckeditor/mail/MailPlugin.js'
import Nextcloud from '../../../mixins/Nextcloud.js'
@@ -124,4 +125,77 @@ describe('TextEditor', () => {
expect(wrapper.emitted().ready[0][0].getData())
.toEqual('bonjour bonjour
')
})
+
+ it('emits updated data while editing source', async () => {
+ vi.useFakeTimers()
+
+ const wrapper = shallowMount(TextEditor, {
+ localVue,
+ provide: {
+ addToFocusTrap: vi.fn(),
+ },
+ propsData: {
+ value: 'bonjour
',
+ html: true,
+ bus: mitt(),
+ },
+ })
+
+ const textarea = document.createElement('textarea')
+ const updateEditorData = vi.fn()
+ const sourceEditingPlugin = {
+ updateEditorData,
+ on: vi.fn(),
+ off: vi.fn(),
+ }
+ const editor = {
+ locale: {
+ uiLanguageDirection: 'ltr',
+ },
+ ui: {
+ view: {
+ toolbar: {
+ element: document.createElement('div'),
+ items: [],
+ },
+ editable: { element: document.createElement('div') },
+ },
+ getEditableElement: vi.fn((name) => name === 'sourceEditing:main' ? textarea : null),
+ },
+ commands: {
+ get: vi.fn(() => null),
+ },
+ plugins: {
+ has: vi.fn((pluginName) => pluginName === 'SourceEditing'),
+ get: vi.fn(() => sourceEditingPlugin),
+ },
+ keystrokes: {
+ set: vi.fn(),
+ },
+ editing: {
+ view: {
+ focus: vi.fn(),
+ },
+ },
+ }
+
+ wrapper.vm.$refs.toolbarContainer = document.createElement('div')
+ wrapper.vm.$refs.editableContainer = { appendChild: vi.fn() }
+
+ wrapper.vm.onEditorReady(editor)
+
+ const sourceEditingModeHandler = sourceEditingPlugin.on.mock.calls.find(([evt]) => evt === 'change:isSourceEditingMode')[1]
+
+ sourceEditingModeHandler(null, 'isSourceEditingMode', true)
+ textarea.dispatchEvent(new Event('input'))
+
+ await vi.runAllTimersAsync()
+
+ // updateEditorData() calls editor.data.set() → model change:data → Vue wrapper emits @input.
+ // We assert the handoff to CKEditor's pipeline here; the Vue wrapper propagation is tested
+ // by @ckeditor/ckeditor5-vue2's own suite.
+ expect(updateEditorData).toHaveBeenCalledTimes(1)
+
+ vi.useRealTimers()
+ })
})
From 3de1febbf46eb57425f8ae26766a0d5ca5358119 Mon Sep 17 00:00:00 2001
From: Daniel Kesselberg
Date: Fri, 15 May 2026 19:52:16 +0200
Subject: [PATCH 032/228] ci: force-enable mail app
Signed-off-by: Daniel Kesselberg
---
.github/workflows/test.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index d676d8585d..d10d7235fc 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -169,7 +169,7 @@ jobs:
if: ${{ matrix.php-versions == '8.6' }}
run: sed -i 's/max-version="8.5"/max-version="8.6"/' nextcloud/apps/mail/appinfo/info.xml
- name: Install Mail
- run: php -f nextcloud/occ app:enable mail
+ run: php -f nextcloud/occ app:enable mail --force
- name: Configure Nextcloud for testing
run: |
php -f nextcloud/occ config:system:set app.mail.debug --type bool --value true
@@ -265,7 +265,7 @@ jobs:
working-directory: nextcloud/apps/mail
run: composer install
- name: Install the app
- run: php -f nextcloud/occ app:enable mail
+ run: php -f nextcloud/occ app:enable mail --force
- name: Set up node ${{ env.E2E_NODE_VERSION }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
From 203ce3603f6abf3640dbc4856e422162a55e5531 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Sat, 16 May 2026 01:35:45 +0000
Subject: [PATCH 033/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/ga.js | 19 +++++++++++++++++++
l10n/ga.json | 19 +++++++++++++++++++
l10n/it.js | 34 ++++++++++++++++++++++++++++++++++
l10n/it.json | 34 ++++++++++++++++++++++++++++++++++
l10n/pt_BR.js | 19 ++++++++++++++++++-
l10n/pt_BR.json | 19 ++++++++++++++++++-
l10n/zh_CN.js | 21 +++++++++++++++++++++
l10n/zh_CN.json | 21 +++++++++++++++++++++
8 files changed, 184 insertions(+), 2 deletions(-)
diff --git a/l10n/ga.js b/l10n/ga.js
index c2abee9e9e..0582fc15e5 100644
--- a/l10n/ga.js
+++ b/l10n/ga.js
@@ -93,6 +93,8 @@ OC.L10N.register(
"SMTP Port" : "Port SMTP",
"SMTP User" : "Úsáideoir SMTP",
"SMTP Password" : "Pasfhocal SMTP",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Éilíonn Google fíordheimhniú OAuth. Mura bhfuil Google OAuth cumraithe ag do riarthóir Nextcloud, is féidir leat Pasfhocal Aipe Google a úsáid ina ionad.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Éilíonn Microsoft fíordheimhniú OAuth. Iarr ar do riarthóir Nextcloud Microsoft OAuth a chumrú sna socruithe riarthóra.",
"Account settings" : "Socruithe cuntas",
"Aliases" : "Ailiasanna",
"Alias to S/MIME certificate mapping" : "Ailias le mapáil teastais S/MIME",
@@ -135,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "Socruithe ríomhphoist",
"General" : "Ginearálta",
"Set as default mail app" : "Socraigh mar aip ríomhphoist réamhshocraithe",
+ "{email} (delegated)" : "{email} (tarmligthe)",
"Add mail account" : "Cuir cuntas ríomhphoist leis",
"Appearance" : "Dealramh",
"Show all messages in thread" : "Taispeáin gach teachtaireacht sa snáithe",
@@ -253,7 +256,21 @@ OC.L10N.register(
"Expand composer" : "Cumadóir a leathnú",
"Close composer" : "Cumadóir dlúth",
"Confirm" : "Deimhnigh",
+ "Delegate access" : "Rochtain toscaire",
"Revoke" : "Chúlghairm",
+ "{userId} will no longer be able to act on your behalf" : "Ní bheidh {userId} in ann gníomhú ar do shon a thuilleadh",
+ "Could not fetch delegates" : "Níorbh fhéidir toscairí a fháil",
+ "Delegated access to {userId}" : "Rochtain tarmligthe chuig {userId}",
+ "Could not delegate access" : "Níorbh fhéidir rochtain a tharmligean",
+ "Revoked access for {userId}" : "Rochtain curtha ar ceal do {userId}",
+ "Could not revoke delegation" : "Níorbh fhéidir an toscaireacht a chúlghairm",
+ "Delegation" : "Toscaireacht",
+ "Allow users to send, receive, and delete mail on your behalf" : "Ceadaigh d'úsáideoirí ríomhphost a sheoladh, a fháil agus a scriosadh ar do shon",
+ "Revoke access" : "Cealaigh rochtain",
+ "Add delegate" : "Cuir toscaire leis",
+ "Select a user" : "Roghnaigh úsáideoir",
+ "They will be able to send, receive, and delete mail on your behalf" : "Beidh siad in ann ríomhphost a sheoladh, a fháil agus a scriosadh ar do shon.",
+ "Revoke access?" : "An bhfuil rochtain á cealú agat?",
"Tag: {name} deleted" : "Chlib: {name} scriosta",
"An error occurred, unable to delete the tag." : "Tharla earráid, níorbh fhéidir an chlib a scriosadh.",
"The tag will be deleted from all messages." : "Scriosfar an chlib ó gach teachtaireacht.",
@@ -450,8 +467,10 @@ OC.L10N.register(
"Remove account" : "Bain cuntas",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Bainfear an cuntas le haghaidh {email} agus na sonraí ríomhphoist i dtaisce de Nextcloud, ach ní bhainfear iad de do sholáthraí ríomhphoist.",
"Remove {email}" : "Bain {email}",
+ "could not delete account" : "níorbh fhéidir cuntas a scriosadh",
"Provisioned account is disabled" : "Tá cuntas soláthraithe díchumasaithe",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Logáil isteach le do thoil agus pasfhocal á úsáid agat chun an cuntas seo a chumasú. Tá an seisiún reatha ag baint úsáide as fíordheimhniú gan pasfhocal, e.g. SSO nó WebAuthn.",
+ "Delegate account" : "Cuntas toscaire",
"Show only subscribed folders" : "Taispeáin fillteáin suibscríofa amháin",
"Add folder" : "Cuir fillteán leis",
"Folder name" : "Ainm fillteáin",
diff --git a/l10n/ga.json b/l10n/ga.json
index f44ac00f7b..5060b634b3 100644
--- a/l10n/ga.json
+++ b/l10n/ga.json
@@ -91,6 +91,8 @@
"SMTP Port" : "Port SMTP",
"SMTP User" : "Úsáideoir SMTP",
"SMTP Password" : "Pasfhocal SMTP",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Éilíonn Google fíordheimhniú OAuth. Mura bhfuil Google OAuth cumraithe ag do riarthóir Nextcloud, is féidir leat Pasfhocal Aipe Google a úsáid ina ionad.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Éilíonn Microsoft fíordheimhniú OAuth. Iarr ar do riarthóir Nextcloud Microsoft OAuth a chumrú sna socruithe riarthóra.",
"Account settings" : "Socruithe cuntas",
"Aliases" : "Ailiasanna",
"Alias to S/MIME certificate mapping" : "Ailias le mapáil teastais S/MIME",
@@ -133,6 +135,7 @@
"Mail settings" : "Socruithe ríomhphoist",
"General" : "Ginearálta",
"Set as default mail app" : "Socraigh mar aip ríomhphoist réamhshocraithe",
+ "{email} (delegated)" : "{email} (tarmligthe)",
"Add mail account" : "Cuir cuntas ríomhphoist leis",
"Appearance" : "Dealramh",
"Show all messages in thread" : "Taispeáin gach teachtaireacht sa snáithe",
@@ -251,7 +254,21 @@
"Expand composer" : "Cumadóir a leathnú",
"Close composer" : "Cumadóir dlúth",
"Confirm" : "Deimhnigh",
+ "Delegate access" : "Rochtain toscaire",
"Revoke" : "Chúlghairm",
+ "{userId} will no longer be able to act on your behalf" : "Ní bheidh {userId} in ann gníomhú ar do shon a thuilleadh",
+ "Could not fetch delegates" : "Níorbh fhéidir toscairí a fháil",
+ "Delegated access to {userId}" : "Rochtain tarmligthe chuig {userId}",
+ "Could not delegate access" : "Níorbh fhéidir rochtain a tharmligean",
+ "Revoked access for {userId}" : "Rochtain curtha ar ceal do {userId}",
+ "Could not revoke delegation" : "Níorbh fhéidir an toscaireacht a chúlghairm",
+ "Delegation" : "Toscaireacht",
+ "Allow users to send, receive, and delete mail on your behalf" : "Ceadaigh d'úsáideoirí ríomhphost a sheoladh, a fháil agus a scriosadh ar do shon",
+ "Revoke access" : "Cealaigh rochtain",
+ "Add delegate" : "Cuir toscaire leis",
+ "Select a user" : "Roghnaigh úsáideoir",
+ "They will be able to send, receive, and delete mail on your behalf" : "Beidh siad in ann ríomhphost a sheoladh, a fháil agus a scriosadh ar do shon.",
+ "Revoke access?" : "An bhfuil rochtain á cealú agat?",
"Tag: {name} deleted" : "Chlib: {name} scriosta",
"An error occurred, unable to delete the tag." : "Tharla earráid, níorbh fhéidir an chlib a scriosadh.",
"The tag will be deleted from all messages." : "Scriosfar an chlib ó gach teachtaireacht.",
@@ -448,8 +465,10 @@
"Remove account" : "Bain cuntas",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Bainfear an cuntas le haghaidh {email} agus na sonraí ríomhphoist i dtaisce de Nextcloud, ach ní bhainfear iad de do sholáthraí ríomhphoist.",
"Remove {email}" : "Bain {email}",
+ "could not delete account" : "níorbh fhéidir cuntas a scriosadh",
"Provisioned account is disabled" : "Tá cuntas soláthraithe díchumasaithe",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Logáil isteach le do thoil agus pasfhocal á úsáid agat chun an cuntas seo a chumasú. Tá an seisiún reatha ag baint úsáide as fíordheimhniú gan pasfhocal, e.g. SSO nó WebAuthn.",
+ "Delegate account" : "Cuntas toscaire",
"Show only subscribed folders" : "Taispeáin fillteáin suibscríofa amháin",
"Add folder" : "Cuir fillteán leis",
"Folder name" : "Ainm fillteáin",
diff --git a/l10n/it.js b/l10n/it.js
index 3c3072059d..0437fbecb3 100644
--- a/l10n/it.js
+++ b/l10n/it.js
@@ -21,9 +21,14 @@ OC.L10N.register(
"Sender is using a custom email: %1$s instead of the sender email: %2$s" : "Il mittente sta usando un’email personalizzata: %1$s invece dell’email del mittente: %2$s",
"Sent date is in the future" : "La data di invio è nel futuro",
"Mail server marked this message as phishing attempt" : "Il server di posta ha contrassegnato questo messaggio come tentativo di phishing",
+ "Some addresses in this message are not matching the link text" : "Alcuni link presenti in questo messaggio non corrispondono all’indirizzo visualizzato",
+ "Reply-To email: %1$s is different from sender email: %2$s" : "L’indirizzo email di risposta: %1$s è diverso dall’indirizzo email del mittente: %2$s",
+ "Mail connection performance" : "Performance della connessione di posta elettronica",
"Slow mail service detected (%1$s) an attempt to connect to several accounts took an average of %2$s seconds per account" : "Rilevato servizio mail lento (%1$s): un tentativo di connessione a diversi account ha richiesto in media %2$s secondi per account",
+ "Slow mail service detected (%1$s) an attempt to perform a mail box list operation on several accounts took an average of %2$s seconds per account" : "Rilevato servizio di posta elettronica lento (%1$s): l’operazione di enumerazione delle caselle di posta su più account ha registrato un tempo medio di %2$s secondi per account.",
"Mail Transport configuration" : "Configurazione del recapito email",
"The app.mail.transport setting is not set to smtp. This configuration can cause issues with modern email security measures such as SPF and DKIM because emails are sent directly from the web server, which is often not properly configured for this purpose. To address this, we have discontinued support for the mail transport. Please remove app.mail.transport from your configuration to use the SMTP transport and hide this message. A properly configured SMTP setup is required to ensure email delivery." : "La configurazione email attuale non usa SMTP. Questo può creare problemi con i controlli di sicurezza moderni, come SPF e DKIM, perché i messaggi vengono inviati direttamente dal server web, che spesso non è configurato correttamente per l’invio di email. Il metodo di invio diretto non è più supportato. Rimuovi app.mail.transport dalla configurazione per passare all’invio tramite SMTP e non visualizzare più questo avviso. Per garantire il corretto recapito delle email è necessario configurare SMTP correttamente.",
+ "Mail account parameters, aliases and preferences" : "Parametri dell’account di posta, alias e preferenze",
"💌 A mail app for Nextcloud" : "💌 Un'applicazione di posta per Nextcloud",
"**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 Un'applicazione di posta elettronica per Nextcloud**\n\n- **🚀 Integrazione con altre applicazioni Nextcloud!** Attualmente Contatti, Calendario e File - ne arriveranno altre.\n- **📥 Account di posta multipli!** Account personali e aziendali? Nessun problema, e una bella casella di posta unificata. Collega qualsiasi account IMAP.\n- **🔒 Invia e ricevi email cifrate!** Utilizzando l'estensione del browser [Mailvelope](https://mailvelope.com).\n- **🙈 Non stiamo reinventando la ruota!** Basata sulle ottime librerie di [Horde](https://horde.org).\n- **📬 Vuoi ospitare il tuo server di posta?** Non dobbiamo reimplementarlo poiché puoi configurare [Mail-in-a-Box](https://mailinabox.email)!\n\n## Valutazione etica dell'IA\n\n### Posta in arrivo prioritaria\n\nPositivo:\n* Il software per l'addestramento e l'inferenza di questo modello è open source.\n* Il modello è creato e addestrato in locale basandosi sui dati dell'utente.\n* I dati di addestramento sono accessibili all'utente, rendendo possibile controllare o correggere le soglie o ottimizzare le prestazioni e l'utilizzo di CO2.\n\n### Riassunti delle discussioni (opt-in)\n\n**Valutazione:** 🟢/🟡/🟠/🔴\n\nLa valutazione dipende dal backend di elaborazione del testo installato. Vedi [la panoramica della valutazione](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) per i dettagli.\n\nScopri di più sulla Valutazione etica dell'IA di Nextcloud [nel nostro blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).",
"Your session has expired. The page will be reloaded." : "La sessione è scaduta. La pagina sarà ricaricata.",
@@ -31,6 +36,7 @@ OC.L10N.register(
"Sent messages are saved in:" : "I messaggi inviati sono salvati in:",
"Deleted messages are moved in:" : "I messaggi eliminati sono spostati in:",
"Archived messages are moved in:" : "I messaggi archiviati sono spostati in:",
+ "Snoozed messages are moved in:" : "I messaggi rimandati vengono spostati in:",
"Junk messages are saved in:" : "I messaggi indesiderati sono salvati in:",
"Connecting" : "Connessione in corso",
"Reconnect Google account" : "Ricollega l'account Google",
@@ -39,17 +45,31 @@ OC.L10N.register(
"Sign in with Microsoft" : "Accedi con Microsoft",
"Save" : "Salva",
"Connect" : "Connetti",
+ "Looking up configuration" : "Recupero della configurazione",
"Checking mail host connectivity" : "Verifica della connettività dell'host di posta",
+ "Configuration discovery failed. Please use the manual settings" : "Rilevamento automatico della configurazione non riuscito. Si prega di utilizzare le impostazioni manuali.",
"Password required" : "Password richiesta",
+ "Testing authentication" : "Verifica dell’autenticazione in corso",
"Awaiting user consent" : "In attesa del consenso dell'utente.",
+ "Account created. Please follow the pop-up instructions to link your Google account" : "Account creato. Seguire le istruzioni del pop-up per collegare il proprio account Google",
+ "Account created. Please follow the pop-up instructions to link your Microsoft account" : "Account creato. Seguire le istruzioni del pop-up per collegare il proprio account Microsoft",
"Loading account" : "Caricamento account",
+ "Account updated. Please follow the pop-up instructions to reconnect your Google account" : "Account aggiornato. Seguire le istruzioni del pop-up per riconnettere il proprio account Google",
+ "Account updated. Please follow the pop-up instructions to reconnect your Microsoft account" : "Account aggiornato. Seguire le istruzioni del pop-up per riconnettere il proprio account Microsoft",
"Account updated" : "Account aggiornato",
"IMAP server is not reachable" : "Il server IMAP non è raggiungibile",
"SMTP server is not reachable" : "Il server SMTP non è raggiungibile",
"IMAP username or password is wrong" : "Il nome utente o la password IMAP sono errati.",
"SMTP username or password is wrong" : "Il nome utente o la password SMTP sono errati.",
+ "IMAP server denied authentication" : "Autenticazione negata dal server IMAP",
+ "SMTP server denied authentication" : "Autenticazione negata dal server SMTP",
+ "IMAP authentication error" : "Errore di autenticazione IMAP",
+ "SMTP authentication error" : "Errore di autenticazione SMTP",
"IMAP connection failed" : "Connessione IMAP non riuscita",
"SMTP connection failed" : "Connessione SMTP non riuscita",
+ "Authorization pop-up closed" : "La finestra pop-up di autorizzazione è stata chiusa",
+ "Configuration discovery temporarily not available. Please try again later." : "Il rilevamento della configurazione è temporaneamente non disponibile. Riprovare più tardi.",
+ "There was an error while setting up your account" : "Si è verificato un errore durante la configurazione dell’account.",
"Auto" : "Automatico",
"Name" : "Nome",
"Mail address" : "Indirizzo di posta",
@@ -73,6 +93,8 @@ OC.L10N.register(
"SMTP Port" : "Porta SMTP",
"SMTP User" : "Utente SMTP",
"SMTP Password" : "Password SMTP",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google richiede l’autenticazione OAuth. Se l’amministratore di Nextcloud non ha configurato Google OAuth, è possibile utilizzare una password per app Google.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft richiede l’autenticazione OAuth. Si prega di contattare l’amministratore di Nextcloud per configurare OAuth di Microsoft nelle impostazioni di amministrazione.",
"Account settings" : "Impostazioni account",
"Aliases" : "Alias",
"Alias to S/MIME certificate mapping" : "Mappatura alias e certificati S/MIME",
@@ -108,11 +130,13 @@ OC.L10N.register(
"Cancel" : "Annulla",
"Search the body of messages in priority Inbox" : "Cerca nel corpo dei messaggi nella posta prioritaria",
"Activate" : "Attiva",
+ "Remind about messages that require a reply but received none" : "Promemoria per i messaggi che richiedono una risposta ma non hanno ricevuto alcun riscontro",
"Highlight external addresses" : "Evidenzia indirizzi esterni",
"Could not update preference" : "Impossibile aggiornare la preferenza",
"Mail settings" : "Impostazioni Posta",
"General" : "Generale",
"Set as default mail app" : "Imposta come applicazione di posta predefinita",
+ "{email} (delegated)" : "{email} (delegata)",
"Add mail account" : "Aggiungi account di posta",
"Appearance" : "Aspetto",
"Show all messages in thread" : "Mostra tutti i messaggi della conversazione",
@@ -144,8 +168,12 @@ OC.L10N.register(
"S/MIME" : "S/MIME",
"Manage certificates" : "Gestisci certificati",
"Mailvelope" : "Mailvelope",
+ "Mailvelope is enabled for the current domain." : "Mailvelope è abilitato per il dominio corrente.",
+ "Step 1" : "Passo 1",
"Install the browser extension" : "Installa l'estensione del browser",
+ "Step 2" : "Passo 2",
"Enable for the current domain" : "Abilita per il dominio corrente",
+ "Assistance features" : "Funzionalità di assistenza",
"Compose new message" : "Componi nuovo messaggio",
"Newer message" : "Messaggio più recente",
"Older message" : "Messaggio più datato",
@@ -158,13 +186,19 @@ OC.L10N.register(
"Refresh" : "Aggiorna",
"About" : "Informazioni",
"Acknowledgements" : "Ringraziamenti",
+ "This application includes CKEditor, an open-source editor. Copyright © CKEditor contributors. Licensed under GPLv2." : "Questa applicazione include CKEditor, un editor open-source. Copyright © dei contributori di CKEditor. Concesso in licenza GPLv2.",
+ "Title of the text block" : "Titolo del blocco di testo",
+ "Content of the text block" : "Contenuto del blocco di testo",
"Ok" : "Ok",
+ "Automatically create tentative appointments in calendar" : "Crea automaticamente appuntamenti provvisori nel calendario",
"No certificate" : "Nessun certificato",
"Certificate updated" : "Certificato aggiornato",
"Could not update certificate" : "Impossibile aggiornare il certificato",
"{commonName} - Valid until {expiryDate}" : "{commonName} - Valido fino al {expiryDate}",
"Select an alias" : "Seleziona un alias",
+ "Select certificates" : "Seleziona i certificati",
"Update Certificate" : "Aggiorna certificato",
+ "The selected certificate is not trusted by the server. Recipients might not be able to verify your signature." : "Il certificato selezionato non è considerato attendibile dal server. I destinatari potrebbero non essere in grado di verificare la tua firma.",
"Encrypt with S/MIME and send later" : "Cifra con S/MIME e invia in seguito",
"Encrypt with S/MIME and send" : "Cifra con S/MIME e invia",
"Encrypt with Mailvelope and send later" : "Cifra con Mailvelope e invia in seguito",
diff --git a/l10n/it.json b/l10n/it.json
index 5b2ae3c409..bd275310c6 100644
--- a/l10n/it.json
+++ b/l10n/it.json
@@ -19,9 +19,14 @@
"Sender is using a custom email: %1$s instead of the sender email: %2$s" : "Il mittente sta usando un’email personalizzata: %1$s invece dell’email del mittente: %2$s",
"Sent date is in the future" : "La data di invio è nel futuro",
"Mail server marked this message as phishing attempt" : "Il server di posta ha contrassegnato questo messaggio come tentativo di phishing",
+ "Some addresses in this message are not matching the link text" : "Alcuni link presenti in questo messaggio non corrispondono all’indirizzo visualizzato",
+ "Reply-To email: %1$s is different from sender email: %2$s" : "L’indirizzo email di risposta: %1$s è diverso dall’indirizzo email del mittente: %2$s",
+ "Mail connection performance" : "Performance della connessione di posta elettronica",
"Slow mail service detected (%1$s) an attempt to connect to several accounts took an average of %2$s seconds per account" : "Rilevato servizio mail lento (%1$s): un tentativo di connessione a diversi account ha richiesto in media %2$s secondi per account",
+ "Slow mail service detected (%1$s) an attempt to perform a mail box list operation on several accounts took an average of %2$s seconds per account" : "Rilevato servizio di posta elettronica lento (%1$s): l’operazione di enumerazione delle caselle di posta su più account ha registrato un tempo medio di %2$s secondi per account.",
"Mail Transport configuration" : "Configurazione del recapito email",
"The app.mail.transport setting is not set to smtp. This configuration can cause issues with modern email security measures such as SPF and DKIM because emails are sent directly from the web server, which is often not properly configured for this purpose. To address this, we have discontinued support for the mail transport. Please remove app.mail.transport from your configuration to use the SMTP transport and hide this message. A properly configured SMTP setup is required to ensure email delivery." : "La configurazione email attuale non usa SMTP. Questo può creare problemi con i controlli di sicurezza moderni, come SPF e DKIM, perché i messaggi vengono inviati direttamente dal server web, che spesso non è configurato correttamente per l’invio di email. Il metodo di invio diretto non è più supportato. Rimuovi app.mail.transport dalla configurazione per passare all’invio tramite SMTP e non visualizzare più questo avviso. Per garantire il corretto recapito delle email è necessario configurare SMTP correttamente.",
+ "Mail account parameters, aliases and preferences" : "Parametri dell’account di posta, alias e preferenze",
"💌 A mail app for Nextcloud" : "💌 Un'applicazione di posta per Nextcloud",
"**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 Un'applicazione di posta elettronica per Nextcloud**\n\n- **🚀 Integrazione con altre applicazioni Nextcloud!** Attualmente Contatti, Calendario e File - ne arriveranno altre.\n- **📥 Account di posta multipli!** Account personali e aziendali? Nessun problema, e una bella casella di posta unificata. Collega qualsiasi account IMAP.\n- **🔒 Invia e ricevi email cifrate!** Utilizzando l'estensione del browser [Mailvelope](https://mailvelope.com).\n- **🙈 Non stiamo reinventando la ruota!** Basata sulle ottime librerie di [Horde](https://horde.org).\n- **📬 Vuoi ospitare il tuo server di posta?** Non dobbiamo reimplementarlo poiché puoi configurare [Mail-in-a-Box](https://mailinabox.email)!\n\n## Valutazione etica dell'IA\n\n### Posta in arrivo prioritaria\n\nPositivo:\n* Il software per l'addestramento e l'inferenza di questo modello è open source.\n* Il modello è creato e addestrato in locale basandosi sui dati dell'utente.\n* I dati di addestramento sono accessibili all'utente, rendendo possibile controllare o correggere le soglie o ottimizzare le prestazioni e l'utilizzo di CO2.\n\n### Riassunti delle discussioni (opt-in)\n\n**Valutazione:** 🟢/🟡/🟠/🔴\n\nLa valutazione dipende dal backend di elaborazione del testo installato. Vedi [la panoramica della valutazione](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) per i dettagli.\n\nScopri di più sulla Valutazione etica dell'IA di Nextcloud [nel nostro blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).",
"Your session has expired. The page will be reloaded." : "La sessione è scaduta. La pagina sarà ricaricata.",
@@ -29,6 +34,7 @@
"Sent messages are saved in:" : "I messaggi inviati sono salvati in:",
"Deleted messages are moved in:" : "I messaggi eliminati sono spostati in:",
"Archived messages are moved in:" : "I messaggi archiviati sono spostati in:",
+ "Snoozed messages are moved in:" : "I messaggi rimandati vengono spostati in:",
"Junk messages are saved in:" : "I messaggi indesiderati sono salvati in:",
"Connecting" : "Connessione in corso",
"Reconnect Google account" : "Ricollega l'account Google",
@@ -37,17 +43,31 @@
"Sign in with Microsoft" : "Accedi con Microsoft",
"Save" : "Salva",
"Connect" : "Connetti",
+ "Looking up configuration" : "Recupero della configurazione",
"Checking mail host connectivity" : "Verifica della connettività dell'host di posta",
+ "Configuration discovery failed. Please use the manual settings" : "Rilevamento automatico della configurazione non riuscito. Si prega di utilizzare le impostazioni manuali.",
"Password required" : "Password richiesta",
+ "Testing authentication" : "Verifica dell’autenticazione in corso",
"Awaiting user consent" : "In attesa del consenso dell'utente.",
+ "Account created. Please follow the pop-up instructions to link your Google account" : "Account creato. Seguire le istruzioni del pop-up per collegare il proprio account Google",
+ "Account created. Please follow the pop-up instructions to link your Microsoft account" : "Account creato. Seguire le istruzioni del pop-up per collegare il proprio account Microsoft",
"Loading account" : "Caricamento account",
+ "Account updated. Please follow the pop-up instructions to reconnect your Google account" : "Account aggiornato. Seguire le istruzioni del pop-up per riconnettere il proprio account Google",
+ "Account updated. Please follow the pop-up instructions to reconnect your Microsoft account" : "Account aggiornato. Seguire le istruzioni del pop-up per riconnettere il proprio account Microsoft",
"Account updated" : "Account aggiornato",
"IMAP server is not reachable" : "Il server IMAP non è raggiungibile",
"SMTP server is not reachable" : "Il server SMTP non è raggiungibile",
"IMAP username or password is wrong" : "Il nome utente o la password IMAP sono errati.",
"SMTP username or password is wrong" : "Il nome utente o la password SMTP sono errati.",
+ "IMAP server denied authentication" : "Autenticazione negata dal server IMAP",
+ "SMTP server denied authentication" : "Autenticazione negata dal server SMTP",
+ "IMAP authentication error" : "Errore di autenticazione IMAP",
+ "SMTP authentication error" : "Errore di autenticazione SMTP",
"IMAP connection failed" : "Connessione IMAP non riuscita",
"SMTP connection failed" : "Connessione SMTP non riuscita",
+ "Authorization pop-up closed" : "La finestra pop-up di autorizzazione è stata chiusa",
+ "Configuration discovery temporarily not available. Please try again later." : "Il rilevamento della configurazione è temporaneamente non disponibile. Riprovare più tardi.",
+ "There was an error while setting up your account" : "Si è verificato un errore durante la configurazione dell’account.",
"Auto" : "Automatico",
"Name" : "Nome",
"Mail address" : "Indirizzo di posta",
@@ -71,6 +91,8 @@
"SMTP Port" : "Porta SMTP",
"SMTP User" : "Utente SMTP",
"SMTP Password" : "Password SMTP",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google richiede l’autenticazione OAuth. Se l’amministratore di Nextcloud non ha configurato Google OAuth, è possibile utilizzare una password per app Google.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft richiede l’autenticazione OAuth. Si prega di contattare l’amministratore di Nextcloud per configurare OAuth di Microsoft nelle impostazioni di amministrazione.",
"Account settings" : "Impostazioni account",
"Aliases" : "Alias",
"Alias to S/MIME certificate mapping" : "Mappatura alias e certificati S/MIME",
@@ -106,11 +128,13 @@
"Cancel" : "Annulla",
"Search the body of messages in priority Inbox" : "Cerca nel corpo dei messaggi nella posta prioritaria",
"Activate" : "Attiva",
+ "Remind about messages that require a reply but received none" : "Promemoria per i messaggi che richiedono una risposta ma non hanno ricevuto alcun riscontro",
"Highlight external addresses" : "Evidenzia indirizzi esterni",
"Could not update preference" : "Impossibile aggiornare la preferenza",
"Mail settings" : "Impostazioni Posta",
"General" : "Generale",
"Set as default mail app" : "Imposta come applicazione di posta predefinita",
+ "{email} (delegated)" : "{email} (delegata)",
"Add mail account" : "Aggiungi account di posta",
"Appearance" : "Aspetto",
"Show all messages in thread" : "Mostra tutti i messaggi della conversazione",
@@ -142,8 +166,12 @@
"S/MIME" : "S/MIME",
"Manage certificates" : "Gestisci certificati",
"Mailvelope" : "Mailvelope",
+ "Mailvelope is enabled for the current domain." : "Mailvelope è abilitato per il dominio corrente.",
+ "Step 1" : "Passo 1",
"Install the browser extension" : "Installa l'estensione del browser",
+ "Step 2" : "Passo 2",
"Enable for the current domain" : "Abilita per il dominio corrente",
+ "Assistance features" : "Funzionalità di assistenza",
"Compose new message" : "Componi nuovo messaggio",
"Newer message" : "Messaggio più recente",
"Older message" : "Messaggio più datato",
@@ -156,13 +184,19 @@
"Refresh" : "Aggiorna",
"About" : "Informazioni",
"Acknowledgements" : "Ringraziamenti",
+ "This application includes CKEditor, an open-source editor. Copyright © CKEditor contributors. Licensed under GPLv2." : "Questa applicazione include CKEditor, un editor open-source. Copyright © dei contributori di CKEditor. Concesso in licenza GPLv2.",
+ "Title of the text block" : "Titolo del blocco di testo",
+ "Content of the text block" : "Contenuto del blocco di testo",
"Ok" : "Ok",
+ "Automatically create tentative appointments in calendar" : "Crea automaticamente appuntamenti provvisori nel calendario",
"No certificate" : "Nessun certificato",
"Certificate updated" : "Certificato aggiornato",
"Could not update certificate" : "Impossibile aggiornare il certificato",
"{commonName} - Valid until {expiryDate}" : "{commonName} - Valido fino al {expiryDate}",
"Select an alias" : "Seleziona un alias",
+ "Select certificates" : "Seleziona i certificati",
"Update Certificate" : "Aggiorna certificato",
+ "The selected certificate is not trusted by the server. Recipients might not be able to verify your signature." : "Il certificato selezionato non è considerato attendibile dal server. I destinatari potrebbero non essere in grado di verificare la tua firma.",
"Encrypt with S/MIME and send later" : "Cifra con S/MIME e invia in seguito",
"Encrypt with S/MIME and send" : "Cifra con S/MIME e invia",
"Encrypt with Mailvelope and send later" : "Cifra con Mailvelope e invia in seguito",
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index 7b93cd8330..be010e9abc 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -94,7 +94,7 @@ OC.L10N.register(
"SMTP User" : "Usuário SMTP",
"SMTP Password" : "Senha SMTP",
"Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "O Google exige autenticação OAuth. Se a administração do Nextcloud não tiver configurado o OAuth do Google, você pode usar uma senha de aplicativo do Google.",
- "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "O Microsoft exige autenticação OAuth. Peça à administração do Nextcloud para configurar o OAuth da Microsoft nas configurações de administração.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "O Microsoft exige autenticação OAuth. Peça à administração do Nextcloud para configurar o OAuth do Microsoft nas configurações de administração.",
"Account settings" : "Configurações de conta",
"Aliases" : "Aliases",
"Alias to S/MIME certificate mapping" : "Mapeamento de alias para certificado S/MIME",
@@ -137,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "Configurações de e-mail",
"General" : "Geral",
"Set as default mail app" : "Definir como aplicativo de e-mail padrão",
+ "{email} (delegated)" : "{email} (delegado)",
"Add mail account" : "Adicionar conta de e-mail",
"Appearance" : "Aparência",
"Show all messages in thread" : "Mostrar todas as mensagens no fio",
@@ -255,7 +256,21 @@ OC.L10N.register(
"Expand composer" : "Expandir compositor",
"Close composer" : "Fechar compositor",
"Confirm" : "Confirmar",
+ "Delegate access" : "Delegar acesso",
"Revoke" : "Revogar",
+ "{userId} will no longer be able to act on your behalf" : "{userId} não poderá mais agir em seu nome",
+ "Could not fetch delegates" : "Não foi possível obter os delegados",
+ "Delegated access to {userId}" : "Delegar acesso a {userId}",
+ "Could not delegate access" : "Não foi possível delegar o acesso",
+ "Revoked access for {userId}" : "Acesso revogado de {userId}",
+ "Could not revoke delegation" : "Não foi possível revogar a delegação",
+ "Delegation" : "Delegação",
+ "Allow users to send, receive, and delete mail on your behalf" : "Permita que os usuários enviem, recebam e excluam e-mails em seu nome",
+ "Revoke access" : "Revogar acesso",
+ "Add delegate" : "Adicionar delegado",
+ "Select a user" : "Selecione um usuário",
+ "They will be able to send, receive, and delete mail on your behalf" : "Eles poderão enviar, receber e excluir e-mails em seu nome",
+ "Revoke access?" : "Revogar acesso?",
"Tag: {name} deleted" : "Etiqueta: {name} excluída",
"An error occurred, unable to delete the tag." : "Ocorreu um erro, não foi possível excluir a etiqueta.",
"The tag will be deleted from all messages." : "A etiqueta será excluída de todas as mensagens.",
@@ -452,8 +467,10 @@ OC.L10N.register(
"Remove account" : "Excluir a conta",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "A conta do e-mail {email} e os dados em cache serão removidos do Nextcloud, mas não do seu provedor de e-mail.",
"Remove {email}" : "Excluir {email}",
+ "could not delete account" : "não foi possível excluir a conta",
"Provisioned account is disabled" : "A conta provisionada está desativada",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Faça o login usando uma senha para habilitar esta conta. A sessão atual está usando autenticação sem senha, p. ex., SSO ou WebAuthn.",
+ "Delegate account" : "Delegar conta",
"Show only subscribed folders" : "Mostrar apenas pastas subscritas",
"Add folder" : "Adicionar pasta",
"Folder name" : "Nome da pasta",
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index 11c8a206ba..4c61eec5d5 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -92,7 +92,7 @@
"SMTP User" : "Usuário SMTP",
"SMTP Password" : "Senha SMTP",
"Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "O Google exige autenticação OAuth. Se a administração do Nextcloud não tiver configurado o OAuth do Google, você pode usar uma senha de aplicativo do Google.",
- "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "O Microsoft exige autenticação OAuth. Peça à administração do Nextcloud para configurar o OAuth da Microsoft nas configurações de administração.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "O Microsoft exige autenticação OAuth. Peça à administração do Nextcloud para configurar o OAuth do Microsoft nas configurações de administração.",
"Account settings" : "Configurações de conta",
"Aliases" : "Aliases",
"Alias to S/MIME certificate mapping" : "Mapeamento de alias para certificado S/MIME",
@@ -135,6 +135,7 @@
"Mail settings" : "Configurações de e-mail",
"General" : "Geral",
"Set as default mail app" : "Definir como aplicativo de e-mail padrão",
+ "{email} (delegated)" : "{email} (delegado)",
"Add mail account" : "Adicionar conta de e-mail",
"Appearance" : "Aparência",
"Show all messages in thread" : "Mostrar todas as mensagens no fio",
@@ -253,7 +254,21 @@
"Expand composer" : "Expandir compositor",
"Close composer" : "Fechar compositor",
"Confirm" : "Confirmar",
+ "Delegate access" : "Delegar acesso",
"Revoke" : "Revogar",
+ "{userId} will no longer be able to act on your behalf" : "{userId} não poderá mais agir em seu nome",
+ "Could not fetch delegates" : "Não foi possível obter os delegados",
+ "Delegated access to {userId}" : "Delegar acesso a {userId}",
+ "Could not delegate access" : "Não foi possível delegar o acesso",
+ "Revoked access for {userId}" : "Acesso revogado de {userId}",
+ "Could not revoke delegation" : "Não foi possível revogar a delegação",
+ "Delegation" : "Delegação",
+ "Allow users to send, receive, and delete mail on your behalf" : "Permita que os usuários enviem, recebam e excluam e-mails em seu nome",
+ "Revoke access" : "Revogar acesso",
+ "Add delegate" : "Adicionar delegado",
+ "Select a user" : "Selecione um usuário",
+ "They will be able to send, receive, and delete mail on your behalf" : "Eles poderão enviar, receber e excluir e-mails em seu nome",
+ "Revoke access?" : "Revogar acesso?",
"Tag: {name} deleted" : "Etiqueta: {name} excluída",
"An error occurred, unable to delete the tag." : "Ocorreu um erro, não foi possível excluir a etiqueta.",
"The tag will be deleted from all messages." : "A etiqueta será excluída de todas as mensagens.",
@@ -450,8 +465,10 @@
"Remove account" : "Excluir a conta",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "A conta do e-mail {email} e os dados em cache serão removidos do Nextcloud, mas não do seu provedor de e-mail.",
"Remove {email}" : "Excluir {email}",
+ "could not delete account" : "não foi possível excluir a conta",
"Provisioned account is disabled" : "A conta provisionada está desativada",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Faça o login usando uma senha para habilitar esta conta. A sessão atual está usando autenticação sem senha, p. ex., SSO ou WebAuthn.",
+ "Delegate account" : "Delegar conta",
"Show only subscribed folders" : "Mostrar apenas pastas subscritas",
"Add folder" : "Adicionar pasta",
"Folder name" : "Nome da pasta",
diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js
index 400f7d41d5..62af5d0d07 100644
--- a/l10n/zh_CN.js
+++ b/l10n/zh_CN.js
@@ -93,6 +93,8 @@ OC.L10N.register(
"SMTP Port" : "SMTP 端口",
"SMTP User" : "SMTP 用户",
"SMTP Password" : "SMTP 密码",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google 需要 OAuth 身份验证。如果您的 Nextcloud 管理员尚未配置 Google OAuth,您可以使用 Google 应用密码代替。",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft 需要使用 OAuth 身份验证。请您的 Nextcloud 管理员在管理员设置中配置 Microsoft OAuth。",
"Account settings" : "账号设置",
"Aliases" : "别名",
"Alias to S/MIME certificate mapping" : "別名到 S/MIME 证书映射",
@@ -135,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "邮件设置",
"General" : "常规",
"Set as default mail app" : "设为默认邮件应用",
+ "{email} (delegated)" : "{email}(已委派)",
"Add mail account" : "添加邮件账号",
"Appearance" : "外观",
"Show all messages in thread" : "显示线程中的所有邮件",
@@ -253,7 +256,21 @@ OC.L10N.register(
"Expand composer" : "展开编辑器",
"Close composer" : "关闭编辑器",
"Confirm" : "确认",
+ "Delegate access" : "委派访问权限",
"Revoke" : "撤销",
+ "{userId} will no longer be able to act on your behalf" : "{userId} 将无法再代表您执行操作",
+ "Could not fetch delegates" : "无法获取委派用户",
+ "Delegated access to {userId}" : "已向 {userId} 委派访问权限",
+ "Could not delegate access" : "无法委派访问权限",
+ "Revoked access for {userId}" : "已撤销 {userId} 的访问权限",
+ "Could not revoke delegation" : "无法撤销委派",
+ "Delegation" : "委派",
+ "Allow users to send, receive, and delete mail on your behalf" : "允许用户代表您发送、接收和删除邮件",
+ "Revoke access" : "撤销访问权限",
+ "Add delegate" : "添加委派",
+ "Select a user" : "选择用户",
+ "They will be able to send, receive, and delete mail on your behalf" : "他们将能够代表您发送、接收和删除邮件",
+ "Revoke access?" : "撤销访问权限?",
"Tag: {name} deleted" : "标签:{name} 已删除",
"An error occurred, unable to delete the tag." : "发生错误,无法删除标签。",
"The tag will be deleted from all messages." : "将从所有邮件中删除此标签。",
@@ -450,8 +467,10 @@ OC.L10N.register(
"Remove account" : "移除账号",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email}和缓存的电子邮箱数据将从 Nextcloud 账号中删除,但不会从你的电子邮箱提供商那里删除。",
"Remove {email}" : "移除 {email}",
+ "could not delete account" : "无法删除账号",
"Provisioned account is disabled" : "预配账号已禁用",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "请使用密码登录以启用此账号。当前会话正在使用无密码身份验证,例如 SSO 或 WebAuthn。",
+ "Delegate account" : "委派账号",
"Show only subscribed folders" : "仅显示已订阅的文件夹",
"Add folder" : "添加文件夹",
"Folder name" : "文件夹名称",
@@ -625,6 +644,8 @@ OC.L10N.register(
"Mark as unfavorite" : "取消标记为收藏",
"Mark as favorite" : "标记为收藏",
"To:" : "到:",
+ "Cc:" : "抄送:",
+ "Bcc:" : "密送:",
"Unsubscribe via link" : "通过链接取消订阅",
"Unsubscribing will stop all messages from the mailing list {sender}" : "取消订阅将停止来自邮寄列表 {sender} 的全部邮件",
"Send unsubscribe email" : "发送取消订阅电子邮件",
diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json
index 646b414a99..4f5aaad39d 100644
--- a/l10n/zh_CN.json
+++ b/l10n/zh_CN.json
@@ -91,6 +91,8 @@
"SMTP Port" : "SMTP 端口",
"SMTP User" : "SMTP 用户",
"SMTP Password" : "SMTP 密码",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google 需要 OAuth 身份验证。如果您的 Nextcloud 管理员尚未配置 Google OAuth,您可以使用 Google 应用密码代替。",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft 需要使用 OAuth 身份验证。请您的 Nextcloud 管理员在管理员设置中配置 Microsoft OAuth。",
"Account settings" : "账号设置",
"Aliases" : "别名",
"Alias to S/MIME certificate mapping" : "別名到 S/MIME 证书映射",
@@ -133,6 +135,7 @@
"Mail settings" : "邮件设置",
"General" : "常规",
"Set as default mail app" : "设为默认邮件应用",
+ "{email} (delegated)" : "{email}(已委派)",
"Add mail account" : "添加邮件账号",
"Appearance" : "外观",
"Show all messages in thread" : "显示线程中的所有邮件",
@@ -251,7 +254,21 @@
"Expand composer" : "展开编辑器",
"Close composer" : "关闭编辑器",
"Confirm" : "确认",
+ "Delegate access" : "委派访问权限",
"Revoke" : "撤销",
+ "{userId} will no longer be able to act on your behalf" : "{userId} 将无法再代表您执行操作",
+ "Could not fetch delegates" : "无法获取委派用户",
+ "Delegated access to {userId}" : "已向 {userId} 委派访问权限",
+ "Could not delegate access" : "无法委派访问权限",
+ "Revoked access for {userId}" : "已撤销 {userId} 的访问权限",
+ "Could not revoke delegation" : "无法撤销委派",
+ "Delegation" : "委派",
+ "Allow users to send, receive, and delete mail on your behalf" : "允许用户代表您发送、接收和删除邮件",
+ "Revoke access" : "撤销访问权限",
+ "Add delegate" : "添加委派",
+ "Select a user" : "选择用户",
+ "They will be able to send, receive, and delete mail on your behalf" : "他们将能够代表您发送、接收和删除邮件",
+ "Revoke access?" : "撤销访问权限?",
"Tag: {name} deleted" : "标签:{name} 已删除",
"An error occurred, unable to delete the tag." : "发生错误,无法删除标签。",
"The tag will be deleted from all messages." : "将从所有邮件中删除此标签。",
@@ -448,8 +465,10 @@
"Remove account" : "移除账号",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email}和缓存的电子邮箱数据将从 Nextcloud 账号中删除,但不会从你的电子邮箱提供商那里删除。",
"Remove {email}" : "移除 {email}",
+ "could not delete account" : "无法删除账号",
"Provisioned account is disabled" : "预配账号已禁用",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "请使用密码登录以启用此账号。当前会话正在使用无密码身份验证,例如 SSO 或 WebAuthn。",
+ "Delegate account" : "委派账号",
"Show only subscribed folders" : "仅显示已订阅的文件夹",
"Add folder" : "添加文件夹",
"Folder name" : "文件夹名称",
@@ -623,6 +642,8 @@
"Mark as unfavorite" : "取消标记为收藏",
"Mark as favorite" : "标记为收藏",
"To:" : "到:",
+ "Cc:" : "抄送:",
+ "Bcc:" : "密送:",
"Unsubscribe via link" : "通过链接取消订阅",
"Unsubscribing will stop all messages from the mailing list {sender}" : "取消订阅将停止来自邮寄列表 {sender} 的全部邮件",
"Send unsubscribe email" : "发送取消订阅电子邮件",
From 78383856e07df0c2a7ba0bd2f7f8e66b7ddcf69c Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Sun, 17 May 2026 01:33:35 +0000
Subject: [PATCH 034/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/lt_LT.js | 49 +++++++++++++++++++++++++++++++++++--------------
l10n/lt_LT.json | 49 +++++++++++++++++++++++++++++++++++--------------
l10n/pt_PT.js | 1 +
l10n/pt_PT.json | 1 +
4 files changed, 72 insertions(+), 28 deletions(-)
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index 16860f5b3c..d16af2a50d 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -93,6 +93,8 @@ OC.L10N.register(
"SMTP Port" : "SMTP prievadas",
"SMTP User" : "SMTP naudotojo vardas",
"SMTP Password" : "SMTP slaptažodis",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "„Google“ reikalauja „OAuth“ autentifikavimo. Jei jūsų „Nextcloud“ administratorius nesukonfigūravo „Google OAuth“, galite naudoti „Google“ programos slaptažodį.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "„Microsoft“ reikalauja „OAuth“ autentifikavimo. Paprašykite „Nextcloud“ administratoriaus sukonfigūruoti „Microsoft OAuth“ administratoriaus nustatymuose.",
"Account settings" : "Paskyros nustatymai",
"Aliases" : "Pseudonimai",
"Alias to S/MIME certificate mapping" : "Slapyvardžio ir S/MIME sertifikato susiejimas",
@@ -135,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "Pašto nustatymai",
"General" : "Bendra",
"Set as default mail app" : "Nustatyti kaip numatytąją pašto programėlę",
+ "{email} (delegated)" : "{email} (deleguotas)",
"Add mail account" : "Pridėti pašto paskyrą",
"Appearance" : "Išvaizda",
"Show all messages in thread" : "Rodyti visus šio pokalbio pranešimus",
@@ -146,7 +149,7 @@ OC.L10N.register(
"Horizontal split" : "Padalijimas horizontaliai",
"List" : "Sąrašas",
"Use compact mode" : "Naudoti kompaktiškąjį režimą",
- "Sorting" : "Rikiavimas",
+ "Sorting" : "Rūšiavimas",
"Newest first" : "Naujausi pirma",
"Oldest first" : "Seniausi pirma",
"Avatars from Gravatar and favicons" : "Avatarai iš „Gravatar“ ir svetainių piktogramos",
@@ -164,7 +167,7 @@ OC.L10N.register(
"Security" : "Saugumas",
"Manage your internal addresses and domains to ensure recognized contacts stay unmarked" : "Tvarkykite savo vidinius adresus ir domenus, kad atpažinti kontaktai neliktų pažymėti",
"S/MIME" : "S/MIME",
- "Manage certificates" : "Tvarkyti liudijimus",
+ "Manage certificates" : "Tvarkyti sertifikatus",
"Mailvelope" : "„Mailvelope“",
"Mailvelope is enabled for the current domain." : "„Mailvelope“ yra įjungta dabartiniam domenui.",
"Step 1" : "1 žingsnis",
@@ -233,7 +236,7 @@ OC.L10N.register(
"Upload attachment" : "Įkelti priedą",
"Add attachment from Files" : "Pridėti priedą iš Failų",
"Add share link from Files" : "Pridėti bendrinimo nuorodą iš Failų",
- "Smart picker" : "\"Smart picker\"",
+ "Smart picker" : "„Išmanusis rinkiklis“",
"Request a read receipt" : "Paprašyti patvirtinimo apie perskaitymą",
"Sign message with S/MIME" : "Pasirašyti laišką naudojant S/MIME",
"Encrypt message with S/MIME" : "Šifruoti laišką naudojant S/MIME",
@@ -253,7 +256,21 @@ OC.L10N.register(
"Expand composer" : "Išskleisti rašymo langą",
"Close composer" : "Uždaryti rašymo langą",
"Confirm" : "Patvirtinti",
+ "Delegate access" : "Deleguoti prieigą",
"Revoke" : "Panaikinti",
+ "{userId} will no longer be able to act on your behalf" : "{userId} nebegalės veikti jūsų vardu",
+ "Could not fetch delegates" : "Nepavyko gauti delegatų",
+ "Delegated access to {userId}" : "Deleguota prieiga prie {userId}",
+ "Could not delegate access" : "Nepavyko deleguoti prieigos",
+ "Revoked access for {userId}" : "Atšaukta prieiga {userId}",
+ "Could not revoke delegation" : "Nepavyko atšaukti delegavimo",
+ "Delegation" : "Delegavimas",
+ "Allow users to send, receive, and delete mail on your behalf" : "Leisti vartotojams siųsti, gauti ir ištrinti el. laiškus jūsų vardu",
+ "Revoke access" : "Atšaukti prieigą",
+ "Add delegate" : "Pridėti delegatą",
+ "Select a user" : "Pasirinkite vartotoją",
+ "They will be able to send, receive, and delete mail on your behalf" : "Jie galės siųsti, gauti ir ištrinti el. laiškus jūsų vardu",
+ "Revoke access?" : "Atšaukti prieigą?",
"Tag: {name} deleted" : "Žyma: {name} ištrinta",
"An error occurred, unable to delete the tag." : "Įvyko klaida, nepavyko ištrinti žymos.",
"The tag will be deleted from all messages." : "Žymė bus ištrinta iš visų pranešimų.",
@@ -305,7 +322,7 @@ OC.L10N.register(
"More actions" : "Daugiau veiksmų",
"Back" : "Atgal",
"Set custom snooze" : "Nustatyti pasirinktinį atidėjimą",
- "Edit as new message" : "Taisyti kaip naują laišką",
+ "Edit as new message" : "Redaguoti kaip naują laišką",
"Reply with meeting" : "Atsisakyti siūlant susitikimą",
"Create task" : "Sukurti užduotį",
"Download message" : "Atsisiųsti laišką",
@@ -450,8 +467,10 @@ OC.L10N.register(
"Remove account" : "Šalinti paskyrą",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Paskyra {email} ir podėlyje esantys el. pašto duomenys bus pašalinti iš Nextcloud, tačiau nebus pašalinti iš jūsų el. pašto teikėjo puslapio.",
"Remove {email}" : "Šalinti {email}",
+ "could not delete account" : "nepavyko ištrinti paskyros",
"Provisioned account is disabled" : "Parengtoji paskyra yra išjungta",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Norėdami aktyvuoti šią paskyrą, prisijunkite naudodami slaptažodį. Dabartinė sesija naudoja autentifikavimą be slaptažodžio, pvz., SSO arba WebAuthn.",
+ "Delegate account" : "Deleguoti paskyrą",
"Show only subscribed folders" : "Rodyti tik prenumeruotus aplankus",
"Add folder" : "Pridėti aplanką",
"Folder name" : "Aplanko pavadinimas",
@@ -485,7 +504,7 @@ OC.L10N.register(
"Outbox" : "Išsiuntimo dėžutė",
"Translate this message to {language}" : "Versti šį laišką į {language} kalbą",
"New message" : "Naujas laiškas",
- "Edit message" : "Taisyti laišką",
+ "Edit message" : "Redaguoti laišką",
"Draft" : "Juodraštis",
"Reply" : "Atsakyti",
"Message saved" : "Laiškas įrašytas",
@@ -537,7 +556,7 @@ OC.L10N.register(
"Could not copy email address to clipboard" : "Nepavyko nukopijuoti el. pašto adreso į iškarpinę",
"Contacts with this address" : "Adresatai turintys šį adresą",
"Add to Contact" : "Pridėti prie „Kontaktai“",
- "New Contact" : "Naujas adresatas",
+ "New Contact" : "Naujas kontaktas",
"Copy to clipboard" : "Kopijuoti į iškarpinę",
"Contact name …" : "Adresato vardas …",
"Add" : "Pridėti",
@@ -625,6 +644,8 @@ OC.L10N.register(
"Mark as unfavorite" : "Pažymėti kaip nepatinkantį",
"Mark as favorite" : "Žymėti kaip mėgstamiausią",
"To:" : "Iki:",
+ "Cc:" : "Cc:",
+ "Bcc:" : "Bcc:",
"Unsubscribe via link" : "Atsisakyti prenumeratos per nuorodą",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Atsisakę prenumeratos, nebegausite jokių laiškų iš šio pašto sąrašo {sender}",
"Send unsubscribe email" : "Siųsti laišką dėl prenumeratos atsisakymo",
@@ -717,7 +738,7 @@ OC.L10N.register(
"Quick action created" : "Greitasis veiksmas sukurtas",
"Failed to delete action step" : "Nepavyko ištrinti veiksmo žingsnio",
"No quick actions yet." : "Kol kas jokių greitųjų veiksmų.",
- "Edit" : "Taisyti",
+ "Edit" : "Redaguoti",
"Quick action name" : "Greitojo veiksmo pavadinimas",
"Do the following actions" : "Atlikti šiuos veiksmus",
"Add another action" : "Pridėti kitą veiksmą",
@@ -731,8 +752,8 @@ OC.L10N.register(
"Error when deleting and deprovisioning accounts for \"{domain}\"" : "Klaida trinant ir atšaukiant „{domain}“ srities paskyrų parengimą",
"Could not save default classification setting" : "Nepavyko išsaugoti numatytojo klasifikavimo nustatymo",
"Mail app" : "Pašto programėlė",
- "The mail app allows users to read mails on their IMAP accounts." : "Pašto programėlė leidžia naudotojams skaityti laiškus savo IMAP paskyrose.",
- "Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Čia galite rasti egzemplioriaus masto nustatymus. Specifinius naudotojo nustatymus galite rasti pačioje programėlėje (apatiniame kairiajame kampe).",
+ "The mail app allows users to read mails on their IMAP accounts." : "Pašto programėlė leidžia vartotojams skaityti laiškus savo IMAP paskyrose.",
+ "Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Čia galite rasti egzemplioriaus masto nustatymus. Specifinius vartotojo nustatymus galite rasti pačioje programėlėje (apatiniame kairiajame kampe).",
"Account provisioning" : "Paskyros parengimas",
"A provisioning configuration will provision all accounts with a matching email address." : "Naudojant parengimo konfigūraciją, bus sukurtos visos atitinkamą el. pašto adresą turinčios paskyros.",
"Using the wildcard (*) in the provisioning domain field will create a configuration that applies to all users, provided they do not match another configuration." : "Naudojant pakaitos simbolį (*) parengimo domeno lauke, bus sukurta konfigūracija, kuri bus taikoma visiems vartotojams, jei jie neatitinka kitos konfigūracijos.",
@@ -799,7 +820,7 @@ OC.L10N.register(
"Provisioning domain" : "Parengimo domenas",
"Email address template" : "El. pašto adreso šablonas",
"IMAP" : "IMAP",
- "User" : "Naudotojas",
+ "User" : "Vartotojas",
"Host" : "Serveris",
"Port" : "Prievadas",
"SMTP" : "SMTP",
@@ -846,17 +867,17 @@ OC.L10N.register(
"Group" : "Grupė",
"Failed to save text block" : "Nepavyko išsaugoti teksto bloko",
"Shared" : "Bendrinama",
- "Edit {title}" : "Taisyti {title}",
+ "Edit {title}" : "Redaguoti {title}",
"Delete {title}" : "Ištrinti {title}",
"Edit text block" : "Redaguoti teksto bloką",
- "Shares" : "Viešiniai",
+ "Shares" : "Bendrinimai",
"Search for users or groups" : "Ieškoti vartotojų arba grupių",
"Choose a text block to insert at the cursor" : "Pasirinkite teksto bloką, kurį norite įterpti ties žymekliu",
"Insert" : "Įterpti",
"Insert text block" : "Įterpti teksto bloką",
"Account connected" : "Paskyra prijungta",
"You can close this window" : "Galite užverti šį langą",
- "Connect your mail account" : "Priregistruoti elektroninio pašto paskyrą",
+ "Connect your mail account" : "Pridėti elektroninio pašto paskyrą",
"To add a mail account, please contact your administrator." : "Norėdami pridėti pašto paskyrą, susisiekite su savo administratoriumi.",
"All" : "Visos",
"Drafts" : "Juodraščiai",
@@ -874,7 +895,7 @@ OC.L10N.register(
"There is already a message in progress. All unsaved changes will be lost if you continue!" : "Jau vyksta žinutės rašymas. Jei tęsite, visi neišsaugoti pakeitimai bus prarasti!",
"Discard changes" : "Atmesti pakeitimus",
"Discard unsaved changes" : "Atmesti neįrašytus pakeitimus",
- "Keep editing message" : "Toliau taisyti laišką",
+ "Keep editing message" : "Toliau redaguoti laišką",
"(All or part of this reply was generated by AI)" : "(Visas šis atsakymas arba jo dalis buvo sugeneruota dirbtinio intelekto)",
"Attachments were not copied. Please add them manually." : "Priedai nebuvo nukopijuoti. Pridėkite juos rankiniu būdu.",
"Could not create snooze mailbox" : "Nepavyko sukurti atidėjimo pašto dėžutės",
diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json
index 9860c7a79b..b16a0ae969 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -91,6 +91,8 @@
"SMTP Port" : "SMTP prievadas",
"SMTP User" : "SMTP naudotojo vardas",
"SMTP Password" : "SMTP slaptažodis",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "„Google“ reikalauja „OAuth“ autentifikavimo. Jei jūsų „Nextcloud“ administratorius nesukonfigūravo „Google OAuth“, galite naudoti „Google“ programos slaptažodį.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "„Microsoft“ reikalauja „OAuth“ autentifikavimo. Paprašykite „Nextcloud“ administratoriaus sukonfigūruoti „Microsoft OAuth“ administratoriaus nustatymuose.",
"Account settings" : "Paskyros nustatymai",
"Aliases" : "Pseudonimai",
"Alias to S/MIME certificate mapping" : "Slapyvardžio ir S/MIME sertifikato susiejimas",
@@ -133,6 +135,7 @@
"Mail settings" : "Pašto nustatymai",
"General" : "Bendra",
"Set as default mail app" : "Nustatyti kaip numatytąją pašto programėlę",
+ "{email} (delegated)" : "{email} (deleguotas)",
"Add mail account" : "Pridėti pašto paskyrą",
"Appearance" : "Išvaizda",
"Show all messages in thread" : "Rodyti visus šio pokalbio pranešimus",
@@ -144,7 +147,7 @@
"Horizontal split" : "Padalijimas horizontaliai",
"List" : "Sąrašas",
"Use compact mode" : "Naudoti kompaktiškąjį režimą",
- "Sorting" : "Rikiavimas",
+ "Sorting" : "Rūšiavimas",
"Newest first" : "Naujausi pirma",
"Oldest first" : "Seniausi pirma",
"Avatars from Gravatar and favicons" : "Avatarai iš „Gravatar“ ir svetainių piktogramos",
@@ -162,7 +165,7 @@
"Security" : "Saugumas",
"Manage your internal addresses and domains to ensure recognized contacts stay unmarked" : "Tvarkykite savo vidinius adresus ir domenus, kad atpažinti kontaktai neliktų pažymėti",
"S/MIME" : "S/MIME",
- "Manage certificates" : "Tvarkyti liudijimus",
+ "Manage certificates" : "Tvarkyti sertifikatus",
"Mailvelope" : "„Mailvelope“",
"Mailvelope is enabled for the current domain." : "„Mailvelope“ yra įjungta dabartiniam domenui.",
"Step 1" : "1 žingsnis",
@@ -231,7 +234,7 @@
"Upload attachment" : "Įkelti priedą",
"Add attachment from Files" : "Pridėti priedą iš Failų",
"Add share link from Files" : "Pridėti bendrinimo nuorodą iš Failų",
- "Smart picker" : "\"Smart picker\"",
+ "Smart picker" : "„Išmanusis rinkiklis“",
"Request a read receipt" : "Paprašyti patvirtinimo apie perskaitymą",
"Sign message with S/MIME" : "Pasirašyti laišką naudojant S/MIME",
"Encrypt message with S/MIME" : "Šifruoti laišką naudojant S/MIME",
@@ -251,7 +254,21 @@
"Expand composer" : "Išskleisti rašymo langą",
"Close composer" : "Uždaryti rašymo langą",
"Confirm" : "Patvirtinti",
+ "Delegate access" : "Deleguoti prieigą",
"Revoke" : "Panaikinti",
+ "{userId} will no longer be able to act on your behalf" : "{userId} nebegalės veikti jūsų vardu",
+ "Could not fetch delegates" : "Nepavyko gauti delegatų",
+ "Delegated access to {userId}" : "Deleguota prieiga prie {userId}",
+ "Could not delegate access" : "Nepavyko deleguoti prieigos",
+ "Revoked access for {userId}" : "Atšaukta prieiga {userId}",
+ "Could not revoke delegation" : "Nepavyko atšaukti delegavimo",
+ "Delegation" : "Delegavimas",
+ "Allow users to send, receive, and delete mail on your behalf" : "Leisti vartotojams siųsti, gauti ir ištrinti el. laiškus jūsų vardu",
+ "Revoke access" : "Atšaukti prieigą",
+ "Add delegate" : "Pridėti delegatą",
+ "Select a user" : "Pasirinkite vartotoją",
+ "They will be able to send, receive, and delete mail on your behalf" : "Jie galės siųsti, gauti ir ištrinti el. laiškus jūsų vardu",
+ "Revoke access?" : "Atšaukti prieigą?",
"Tag: {name} deleted" : "Žyma: {name} ištrinta",
"An error occurred, unable to delete the tag." : "Įvyko klaida, nepavyko ištrinti žymos.",
"The tag will be deleted from all messages." : "Žymė bus ištrinta iš visų pranešimų.",
@@ -303,7 +320,7 @@
"More actions" : "Daugiau veiksmų",
"Back" : "Atgal",
"Set custom snooze" : "Nustatyti pasirinktinį atidėjimą",
- "Edit as new message" : "Taisyti kaip naują laišką",
+ "Edit as new message" : "Redaguoti kaip naują laišką",
"Reply with meeting" : "Atsisakyti siūlant susitikimą",
"Create task" : "Sukurti užduotį",
"Download message" : "Atsisiųsti laišką",
@@ -448,8 +465,10 @@
"Remove account" : "Šalinti paskyrą",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Paskyra {email} ir podėlyje esantys el. pašto duomenys bus pašalinti iš Nextcloud, tačiau nebus pašalinti iš jūsų el. pašto teikėjo puslapio.",
"Remove {email}" : "Šalinti {email}",
+ "could not delete account" : "nepavyko ištrinti paskyros",
"Provisioned account is disabled" : "Parengtoji paskyra yra išjungta",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Norėdami aktyvuoti šią paskyrą, prisijunkite naudodami slaptažodį. Dabartinė sesija naudoja autentifikavimą be slaptažodžio, pvz., SSO arba WebAuthn.",
+ "Delegate account" : "Deleguoti paskyrą",
"Show only subscribed folders" : "Rodyti tik prenumeruotus aplankus",
"Add folder" : "Pridėti aplanką",
"Folder name" : "Aplanko pavadinimas",
@@ -483,7 +502,7 @@
"Outbox" : "Išsiuntimo dėžutė",
"Translate this message to {language}" : "Versti šį laišką į {language} kalbą",
"New message" : "Naujas laiškas",
- "Edit message" : "Taisyti laišką",
+ "Edit message" : "Redaguoti laišką",
"Draft" : "Juodraštis",
"Reply" : "Atsakyti",
"Message saved" : "Laiškas įrašytas",
@@ -535,7 +554,7 @@
"Could not copy email address to clipboard" : "Nepavyko nukopijuoti el. pašto adreso į iškarpinę",
"Contacts with this address" : "Adresatai turintys šį adresą",
"Add to Contact" : "Pridėti prie „Kontaktai“",
- "New Contact" : "Naujas adresatas",
+ "New Contact" : "Naujas kontaktas",
"Copy to clipboard" : "Kopijuoti į iškarpinę",
"Contact name …" : "Adresato vardas …",
"Add" : "Pridėti",
@@ -623,6 +642,8 @@
"Mark as unfavorite" : "Pažymėti kaip nepatinkantį",
"Mark as favorite" : "Žymėti kaip mėgstamiausią",
"To:" : "Iki:",
+ "Cc:" : "Cc:",
+ "Bcc:" : "Bcc:",
"Unsubscribe via link" : "Atsisakyti prenumeratos per nuorodą",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Atsisakę prenumeratos, nebegausite jokių laiškų iš šio pašto sąrašo {sender}",
"Send unsubscribe email" : "Siųsti laišką dėl prenumeratos atsisakymo",
@@ -715,7 +736,7 @@
"Quick action created" : "Greitasis veiksmas sukurtas",
"Failed to delete action step" : "Nepavyko ištrinti veiksmo žingsnio",
"No quick actions yet." : "Kol kas jokių greitųjų veiksmų.",
- "Edit" : "Taisyti",
+ "Edit" : "Redaguoti",
"Quick action name" : "Greitojo veiksmo pavadinimas",
"Do the following actions" : "Atlikti šiuos veiksmus",
"Add another action" : "Pridėti kitą veiksmą",
@@ -729,8 +750,8 @@
"Error when deleting and deprovisioning accounts for \"{domain}\"" : "Klaida trinant ir atšaukiant „{domain}“ srities paskyrų parengimą",
"Could not save default classification setting" : "Nepavyko išsaugoti numatytojo klasifikavimo nustatymo",
"Mail app" : "Pašto programėlė",
- "The mail app allows users to read mails on their IMAP accounts." : "Pašto programėlė leidžia naudotojams skaityti laiškus savo IMAP paskyrose.",
- "Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Čia galite rasti egzemplioriaus masto nustatymus. Specifinius naudotojo nustatymus galite rasti pačioje programėlėje (apatiniame kairiajame kampe).",
+ "The mail app allows users to read mails on their IMAP accounts." : "Pašto programėlė leidžia vartotojams skaityti laiškus savo IMAP paskyrose.",
+ "Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Čia galite rasti egzemplioriaus masto nustatymus. Specifinius vartotojo nustatymus galite rasti pačioje programėlėje (apatiniame kairiajame kampe).",
"Account provisioning" : "Paskyros parengimas",
"A provisioning configuration will provision all accounts with a matching email address." : "Naudojant parengimo konfigūraciją, bus sukurtos visos atitinkamą el. pašto adresą turinčios paskyros.",
"Using the wildcard (*) in the provisioning domain field will create a configuration that applies to all users, provided they do not match another configuration." : "Naudojant pakaitos simbolį (*) parengimo domeno lauke, bus sukurta konfigūracija, kuri bus taikoma visiems vartotojams, jei jie neatitinka kitos konfigūracijos.",
@@ -797,7 +818,7 @@
"Provisioning domain" : "Parengimo domenas",
"Email address template" : "El. pašto adreso šablonas",
"IMAP" : "IMAP",
- "User" : "Naudotojas",
+ "User" : "Vartotojas",
"Host" : "Serveris",
"Port" : "Prievadas",
"SMTP" : "SMTP",
@@ -844,17 +865,17 @@
"Group" : "Grupė",
"Failed to save text block" : "Nepavyko išsaugoti teksto bloko",
"Shared" : "Bendrinama",
- "Edit {title}" : "Taisyti {title}",
+ "Edit {title}" : "Redaguoti {title}",
"Delete {title}" : "Ištrinti {title}",
"Edit text block" : "Redaguoti teksto bloką",
- "Shares" : "Viešiniai",
+ "Shares" : "Bendrinimai",
"Search for users or groups" : "Ieškoti vartotojų arba grupių",
"Choose a text block to insert at the cursor" : "Pasirinkite teksto bloką, kurį norite įterpti ties žymekliu",
"Insert" : "Įterpti",
"Insert text block" : "Įterpti teksto bloką",
"Account connected" : "Paskyra prijungta",
"You can close this window" : "Galite užverti šį langą",
- "Connect your mail account" : "Priregistruoti elektroninio pašto paskyrą",
+ "Connect your mail account" : "Pridėti elektroninio pašto paskyrą",
"To add a mail account, please contact your administrator." : "Norėdami pridėti pašto paskyrą, susisiekite su savo administratoriumi.",
"All" : "Visos",
"Drafts" : "Juodraščiai",
@@ -872,7 +893,7 @@
"There is already a message in progress. All unsaved changes will be lost if you continue!" : "Jau vyksta žinutės rašymas. Jei tęsite, visi neišsaugoti pakeitimai bus prarasti!",
"Discard changes" : "Atmesti pakeitimus",
"Discard unsaved changes" : "Atmesti neįrašytus pakeitimus",
- "Keep editing message" : "Toliau taisyti laišką",
+ "Keep editing message" : "Toliau redaguoti laišką",
"(All or part of this reply was generated by AI)" : "(Visas šis atsakymas arba jo dalis buvo sugeneruota dirbtinio intelekto)",
"Attachments were not copied. Please add them manually." : "Priedai nebuvo nukopijuoti. Pridėkite juos rankiniu būdu.",
"Could not create snooze mailbox" : "Nepavyko sukurti atidėjimo pašto dėžutės",
diff --git a/l10n/pt_PT.js b/l10n/pt_PT.js
index 4e31e59534..3b64aeebec 100644
--- a/l10n/pt_PT.js
+++ b/l10n/pt_PT.js
@@ -192,6 +192,7 @@ OC.L10N.register(
"Clear locally cached data, in case there are issues with synchronization." : "Limpe a cache de dados local no caso de ter problemas com a sincronização.",
"Subscribed" : "Subscrito",
"New message" : "Nova mensagem",
+ "Draft" : "Rascunho",
"Reply" : "Resposta",
"Error sending your message" : "Erro ao enviar a sua mensagem",
"Retry" : "Repetir",
diff --git a/l10n/pt_PT.json b/l10n/pt_PT.json
index fed189a2d7..87fc06f140 100644
--- a/l10n/pt_PT.json
+++ b/l10n/pt_PT.json
@@ -190,6 +190,7 @@
"Clear locally cached data, in case there are issues with synchronization." : "Limpe a cache de dados local no caso de ter problemas com a sincronização.",
"Subscribed" : "Subscrito",
"New message" : "Nova mensagem",
+ "Draft" : "Rascunho",
"Reply" : "Resposta",
"Error sending your message" : "Erro ao enviar a sua mensagem",
"Retry" : "Repetir",
From 092b16dedde55060e19e1fd95cf3ff23a8c2fe72 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Mon, 18 May 2026 07:38:59 +0200
Subject: [PATCH 035/228] chore(release): v5.9.0-alpha.1
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
CHANGELOG.md | 8 ++++++++
appinfo/info.xml | 2 +-
package-lock.json | 4 ++--
package.json | 2 +-
4 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15a53f5ce2..9baf88b857 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,14 @@
# Changelog
All notable changes to this project will be documented in this file.
+## 5.9.0 – unreleased
+### Added
+* Account delegation
+* HTML and source editing support in composer/signature editor
+* Per-message To/Cc/Bcc recipients in thread view
+### Changed
+* Translations
+
## 5.8.0 – unreleased
### Added
* Deep link support for opening messages by Message-ID
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 9438b8376d..86f5348477 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -34,7 +34,7 @@ The rating depends on the installed text processing backend. See [the rating ove
Learn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).
]]>
- 5.9.0-dev.3
+ 5.9.0-alpha.1
agpl
Christoph Wurst
GretaD
diff --git a/package-lock.json b/package-lock.json
index 9f216b8a32..d5ff128a33 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "nextcloud-mail",
- "version": "5.9.0-dev.1",
+ "version": "5.9.0-alpha.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nextcloud-mail",
- "version": "5.9.0-dev.1",
+ "version": "5.9.0-alpha.1",
"hasInstallScript": true,
"license": "AGPL-3.0-only",
"dependencies": {
diff --git a/package.json b/package.json
index b83de70929..dd20a52879 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "nextcloud-mail",
- "version": "5.9.0-dev.1",
+ "version": "5.9.0-alpha.1",
"private": true,
"description": "Nextcloud Mail",
"license": "AGPL-3.0-only",
From e3dcc0e0ac3b644199abb36def63c6737a89919c Mon Sep 17 00:00:00 2001
From: Joas Schilling
Date: Sat, 16 May 2026 01:10:05 +0200
Subject: [PATCH 036/228] feat(deps): Add Nextcloud 35 support
Signed-off-by: Joas Schilling
---
appinfo/info.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 86f5348477..fd16908695 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -53,7 +53,7 @@ Learn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud
https://user-images.githubusercontent.com/12728974/266270227-86b99bbb-03ea-468b-8408-e248e1730bed.png
-
+
OCA\Mail\BackgroundJob\CleanupJob
From e18b5821674588c39c42791e74390393590b8d98 Mon Sep 17 00:00:00 2001
From: Joas Schilling
Date: Fri, 15 May 2026 12:19:51 +0200
Subject: [PATCH 037/228] chore(CI): Adjust testing matrix for Nextcloud 34 on
main
Signed-off-by: Joas Schilling
---
.github/workflows/test.yml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index d10d7235fc..dde06cc527 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -24,6 +24,8 @@ jobs:
nextcloud-versions: 'stable32'
- php-versions: '8.2'
nextcloud-versions: 'stable33'
+ - php-versions: '8.2'
+ nextcloud-versions: 'stable34'
- php-versions: '8.3'
nextcloud-versions: 'master'
name: Nextcloud ${{ matrix.nextcloud-versions }} php${{ matrix.php-versions }} unit tests ${{ matrix.coverage && '(coverage)' || ''}}
@@ -88,6 +90,10 @@ jobs:
db: 'mysql'
cache: 'redis'
coverage: true
+ - php-versions: 8.4
+ nextcloud-versions: 'stable34'
+ db: 'mysql'
+ cache: 'redis'
- php-versions: 8.5
nextcloud-versions: 'master'
db: 'mysql'
From 0367a07118c904d5522a9047520104145ec7f219 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Tue, 19 May 2026 01:42:09 +0000
Subject: [PATCH 038/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/it.js | 250 ++++++++++++++++++++++++++++++++++++++++++++++--
l10n/it.json | 250 ++++++++++++++++++++++++++++++++++++++++++++++--
l10n/zh_TW.js | 17 ++++
l10n/zh_TW.json | 17 ++++
4 files changed, 520 insertions(+), 14 deletions(-)
diff --git a/l10n/it.js b/l10n/it.js
index 0437fbecb3..3bab88b874 100644
--- a/l10n/it.js
+++ b/l10n/it.js
@@ -106,9 +106,9 @@ OC.L10N.register(
"The folders to use for drafts, sent messages, deleted messages, archived messages and junk messages." : "Le cartelle da usare per bozze, messaggi inviati, messaggi archiviati e posta indesiderata.",
"Automatic trash deletion" : "Eliminazione automatica del cestino",
"Days after which messages in Trash will automatically be deleted:" : "Giorni dopo i quali i messaggi nel cestino verranno eliminati automaticamente:",
- "Autoresponder" : "Risponditore automatico",
+ "Autoresponder" : "Risposta automatica",
"Automated reply to incoming messages. If someone sends you several messages, this automated reply will be sent at most once every 4 days." : "Risposta automatica ai messaggi in arrivo. Se qualcuno ti invia più messaggi, questa risposta automatica verrà inviata al massimo una volta ogni 4 giorni.",
- "The autoresponder uses Sieve, a scripting language supported by many email providers. If you're unsure whether yours does, check with your provider. If Sieve is available, click the button to go to the settings and enable it." : "Il risponditore automatico utilizza Sieve, un linguaggio di scripting supportato da molti provider di posta elettronica. Se non sei sicuro che il tuo lo supporti, verifica con il tuo provider. Se Sieve è disponibile, fai clic sul pulsante per accedere alle impostazioni e abilitarlo.",
+ "The autoresponder uses Sieve, a scripting language supported by many email providers. If you're unsure whether yours does, check with your provider. If Sieve is available, click the button to go to the settings and enable it." : "La risposta automatica utilizza Sieve, un linguaggio di scripting supportato da molti provider di posta elettronica. Se non sei sicuro che il tuo lo supporti, verifica con il tuo provider. Se Sieve è disponibile, fai clic sul pulsante per accedere alle impostazioni e abilitarlo.",
"Go to Sieve settings" : "Vai alle impostazioni Sieve",
"Calendar settings" : "Impostazioni Calendario",
"Classification settings" : "Impostazioni di classificazione",
@@ -130,6 +130,7 @@ OC.L10N.register(
"Cancel" : "Annulla",
"Search the body of messages in priority Inbox" : "Cerca nel corpo dei messaggi nella posta prioritaria",
"Activate" : "Attiva",
+ "Make mails available to Context Chat" : "Rendi le email disponibili per Context Chat",
"Remind about messages that require a reply but received none" : "Promemoria per i messaggi che richiedono una risposta ma non hanno ricevuto alcun riscontro",
"Highlight external addresses" : "Evidenzia indirizzi esterni",
"Could not update preference" : "Impossibile aggiornare la preferenza",
@@ -174,6 +175,7 @@ OC.L10N.register(
"Step 2" : "Passo 2",
"Enable for the current domain" : "Abilita per il dominio corrente",
"Assistance features" : "Funzionalità di assistenza",
+ "Context Chat integration" : "Integrazione con Context Chat",
"Compose new message" : "Componi nuovo messaggio",
"Newer message" : "Messaggio più recente",
"Older message" : "Messaggio più datato",
@@ -205,16 +207,23 @@ OC.L10N.register(
"Encrypt with Mailvelope and send" : "Cifra con Mailvelope e invia",
"Send later" : "Invia più tardi",
"Message {id} could not be found" : "Il messaggio {id} non può essere trovato",
+ "Sign or Encrypt with S/MIME was selected, but we don't have a certificate for the selected alias. The message will not be signed or encrypted." : "Hai selezionato la firma o la cifratura con S/MIME, ma non è disponibile alcun certificato per l’alias scelto. Il messaggio non verrà firmato né cifrato.",
+ "Any existing formatting (for example bold, italic, underline or inline images) will be removed." : "La formattazione esistente (ad esempio grassetto, corsivo, sottolineato o immagini incorporate) verrà rimossa.",
+ "Turn off formatting" : "Disattiva formattazione",
+ "Turn off and remove formatting" : "Disattiva e rimuovi la formattazione",
"Keep formatting" : "Mantieni la formattazione",
"From" : "Da",
"Select account" : "Seleziona account",
"To" : "A",
"Cc/Bcc" : "Cc/Ccn",
+ "Select recipient" : "Seleziona destinatario",
+ "Contact or email address …" : "Contatto o indirizzo email …",
"Cc" : "Cc",
"Bcc" : "Ccn",
"Subject" : "Oggetto",
"Subject …" : "Oggetto...",
"This message came from a noreply address so your reply will probably not be read." : "Nota che il messaggio è arrivato da un indirizzo noreply, perciò la tua risposta non sarà probabilmente letta.",
+ "The following recipients do not have a S/MIME certificate: {recipients}." : "I seguenti destinatari non hanno un certificato S/MIME: {recipients}.",
"The following recipients do not have a PGP key: {recipients}." : "I seguenti destinatari non hanno una chiave PGP: {recipients}.",
"Write message …" : "Scrivi messaggio...",
"Saving draft …" : "Salvataggio bozza…",
@@ -226,6 +235,7 @@ OC.L10N.register(
"Disable formatting" : "Disabilita la formattazione",
"Upload attachment" : "Carica allegato",
"Add attachment from Files" : "Aggiungi allegato da File",
+ "Add share link from Files" : "Aggiungi link condiviso da Files",
"Smart picker" : "Selettore intelligente",
"Request a read receipt" : "Richiedi una conferma di lettura",
"Sign message with S/MIME" : "Firma il messaggio con S/MIME",
@@ -246,7 +256,24 @@ OC.L10N.register(
"Expand composer" : "Espandi compositore",
"Close composer" : "Chiudi compositore",
"Confirm" : "Conferma",
+ "Delegate access" : "Accesso delegato",
"Revoke" : "Revoca",
+ "{userId} will no longer be able to act on your behalf" : "{userId} non potrà più agire per tuo conto",
+ "Could not fetch delegates" : "Non è stato possibile recuperare i delegati",
+ "Delegated access to {userId}" : "Accesso delegato a {userId}",
+ "Could not delegate access" : "Non è stato possibile delegare l’accesso",
+ "Revoked access for {userId}" : "Revoca l'accesso a {userId}",
+ "Could not revoke delegation" : "Non è possibile revocare la delega",
+ "Delegation" : "Delega",
+ "Allow users to send, receive, and delete mail on your behalf" : "Consenti agli utenti delegati di inviare, ricevere ed eliminare email per tuo conto",
+ "Revoke access" : "Revoca l'accesso",
+ "Add delegate" : "Aggiungi delegato",
+ "Select a user" : "Seleziona un utente",
+ "They will be able to send, receive, and delete mail on your behalf" : "Potranno inviare, ricevere ed eliminare email per tuo conto",
+ "Revoke access?" : "Revocare l'accesso?",
+ "Tag: {name} deleted" : "Etichetta: {name} eliminata",
+ "An error occurred, unable to delete the tag." : "Si è verificato un errore: non è stato possibile eliminare l’etichetta.",
+ "The tag will be deleted from all messages." : "L’etichetta verrà rimossa da tutti i messaggi.",
"Plain text" : "Testo semplice",
"Rich text" : "Testo formattato",
"No messages in this folder" : "Nessun messaggio in questa cartella",
@@ -262,9 +289,18 @@ OC.L10N.register(
"Set reminder for this weekend" : "Imposta promemoria per questo fine settimana",
"Next week – {timeLocale}" : "Prossima settimana – {timeLocale}",
"Set reminder for next week" : "Imposta promemoria per la prossima settimana",
+ "Could not apply tag, configured tag not found" : "Non è stato possibile applicare l’etichetta: l’etichetta configurata non è stata trovata",
+ "Could not move thread, destination mailbox not found" : "Non è stato possibile spostare la conversazione: la cartella di destinazione non è stata trovata",
+ "Could not execute quick action" : "Non è stato possibile eseguire l’azione rapida",
"Quick action executed" : "Azione rapida eseguita",
+ "No trash folder configured" : "Nessuna cartella Cestino configurata",
"Could not delete message" : "Impossibile eliminare il messaggio",
"Could not archive message" : "Impossibile archiviare il messaggio",
+ "Thread was snoozed" : "Conversazione posticipata",
+ "Could not snooze thread" : "Non è possibile posticipare la conversazione",
+ "Thread was unsnoozed" : "Posicipo della conversazione annullato",
+ "Could not unsnooze thread" : "Non è stato possibile annullare il posticipo della conversazione",
+ "This summary was AI generated" : "Questo riepilogo è stato generato tramite IA",
"Encrypted message" : "Messaggio cifrato",
"This message is unread" : "Questo messaggio è non letto",
"Unfavorite" : "Rimuovi preferito",
@@ -275,6 +311,8 @@ OC.L10N.register(
"Mark not spam" : "Marca come posta non indesiderata",
"Mark as spam" : "Marca come posta indesiderata",
"Edit tags" : "Modifica etichette",
+ "Snooze" : "Posticipa",
+ "Unsnooze" : "Annulla posticipo",
"Move thread" : "Sposta conversazione",
"Move Message" : "Sposta messaggio",
"Archive thread" : "Archivia la discussione",
@@ -283,7 +321,9 @@ OC.L10N.register(
"Delete message" : "Elimina messaggio",
"More actions" : "Altre azioni",
"Back" : "Indietro",
+ "Set custom snooze" : "Imposta posticipo personalizzato",
"Edit as new message" : "Modifica come nuovo messaggio",
+ "Reply with meeting" : "Rispondi proponendo una riunione",
"Create task" : "Crea attività",
"Download message" : "Scarica messaggio",
"Back to all actions" : "Torna a tutte le azioni",
@@ -296,16 +336,22 @@ OC.L10N.register(
"_Unfavorite {number}_::_Unfavorite {number}_" : ["Rimuovi dai preferiti {number}","Rimuovi dai preferiti {number}","Rimuovi dai preferiti {number}"],
"_Favorite {number}_::_Favorite {number}_" : ["Aggiungi ai preferiti {number}","Aggiungi ai preferiti {number}","Aggiungi ai preferiti {number}"],
"_Unselect {number}_::_Unselect {number}_" : ["Deseleziona {number}","Deseleziona {number}","Deseleziona {number}"],
+ "_Mark {number} as spam_::_Mark {number} as spam_" : ["Segna {number} come spam","Segna {number} come spam","Segna {number} come spam"],
+ "_Mark {number} as not spam_::_Mark {number} as not spam_" : ["Segna {number} come non spam","Segna {number} come non spam","Segna {number} come non spam"],
+ "_Edit tags for {number}_::_Edit tags for {number}_" : ["Modifica etichetta per {number}","Modifica etichette per {number}","Modifica etichette per {number}"],
"_Move {number} thread_::_Move {number} threads_" : ["Sposta {number} conversazione","Sposta {number} conversazioni","Sposta {number} conversazioni"],
"_Forward {number} as attachment_::_Forward {number} as attachment_" : ["Inoltra {number} come allegato","Inoltra {number} come allegati","Inoltra {number} come allegati"],
"Mark as unread" : "Segna come non letto",
"Mark as read" : "Segna come letto",
+ "Mark as unimportant" : "Segna come non importante",
+ "Mark as important" : "Segna come importante",
"Report this bug" : "Segnala questo bug",
"Event created" : "Evento creato",
"Could not create event" : "Impossibile creare l'evento",
"Create event" : "Crea evento",
"All day" : "Tutto il giorno",
"Attendees" : "Partecipanti",
+ "You can only invite attendees if your account has an email address set" : "Puoi invitare partecipanti solo se il tuo account ha un indirizzo email configurato",
"Select calendar" : "Seleziona calendario",
"Description" : "Descrizione",
"Create" : "Crea",
@@ -328,43 +374,79 @@ OC.L10N.register(
"Decline" : "Rifiuta",
"Tentatively accept" : "Accetta provvisoriamente",
"More options" : "Altre opzioni",
+ "This message has an attached invitation but the invitation dates are in the past" : "Questo messaggio contiene un invito, ma le date dell’invito sono già passate.",
+ "This message has an attached invitation but the invitation does not contain a participant that matches any configured mail account address" : "Questo messaggio contiene un invito, ma nell’invito non è presente alcun partecipante associato agli indirizzi email configurati.",
+ "Could not remove internal address {sender}" : "Non è stato possibile rimuovere l’indirizzo interno {sender}",
+ "Could not add internal address {address}" : "Non è stato possibile aggiungere l’indirizzo interno {address}",
"individual" : "individuale",
"domain" : "dominio",
"Remove" : "Rimuovi",
"Add internal address" : "Aggiungi indirizzo interno",
+ "Add internal email or domain" : "Aggiungi indirizzo email o dominio interno",
"Itinerary for {type} is not supported yet" : "L'itinerario per {type} non è ancora supportato",
+ "To archive a message please configure an archive folder in account settings" : "Per archiviare un messaggio, configura prima una cartella Archivio nelle impostazioni dell’account",
"You are not allowed to move this message to the archive folder and/or delete this message from the current folder" : "Non ti è consentito spostare questo messaggio nella cartella degli archivi e/o eliminare questo messaggio dalla cartella corrente.",
+ "Your IMAP server does not support storing the seen/unseen state." : "Il server IMAP non supporta il salvataggio dello stato letto/non letto.",
+ "Could not mark message as seen/unseen" : "Non è stato possibile segnare il messaggio come letto/non letto",
"Last hour" : "Ultima ora",
"Today" : "Oggi",
"Yesterday" : "Ieri",
"Last week" : "Ultima settimana",
"Last month" : "Ultimo mese",
+ "Could not open folder" : "Non è possibile aprire la cartella",
+ "Loading messages …" : "Caricamento messaggi in corso …",
+ "Indexing your messages. This can take a bit longer for larger folders." : "Indicizzazione dei messaggi in corso. Per le cartelle più grandi l’operazione potrebbe richiedere più tempo.",
"Choose target folder" : "Scegli la cartella di destinazione",
"No more submailboxes in here" : "Qui non ci sono altre sotto-caselle di posta",
+ "Messages will automatically be marked as important using AI. The system learns from which messages you interact with or mark as important. In the beginning you might have to manually change the importance to teach it, but it will improve over time" : "I messaggi verranno contrassegnati automaticamente come importanti tramite l’IA. Il sistema impara dai messaggi con cui interagisci o che segni come importanti. All’inizio potresti dover modificare manualmente il livello di importanza per addestrarlo, ma la precisione migliorerà nel tempo.",
+ "Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "I messaggi che hai aggiunto ai preferiti verranno mostrati in cima alle cartelle. Puoi disattivare questa opzione dalle impostazioni di Posta.",
+ "AI identifies messages sent by you that likely require a reply but did not receive one after a couple of days and shows them here" : "L’IA identifica i messaggi inviati da te che probabilmente richiedono una risposta ma che non ne hanno ricevuta dopo alcuni giorni, e li mostra qui.",
"Favorites" : "Preferiti",
+ "Favorites info" : "Informazioni sui preferiti",
+ "Load more favorites" : "Carica altri preferiti",
+ "Follow up" : "Follow-up",
+ "Follow up info" : "Informazioni sui follow-up",
+ "Load more follow ups" : "Carica altri follow-up",
"Important info" : "Informazione importante",
+ "Load more important messages" : "Carica altri messaggi importanti",
"Other" : "Altro",
+ "Load more other messages" : "Carica altri messaggi",
"Could not send mdn" : "Impossibile inviare mdn",
"The sender of this message has asked to be notified when you read this message." : "Il mittente di questo messaggio ha chiesto di essere avvisato quando leggi questo messaggio.",
"Notify the sender" : "Notifica al mittente",
"You sent a read confirmation to the sender of this message." : "Hai inviato una conferma di lettura al mittente di questo messaggio.",
+ "Message was snoozed" : "Messaggio posticipato",
+ "Could not snooze message" : "Non è possibile posticipare il messaggio",
+ "Message was unsnoozed" : "Posticipo del messaggio annullato",
+ "Could not unsnooze message" : "Non è stato possibile annullare il posticipo del messaggio",
"Forward" : "Inoltra",
"Move message" : "Sposta messaggio",
"Translate" : "Traduci",
+ "Forward message as attachment" : "Inoltra il messaggio come allegato",
"View source" : "Visualizza sorgente",
"Print message" : "Stampa messaggio",
+ "Create mail filter" : "Crea filtro email",
"Download thread data for debugging" : "Scarica i dati del conversazione per il debug",
+ "Suggested replies are using AI" : "Le risposte suggerite sono generate tramite IA",
"Message body" : "Corpo del messaggio",
+ "Warning: The S/MIME signature of this message is unverified. The sender might be impersonating someone!" : "Attenzione: la firma S/MIME di questo messaggio non è verificata. Il mittente potrebbe non essere chi dichiara di essere.",
+ "AI info" : "IA informazioni",
"Unnamed" : "Senza nome",
"Embedded message" : "Messaggio incorporato",
+ "Attachment saved to Files" : "Allegato salvato in Files",
+ "Attachment could not be saved" : "L'allegato non può essere salvato",
"calendar imported" : "calendario importato",
"Choose a folder to store the attachment in" : "Scegli una cartella dove salvare l'allegato",
"Import into calendar" : "Importa nel calendario",
"Download attachment" : "Scarica allegato",
"Save to Files" : "Salva in File",
+ "Attachments saved to Files" : "Allegati salvati in Files",
+ "Error while saving attachments" : "Errore durante il salvataggio degli allegati",
+ "View fewer attachments" : "Mostra meno allegati",
"Choose a folder to store the attachments in" : "Scegli una cartella in cui salvare gli allegati",
"Save all to Files" : "Salva tutto in File",
"Download Zip" : "Scarica Zip",
+ "_View {count} more attachment_::_View {count} more attachments_" : ["Mostra altri {count} allegati","Mostra altri {count} allegati","Mostra altri {count} allegati"],
"This message is encrypted with PGP. Install Mailvelope to decrypt it." : "Questo messaggio è cifrato con PGP. Installa Mailvelope per decifrarlo.",
"The images have been blocked to protect your privacy." : "Le immagini sono state bloccate per proteggere la tua riservatezza.",
"Show images" : "Mostra le immagini",
@@ -377,11 +459,18 @@ OC.L10N.register(
"Moving" : "Spostamento",
"Moving thread" : "Spostamento conversazione",
"Moving message" : "Spostamento messaggio",
+ "This account cannot connect" : "Questo account non riesce a connettersi",
+ "Connection failed. Please verify your information and try again" : "Connessione non riuscita. Verifica i dati inseriti e riprova.",
"Used quota: {quota}% ({limit})" : "Spazio utilizzato: {quota} % ({limit})",
"Used quota: {quota}%" : "Spazio utilizzato: {quota}%",
+ "Unable to create mailbox. The name likely contains invalid characters. Please try another name." : "Non è stato possibile creare la cartella. Il nome contiene probabilmente caratteri non validi. Prova a usare un altro nome.",
"Remove account" : "Rimuovi account",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "L'account per {email} e i dati di posta elettronica memorizzati nella cache saranno rimossi da Nextcloud, ma non dal tuo fornitore di posta elettronica.",
"Remove {email}" : "Rimuovi {email}",
+ "could not delete account" : "Non è stato possibile eliminare l’account",
+ "Provisioned account is disabled" : "L’account configurato automaticamente è disattivato",
+ "Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Accedi con password per abilitare questo account. La sessione corrente usa un accesso senza password, ad esempio SSO o WebAuthn.",
+ "Delegate account" : "Account delegato",
"Show only subscribed folders" : "Mostra solo le cartelle sottoscritte",
"Add folder" : "Aggiungi cartella",
"Folder name" : "Nome della cartella",
@@ -394,19 +483,26 @@ OC.L10N.register(
"_{total} message_::_{total} messages_" : ["{total} messaggio","{total} messaggi","{total} messaggi"],
"_{unread} unread of {total}_::_{unread} unread of {total}_" : ["{unread} non letto di {total}","{unread} non letti di {total}","{unread} non letti di {total}"],
"Loading …" : "Caricamento in corso...",
+ "All messages in mailbox will be deleted." : "Tutti i messaggi presenti nella cartella verranno eliminati.",
+ "Clear mailbox {name}" : "Svuota cartella {name}",
+ "Clear folder" : "Svuota cartella",
"The folder and all messages in it will be deleted." : "La cartella e tutti i messaggi in essa saranno eliminati.",
"Delete folder" : "Elimina cartella",
"Delete folder {name}" : "Elimina cartella {name}",
"An error occurred, unable to rename the mailbox." : "Si è verificato un errore, impossibile rinominare la casella di posta.",
+ "Please wait 10 minutes before repairing again" : "Attendi 10 minuti prima di ripetere la riparazione",
"Mark all as read" : "Marca tutti come letti",
"Add subfolder" : "Aggiungi sottocartella",
"Rename" : "Rinomina",
"Move folder" : "Sposta cartella",
+ "Repair folder" : "Ripara cartella",
"Clear cache" : "Svuota cache",
"Clear locally cached data, in case there are issues with synchronization." : "Cancella i dati locali in cache, nel caso ci siano problemi di sincronizzazione.",
"Subscribed" : "Sottoscritta",
"Sync in background" : "Sincronizza in background",
+ "Delete all messages" : "Elimina tutti i messaggi",
"Outbox" : "Posta in uscita",
+ "Translate this message to {language}" : "Traduci questo messaggio in {language}",
"New message" : "Nuovo messaggio",
"Edit message" : "Modifica messaggio",
"Draft" : "Bozza",
@@ -416,36 +512,59 @@ OC.L10N.register(
"Failed to save draft" : "Impossibile salvare la bozza",
"attachment" : "allegato",
"attached" : "allegato",
+ "No \"sent\" folder configured. Please pick one in the account settings." : "Nessuna cartella “Posta inviata” configurata. Selezionane una nelle impostazioni dell’account.",
"You are trying to send to many recipients in To and/or Cc. Consider using Bcc to hide recipient addresses." : "Stai tentando di inviare a troppi destinatari in A e/o CC. Considera l'idea di utilizzare CCN per nascondere gli indirizzi dei destinatari.",
"Your message has no subject. Do you want to send it anyway?" : "Il tuo messaggio non ha oggetto. Vuoi inviarlo comunque?",
"You mentioned an attachment. Did you forget to add it?" : "Hai menzionato un allegato. Hai dimenticato di aggiungerlo?",
"Message discarded" : "Messaggio scartato",
"Could not discard message" : "Impossibile eliminare il messaggio",
+ "Maximize composer" : "Espandi finestra",
+ "Show recipient details" : "Mostra dettagli dei destinatari",
+ "Hide recipient details" : "Nascondi dettagli dei destinatari",
+ "Minimize composer" : "Riduci finestra",
"Error sending your message" : "Errore di invio del messaggio",
"Retry" : "Riprova",
"Warning sending your message" : "Avviso durante l'invio del tuo messaggio",
"Send anyway" : "Invia comunque",
- "Autoresponder off" : "Risponditore automatico spento",
- "Autoresponder on" : "Risponditore automatico attivo",
+ "Welcome to {productName} Mail" : "Benvenuto in {productName} Mail",
+ "Start writing a message by clicking below or select an existing message to display its contents" : "Inizia a scrivere un messaggio cliccando qui sotto oppure seleziona un messaggio esistente per visualizzarne il contenuto",
+ "Autoresponder off" : "Risposta automatica disattivata",
+ "Autoresponder on" : "Risposta automatica attiva",
+ "Autoresponder follows system settings" : "La risposta automatica segue le impostazioni di sistema",
+ "The autoresponder follows your personal absence period settings." : "La risposta automatica segue le impostazioni del tuo periodo di assenza.",
+ "Edit absence settings" : "Modifica impostazioni di assenza",
"First day" : "Primo giorno",
"Last day (optional)" : "Ultimo giorno (facoltativo)",
+ "${subject} will be replaced with the subject of the message you are responding to" : "${subject} verrà sostituito con l’oggetto del messaggio a cui stai rispondendo",
"Message" : "Messaggio",
"Oh Snap!" : "Accidenti!",
- "Save autoresponder" : "Salva risponditore automatico",
+ "Save autoresponder" : "Salva risposta automatica",
"Could not open outbox" : "Impossibile aprire la posta in uscita",
+ "Pending or not sent messages will show up here" : "Qui verranno mostrati i messaggi in sospeso o non ancora inviati",
+ "Could not copy to \"Sent\" folder" : "Non è possibile copiare nella cartella \"Posta inviata\"",
+ "Mail server error" : "Errore del server di posta",
"Message could not be sent" : "Il messaggio non può essere inviato",
"Message deleted" : "Messaggio eliminato",
+ "Copy to \"Sent\" Folder" : "Copia nella cartella \"Posta inviata\"",
+ "Copy to Sent Folder" : "Copia nella cartella Posta inviata",
+ "Phishing email" : "Email di phishing",
+ "This email might be a phishing attempt" : "Questa email potrebbe essere un tentativo di phishing",
+ "Hide suspicious links" : "Nascondi link sospetti",
+ "Show suspicious links" : "Mostra link sospetti",
+ "link text" : "testo del link",
"Copied email address to clipboard" : "Indirizzo email copiato negli appunti",
"Could not copy email address to clipboard" : "Impossibile copiare l'indirizzo email negli appunti",
"Contacts with this address" : "Contatti con questo indirizzo",
"Add to Contact" : "Aggiungi ai contatti",
"New Contact" : "Nuovo contatto",
"Copy to clipboard" : "Copia negli appunti",
+ "Contact name …" : "Nome contatto …",
"Add" : "Aggiungi",
"Show less" : "Mostra meno",
"Show more" : "Mostra più",
"Clear" : "Pulisci",
"Search in folder" : "Cerca nella cartella",
+ "Open search modal" : "Apri finestra di ricerca",
"Close" : "Chiudi",
"Search parameters" : "Parametri di ricerca",
"Search subject" : "Cerca nell'oggetto",
@@ -460,9 +579,13 @@ OC.L10N.register(
"Select BCC recipients" : "Seleziona i destinatari CCN",
"Tags" : "Etichette",
"Select tags" : "Seleziona etichette",
+ "Marked as" : "Contrassegnato come",
"Has attachments" : "Ha allegati",
+ "Mentions me" : "Mi menziona",
+ "Has attachment" : "Con allegato",
+ "To me" : "A me",
"Enable mail body search" : "Abilita ricerca nel corpo del messaggio",
- "Sieve is a powerful language for writing filters for your mailbox. You can manage the sieve scripts in Mail if your email service supports it. Sieve is also required to use Autoresponder and Filters." : "Sieve è un potente linguaggio per la creazione di filtri per la tua casella di posta. Puoi gestire gli script Sieve nell’app Posta se il tuo servizio email lo supporta. Sieve è inoltre necessario per utilizzare il risponditore automatico e i filtri.",
+ "Sieve is a powerful language for writing filters for your mailbox. You can manage the sieve scripts in Mail if your email service supports it. Sieve is also required to use Autoresponder and Filters." : "Sieve è un potente linguaggio per la creazione di filtri per la tua casella di posta. Puoi gestire gli script Sieve nell’app Posta se il tuo servizio email lo supporta. Sieve è inoltre necessario per utilizzare le risposte automatiche e i filtri.",
"Enable sieve filter" : "Abilita filtri Sieve",
"Sieve host" : "Host Sieve",
"Sieve security" : "Sicurezza Sieve",
@@ -472,33 +595,67 @@ OC.L10N.register(
"Custom" : "Personalizzato",
"Sieve User" : "Utente Sieve",
"Sieve Password" : "Password Sieve",
+ "Oh snap!" : "Ops!",
"Save sieve settings" : "Salva impostazione Sieve",
+ "The syntax seems to be incorrect:" : "La sintassi non sembra corretta:",
"Save sieve script" : "Salva script Sieve",
"Signature …" : "Scrivi firma …",
+ "Your signature is larger than 2 MB. This may affect the performance of your editor." : "La firma supera i 2 MB e potrebbe rallentare l’editor.",
"Save signature" : "Salva firma",
"Place signature above quoted text" : "Posiziona la firma sopra il testo citato",
"Message source" : "Sorgente del messaggio",
"An error occurred, unable to rename the tag." : "Si è verificato un errore, impossibile rinominare l'etichetta.",
"Edit name or color" : "Modifica nome o colore",
+ "Saving new tag name …" : "Salvataggio del nuovo nome dell’etichetta in corso …",
"Delete tag" : "Elimina etichetta",
+ "Set tag" : "Assegna etichetta",
+ "Unset tag" : "Rimuovi etichetta",
+ "Tag name is a hidden system tag" : "Questo nome è riservato a un’etichetta di sistema nascosta",
"Tag already exists" : "L'etichetta esiste già",
+ "Tag name cannot be empty" : "Il nome dell’etichetta non può essere vuoto",
"An error occurred, unable to create the tag." : "Si è verificato un errore, impossibile creare l'etichetta.",
"Add default tags" : "Aggiungi etichette predefiniti",
"Add tag" : "Aggiungi etichetta",
+ "Saving tag …" : "Salvataggio etichetta in corso …",
"Task created" : "Attività creata",
"Could not create task" : "Impossibile creare l'attività",
+ "No calendars with task list support" : "Nessun calendario supporta le liste di attività",
+ "Summarizing thread failed." : "Non è stato possibile generare il riepilogo della conversazione.",
"Could not load your message thread" : "Impossibile caricare la tua discussione",
+ "The thread doesn't exist or has been deleted" : "La conversazione non esiste oppure è stata eliminata",
+ "Email was not able to be opened" : "Non è stato possibile aprire l’email",
"Print" : "Stampa",
"Could not print message" : "Impossibile stampare il messaggio",
+ "Loading thread" : "Caricamento conversazione in corso",
"Not found" : "Non trovato",
"Encrypted & verified " : "Cifrato e verificato",
"Signature verified" : "Firma verificata",
"Signature unverified " : "Firma non verificata",
"This message was encrypted by the sender before it was sent." : "Questo messaggio è stato cifrato dal mittente prima di essere inviato.",
+ "This message contains a verified digital S/MIME signature. The message wasn't changed since it was sent." : "Questo messaggio contiene una firma digitale S/MIME verificata. Il messaggio non è stato modificato dopo l’invio.",
+ "This message contains an unverified digital S/MIME signature. The message might have been changed since it was sent or the certificate of the signer is untrusted." : "Questo messaggio contiene una firma digitale S/MIME non verificata. Il messaggio potrebbe essere stato modificato dopo l’invio oppure il certificato del firmatario potrebbe non essere attendibile.",
"Reply all" : "Rispondi a tutti",
+ "Unsubscribe request sent" : "Richiesta di disiscrizione inviata",
+ "Could not unsubscribe from mailing list" : "Non è stato possibile disiscriversi dalla mailing list",
+ "Please wait for the message to load" : "Attendi il caricamento del messaggio",
+ "Disable reminder" : "Disattiva promemoria",
"Unsubscribe" : "Rimuovi sottoscrizione",
"Reply to sender only" : "Rispondi solo al mittente",
+ "Mark as unfavorite" : "Rimuovi dai preferiti",
+ "Mark as favorite" : "Aggiungi ai preferiti",
+ "To:" : "A: ",
+ "Cc:" : "Cc:",
+ "Bcc:" : "Bcc:",
+ "Unsubscribe via link" : "Disiscriviti tramite link",
+ "Unsubscribing will stop all messages from the mailing list {sender}" : "Disiscrivendoti non riceverai più messaggi da questa mailing list {sender}",
+ "Send unsubscribe email" : "Invia email di disiscrizione",
+ "Unsubscribe via email" : "Disiscriviti tramite email",
+ "{name} Assistant" : "{name} Assistente",
+ "Thread summary" : "Riepilogo della conversazione",
"Go to latest message" : "Vai all'ultimo messaggio",
+ "Newest message" : "Messaggio più recente",
+ "This summary is AI generated and may contain mistakes." : "Questo riepilogo è stato generato tramite IA e potrebbe contenere imprecisioni.",
+ "Please select languages to translate to and from" : "Seleziona la lingua di partenza e quella di destinazione per la traduzione",
"The message could not be translated" : "Questo messaggio non può essere tradotto",
"Translation copied to clipboard" : "Traduzione copiata negli appunti",
"Translation could not be copied" : "La traduzione non può essere copiata",
@@ -508,6 +665,7 @@ OC.L10N.register(
"Target language to translate into" : "Lingua di destinazione in cui tradurre",
"Translate to" : "Traduci in",
"Translating" : "Traduco",
+ "This translation is generated using AI and may contain inaccuracies" : "Questa traduzione è stata generata con l’IA e potrebbe contenere imprecisioni",
"Copy translated text" : "Copia testo tradotto",
"Disable trash retention by leaving the field empty or setting it to 0. Only mails deleted after enabling trash retention will be processed." : "Disattiva la conservazione nel cestino lasciando il campo vuoto o impostandolo a 0. Verranno elaborati solo i messaggi eliminati dopo l’attivazione della conservazione.",
"Could not remove trusted sender {sender}" : "Impossibile rimuovere il mittente fidato {sender}",
@@ -522,15 +680,48 @@ OC.L10N.register(
"{trainNr} from {depStation} to {arrStation}" : "{trainNr} da {depStation} a {arrStation}",
"Train from {depStation} to {arrStation}" : "Treno da {depStation} a {arrStation}",
"Train" : "Treno",
+ "Mark message as" : "Contrassegna il messaggio come",
+ "Add flag" : "Aggiungi contrassegno",
"Move into folder" : "Sposta nella cartella",
"Stop" : "Ferma",
+ "Delete action" : "Elimina azione",
+ "Answered" : "Risposto",
"Deleted" : "Eliminato",
+ "Flagged" : "Contrassegnato",
+ "Seen" : "Letto",
+ "Enter flag" : "Inserisci contrassegno",
+ "Stop ends all processing" : "Interrompi: termina tutte le elaborazioni",
+ "Sender" : "Mittente",
"Recipient" : "Destinatario",
+ "Create a new mail filter" : "Crea un nuovo filtro email",
+ "Choose the headers you want to use to create your filter. In the next step, you will be able to refine the filter conditions and specify the actions to be taken on messages that match your criteria." : "Scegli le intestazioni da usare per creare il filtro. Nel passaggio successivo potrai definire meglio le condizioni e indicare quali azioni applicare ai messaggi che corrispondono ai criteri scelti.",
"Delete filter" : "Elimina filtro",
+ "Delete mail filter {filterName}?" : "Cancella filtro email {filterName}?",
+ "Are you sure to delete the mail filter?" : "Sei sicuro di cancellare il filtro email?",
+ "New filter" : "Nuovo filtro",
+ "Filter saved" : "Filtro salvato",
+ "Could not save filter" : "Impossibile salvare il filtro",
+ "Filter deleted" : "Filtro cancellato",
+ "Could not delete filter" : "Impossibile cancellare il filtro",
+ "Take control of your email chaos. Filters help you to prioritize what matters and eliminate clutter." : "Metti ordine nella tua posta. I filtri ti aiutano a dare priorità ai messaggi importanti e a ridurre il superfluo.",
+ "Hang tight while the filters load" : "Caricamento dei filtri in corso",
+ "Filter is active" : "Il filtro è attivo",
+ "Filter is not active" : "Il filtro non è attivo",
+ "If all the conditions are met, the actions will be performed" : "Se tutte le condizioni sono soddisfatte, verranno eseguite le azioni previste",
+ "If any of the conditions are met, the actions will be performed" : "Se almeno una delle condizioni è soddisfatta, verranno eseguite le azioni previste",
"Help" : "Assistenza",
"contains" : "contiene",
+ "A substring match. The field matches if the provided value is contained within it. For example, \"report\" would match \"port\"." : "Corrispondenza parziale. Il campo corrisponde se contiene il valore indicato. Ad esempio, “report” può corrispondere a “Business report 2024”.",
"matches" : "corrisponde",
+ "A pattern match using wildcards. The \"*\" symbol represents any number of characters (including none), while \"?\" represents exactly one character. For example, \"*report*\" would match \"Business report 2024\"." : "Corrispondenza tramite caratteri jolly. Il simbolo “*” rappresenta qualsiasi numero di caratteri (anche nessuno), mentre “?” rappresenta esattamente un carattere. Ad esempio, “*report*” può corrispondere a “Business report 2024”.",
+ "Enter subject" : "Inserisci oggetto",
+ "Enter sender" : "Inserisci mittente",
+ "Enter recipient" : "Inserisci destinatario",
+ "is exactly" : "è esattamente",
+ "Conditions" : "Condizioni",
+ "Add condition" : "Aggiungi condizione",
"Actions" : "Azioni",
+ "Add action" : "Aggiungi azione",
"Priority" : "Priorità",
"Enable filter" : "Abilita filtri",
"Tag" : "Etichetta",
@@ -538,11 +729,19 @@ OC.L10N.register(
"Edit quick action" : "Modifica azione rapida",
"Add quick action" : "Aggiungi azione rapida",
"Quick action deleted" : "Azione rapida eliminata",
+ "Failed to delete quick action" : "Non è stato possibile eliminare l’azione rapida",
+ "Failed to update quick action" : "Non è stato possibile aggiornare l’azione rapida",
+ "Failed to update step in quick action" : "Non è stato possibile aggiornare il passaggio dell’azione rapida",
"Quick action updated" : "Azione rapida aggiornata",
+ "Failed to create quick action" : "Non è stato possibile creare l’azione rapida",
+ "Failed to add steps to quick action" : "Non è stato possibile aggiungere passaggi all’azione rapida",
"Quick action created" : "Azione rapida creata",
+ "Failed to delete action step" : "Non è stato possibile eliminare il passaggio dell’azione",
"No quick actions yet." : "Nessuna azione rapida disponibile al momento.",
"Edit" : "Modifica",
"Quick action name" : "Azione rapida nome",
+ "Do the following actions" : "Esegui le seguenti azioni",
+ "Add another action" : "Aggiungi un’altra azione",
"Successfully updated config for \"{domain}\"" : "Configurazione aggiornata con successo per \"{domain}\"",
"Error saving config" : "Errore durante il salvataggio della configurazione",
"Saved config for \"{domain}\"" : "Configurazione salvata per \"{domain}\"",
@@ -551,6 +750,7 @@ OC.L10N.register(
"There was an error when provisioning accounts." : "Si è verificato un errore durante il approvvigionamento degli account.",
"Successfully deleted and deprovisioned accounts for \"{domain}\"" : " Account eliminati e approvvigionato correttamente per \"{domain}\"",
"Error when deleting and deprovisioning accounts for \"{domain}\"" : "Errore durante l'eliminazione e il approvvigionamento degli account per \"{domain}\"",
+ "Could not save default classification setting" : "Non è stato possibile salvare l’impostazione di classificazione predefinita",
"Mail app" : "Applicazione di posta",
"The mail app allows users to read mails on their IMAP accounts." : "L'applicazione di posta consente agli utenti di leggere i messaggi dei propri account IMAP.",
"Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Qui puoi trovare le impostazioni a livello di istanza. Le impostazioni specifiche dell'utente si trovano nell'applicazione stessa (angolo in basso a sinistra).",
@@ -566,11 +766,28 @@ OC.L10N.register(
"Provisioning Configurations" : "Configurazione di approvvigionamento",
"Add new config" : "Aggiungi nuova configurazione",
"Provision all accounts" : "Predisponi tutti gli account",
+ "Allow additional mail accounts" : "Consenti account email aggiuntivi",
+ "Allow additional Mail accounts from User Settings" : "Consenti account Mail aggiuntivi dalle impostazioni utente",
+ "Enable text processing through LLMs" : "Abilita elaborazione del testo tramite LLM",
+ "The Mail app can process user data with the help of the configured large language model and provide assistance features like thread summaries, smart replies and event agendas." : "L’app Mail può elaborare i dati dell’utente tramite il modello linguistico configurato e offrire funzionalità avanzate come riepiloghi delle conversazioni, risposte intelligenti e agenda degli eventi.",
+ "Enable LLM processing" : "Abilita elaborazione tramite LLM",
+ "Enable classification by importance by default" : "Abilita di default la classificazione per importanza",
+ "The Mail app can classify incoming emails by importance using machine learning. This feature is enabled by default but can be disabled by default here. Individual users will still be able to toggle the feature for their accounts." : "L’app Mail può classificare automaticamente le email in arrivo in base alla loro importanza tramite machine learning. La funzionalità è attiva per impostazione predefinita, ma può essere disattivata qui. I singoli utenti potranno comunque abilitarla o disabilitarla per il proprio account.",
+ "Enable classification of important mails by default" : "Abilita di default la classificazione delle email importanti",
"Anti Spam Service" : "Servizio anti-spam",
"You can set up an anti spam service email address here." : "È possibile impostare un indirizzo e-mail del servizio Anti-Spam qui.",
"Any email that is marked as spam will be sent to the anti spam service." : "Qualsiasi email contrassegnata come posta indesiderata verrà inviata al servizio anti-spam.",
"Gmail integration" : "Integrazione Gmail",
+ "Gmail allows users to access their email via IMAP. For security reasons this access is only possible with an OAuth 2.0 connection or Google accounts that use two-factor authentication and app passwords." : "Gmail consente l’accesso alle email tramite IMAP. Per motivi di sicurezza, questa modalità è disponibile solo tramite una connessione OAuth 2.0 oppure per gli account Google con autenticazione a due fattori e password per le app.",
+ "You have to register a new Client ID for a \"Web application\" in the Google Cloud console. Add the URL {url} as authorized redirect URI." : "Devi registrare un nuovo Client ID di tipo “Applicazione web” nella console Google Cloud. Aggiungi l’URL {url} come URI di reindirizzamento autorizzato.",
"Microsoft integration" : "Integrazione Microsoft",
+ "Microsoft requires you to access your emails via IMAP using OAuth 2.0 authentication. To do this, you need to register an app with Microsoft Entra ID, formerly known as Microsoft Azure Active Directory." : "Microsoft richiede l’accesso alle email tramite IMAP con autenticazione OAuth 2.0. Per configurarlo, devi registrare un’app in Microsoft Entra ID, in precedenza noto come Microsoft Azure Active Directory.",
+ "Redirect URI" : "URI di reindirizzamento",
+ "For more details, please click here to open our documentation." : "Per maggiori dettagli, fai clic qui per aprire la documentazione.",
+ "User Interface Preference Defaults" : "Preferenze predefinite dell’interfaccia utente",
+ "These settings are used to pre-configure the user interface preferences they can be overridden by the user in the mail settings" : "Queste impostazioni servono a preconfigurare le preferenze dell’interfaccia utente. L’utente potrà comunque modificarle dalle impostazioni di Posta.",
+ "Message View Mode" : "Modalità di visualizzazione dei messaggi",
+ "Show only the selected message" : "Mostra solo il messaggio selezionato",
"Successfully set up anti spam email addresses" : "Impostare correttamente gli indirizzi e-mail anti-spam",
"Error saving anti spam email addresses" : "Errore durante il salvataggio degli indirizzi email anti-spam",
"Successfully deleted anti spam reporting email" : "Email di segnalazione anti-spam eliminata con successo",
@@ -623,6 +840,7 @@ OC.L10N.register(
"The provided PKCS #12 certificate must contain at least one certificate and exactly one private key." : "Il certificato PKCS #12 fornito deve contenere almeno un certificato ed esattamente una chiave privata.",
"Failed to import the certificate. Please check the password." : "Impossibile importare il certificato. Controlla la password.",
"Certificate imported successfully" : "Certificato importato correttamente",
+ "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Non è stato possibile importare il certificato. Verifica che la chiave privata corrisponda al certificato e che non sia protetta da passphrase.",
"Failed to import the certificate" : "Importare del certificato non riuscita",
"S/MIME certificates" : "Certificati S/MIME",
"Certificate name" : "Nome del certificato",
@@ -639,13 +857,24 @@ OC.L10N.register(
"The private key is only required if you intend to send signed and encrypted emails using this certificate." : "La chiave privata è necessaria solo se si intende inviare email firmate e cifrate utilizzando questo certificato.",
"Submit" : "Invia",
"No text blocks available" : "Nessun blocco di testo disponibile",
+ "Text block deleted" : "Blocco di testo cancellato",
+ "Failed to delete text block" : "Cancellazione testo di blocco fallita",
+ "Text block shared with {sharee}" : "Blocco di testo condiviso con {sharee}",
+ "Failed to share text block with {sharee}" : "Non è stato possibile condividere il blocco di testo con {sharee}",
+ "Share deleted for {name}" : "Condivisione rimossa per {name}",
+ "Failed to delete share with {name}" : "Non è stato possibile rimuovere la condivisione con {name}",
"Guest" : "Ospite",
"Group" : "Gruppo",
+ "Failed to save text block" : "Salvataggio testo di blocco fallito",
"Shared" : "Condiviso",
"Edit {title}" : "Modifica {title}",
"Delete {title}" : "Elimina {title}",
+ "Edit text block" : "Modifica blocco di testo",
"Shares" : "Condivisioni",
+ "Search for users or groups" : "Cerca utenti o gruppi",
+ "Choose a text block to insert at the cursor" : "Scegli un blocco di testo da inserire nel punto selezionato",
"Insert" : "Inserisci",
+ "Insert text block" : "Inserisci testo di blocco",
"Account connected" : "Account connesso",
"You can close this window" : "Puoi chiudere questa finestra",
"Connect your mail account" : "Connetti il tuo account di posta",
@@ -667,15 +896,22 @@ OC.L10N.register(
"Discard changes" : "Scarta le modifiche",
"Discard unsaved changes" : "Scartare le modifiche non salvate",
"Keep editing message" : "Continua a modificare il messaggio",
+ "(All or part of this reply was generated by AI)" : "(Questa risposta è stata generata interamente o parzialmente dall'IA)",
"Attachments were not copied. Please add them manually." : "Gli allegati non sono stati copiati. Aggiungili manualmente.",
+ "Could not create snooze mailbox" : "Non è stato possibile creare la cartella per i messaggi posticipati",
+ "Sorry, the message could not be loaded. The draft may no longer exist. Please refresh the page and try again." : "Non è stato possibile caricare il messaggio. La bozza potrebbe non esistere più. Aggiorna la pagina e riprova.",
+ "Sending message…" : "Invio del messaggio in corso...",
"Message sent" : "Messaggio inviato",
"Could not send message" : "Impossibile inviare il messaggio",
+ "Message copied to \"Sent\" folder" : "Messaggio copiato nella cartella “Posta inviata”",
+ "Could not copy message to \"Sent\" folder" : "Non è possibile copiare messaggi nella cartella \"Posta inviata\"",
"Could not load {tag}{name}{endtag}" : "Impossibile caricare {tag}{name}{endtag}",
"There was a problem loading {tag}{name}{endtag}" : "Si è verificato un programma durante il caricamento di {tag}{name}{endtag}",
"Could not load your message" : "Impossibile caricare il tuo messaggio",
"Could not load the desired message" : "Impossibile caricare messaggio desiderato",
"Could not load the message" : "Impossibile caricare il messaggio",
"Error loading message" : "Errore durante il caricamento del messaggio",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "I messaggi saranno automaticamente contrassegnati come importanti in base ai messaggi con cui hai interagito o contrassegnati come importanti. All'inizio potresti dover cambiare manualmente l'importanza per addestrare il sistema, ma migliorerà nel tempo."
+ "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "I messaggi saranno automaticamente contrassegnati come importanti in base ai messaggi con cui hai interagito o contrassegnati come importanti. All'inizio potresti dover cambiare manualmente l'importanza per addestrare il sistema, ma migliorerà nel tempo.",
+ "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Qui verranno mostrati i messaggi che hai inviato e che richiedono una risposta, ma che non ne hanno ricevuta una dopo alcuni giorni."
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/l10n/it.json b/l10n/it.json
index bd275310c6..f6928a3500 100644
--- a/l10n/it.json
+++ b/l10n/it.json
@@ -104,9 +104,9 @@
"The folders to use for drafts, sent messages, deleted messages, archived messages and junk messages." : "Le cartelle da usare per bozze, messaggi inviati, messaggi archiviati e posta indesiderata.",
"Automatic trash deletion" : "Eliminazione automatica del cestino",
"Days after which messages in Trash will automatically be deleted:" : "Giorni dopo i quali i messaggi nel cestino verranno eliminati automaticamente:",
- "Autoresponder" : "Risponditore automatico",
+ "Autoresponder" : "Risposta automatica",
"Automated reply to incoming messages. If someone sends you several messages, this automated reply will be sent at most once every 4 days." : "Risposta automatica ai messaggi in arrivo. Se qualcuno ti invia più messaggi, questa risposta automatica verrà inviata al massimo una volta ogni 4 giorni.",
- "The autoresponder uses Sieve, a scripting language supported by many email providers. If you're unsure whether yours does, check with your provider. If Sieve is available, click the button to go to the settings and enable it." : "Il risponditore automatico utilizza Sieve, un linguaggio di scripting supportato da molti provider di posta elettronica. Se non sei sicuro che il tuo lo supporti, verifica con il tuo provider. Se Sieve è disponibile, fai clic sul pulsante per accedere alle impostazioni e abilitarlo.",
+ "The autoresponder uses Sieve, a scripting language supported by many email providers. If you're unsure whether yours does, check with your provider. If Sieve is available, click the button to go to the settings and enable it." : "La risposta automatica utilizza Sieve, un linguaggio di scripting supportato da molti provider di posta elettronica. Se non sei sicuro che il tuo lo supporti, verifica con il tuo provider. Se Sieve è disponibile, fai clic sul pulsante per accedere alle impostazioni e abilitarlo.",
"Go to Sieve settings" : "Vai alle impostazioni Sieve",
"Calendar settings" : "Impostazioni Calendario",
"Classification settings" : "Impostazioni di classificazione",
@@ -128,6 +128,7 @@
"Cancel" : "Annulla",
"Search the body of messages in priority Inbox" : "Cerca nel corpo dei messaggi nella posta prioritaria",
"Activate" : "Attiva",
+ "Make mails available to Context Chat" : "Rendi le email disponibili per Context Chat",
"Remind about messages that require a reply but received none" : "Promemoria per i messaggi che richiedono una risposta ma non hanno ricevuto alcun riscontro",
"Highlight external addresses" : "Evidenzia indirizzi esterni",
"Could not update preference" : "Impossibile aggiornare la preferenza",
@@ -172,6 +173,7 @@
"Step 2" : "Passo 2",
"Enable for the current domain" : "Abilita per il dominio corrente",
"Assistance features" : "Funzionalità di assistenza",
+ "Context Chat integration" : "Integrazione con Context Chat",
"Compose new message" : "Componi nuovo messaggio",
"Newer message" : "Messaggio più recente",
"Older message" : "Messaggio più datato",
@@ -203,16 +205,23 @@
"Encrypt with Mailvelope and send" : "Cifra con Mailvelope e invia",
"Send later" : "Invia più tardi",
"Message {id} could not be found" : "Il messaggio {id} non può essere trovato",
+ "Sign or Encrypt with S/MIME was selected, but we don't have a certificate for the selected alias. The message will not be signed or encrypted." : "Hai selezionato la firma o la cifratura con S/MIME, ma non è disponibile alcun certificato per l’alias scelto. Il messaggio non verrà firmato né cifrato.",
+ "Any existing formatting (for example bold, italic, underline or inline images) will be removed." : "La formattazione esistente (ad esempio grassetto, corsivo, sottolineato o immagini incorporate) verrà rimossa.",
+ "Turn off formatting" : "Disattiva formattazione",
+ "Turn off and remove formatting" : "Disattiva e rimuovi la formattazione",
"Keep formatting" : "Mantieni la formattazione",
"From" : "Da",
"Select account" : "Seleziona account",
"To" : "A",
"Cc/Bcc" : "Cc/Ccn",
+ "Select recipient" : "Seleziona destinatario",
+ "Contact or email address …" : "Contatto o indirizzo email …",
"Cc" : "Cc",
"Bcc" : "Ccn",
"Subject" : "Oggetto",
"Subject …" : "Oggetto...",
"This message came from a noreply address so your reply will probably not be read." : "Nota che il messaggio è arrivato da un indirizzo noreply, perciò la tua risposta non sarà probabilmente letta.",
+ "The following recipients do not have a S/MIME certificate: {recipients}." : "I seguenti destinatari non hanno un certificato S/MIME: {recipients}.",
"The following recipients do not have a PGP key: {recipients}." : "I seguenti destinatari non hanno una chiave PGP: {recipients}.",
"Write message …" : "Scrivi messaggio...",
"Saving draft …" : "Salvataggio bozza…",
@@ -224,6 +233,7 @@
"Disable formatting" : "Disabilita la formattazione",
"Upload attachment" : "Carica allegato",
"Add attachment from Files" : "Aggiungi allegato da File",
+ "Add share link from Files" : "Aggiungi link condiviso da Files",
"Smart picker" : "Selettore intelligente",
"Request a read receipt" : "Richiedi una conferma di lettura",
"Sign message with S/MIME" : "Firma il messaggio con S/MIME",
@@ -244,7 +254,24 @@
"Expand composer" : "Espandi compositore",
"Close composer" : "Chiudi compositore",
"Confirm" : "Conferma",
+ "Delegate access" : "Accesso delegato",
"Revoke" : "Revoca",
+ "{userId} will no longer be able to act on your behalf" : "{userId} non potrà più agire per tuo conto",
+ "Could not fetch delegates" : "Non è stato possibile recuperare i delegati",
+ "Delegated access to {userId}" : "Accesso delegato a {userId}",
+ "Could not delegate access" : "Non è stato possibile delegare l’accesso",
+ "Revoked access for {userId}" : "Revoca l'accesso a {userId}",
+ "Could not revoke delegation" : "Non è possibile revocare la delega",
+ "Delegation" : "Delega",
+ "Allow users to send, receive, and delete mail on your behalf" : "Consenti agli utenti delegati di inviare, ricevere ed eliminare email per tuo conto",
+ "Revoke access" : "Revoca l'accesso",
+ "Add delegate" : "Aggiungi delegato",
+ "Select a user" : "Seleziona un utente",
+ "They will be able to send, receive, and delete mail on your behalf" : "Potranno inviare, ricevere ed eliminare email per tuo conto",
+ "Revoke access?" : "Revocare l'accesso?",
+ "Tag: {name} deleted" : "Etichetta: {name} eliminata",
+ "An error occurred, unable to delete the tag." : "Si è verificato un errore: non è stato possibile eliminare l’etichetta.",
+ "The tag will be deleted from all messages." : "L’etichetta verrà rimossa da tutti i messaggi.",
"Plain text" : "Testo semplice",
"Rich text" : "Testo formattato",
"No messages in this folder" : "Nessun messaggio in questa cartella",
@@ -260,9 +287,18 @@
"Set reminder for this weekend" : "Imposta promemoria per questo fine settimana",
"Next week – {timeLocale}" : "Prossima settimana – {timeLocale}",
"Set reminder for next week" : "Imposta promemoria per la prossima settimana",
+ "Could not apply tag, configured tag not found" : "Non è stato possibile applicare l’etichetta: l’etichetta configurata non è stata trovata",
+ "Could not move thread, destination mailbox not found" : "Non è stato possibile spostare la conversazione: la cartella di destinazione non è stata trovata",
+ "Could not execute quick action" : "Non è stato possibile eseguire l’azione rapida",
"Quick action executed" : "Azione rapida eseguita",
+ "No trash folder configured" : "Nessuna cartella Cestino configurata",
"Could not delete message" : "Impossibile eliminare il messaggio",
"Could not archive message" : "Impossibile archiviare il messaggio",
+ "Thread was snoozed" : "Conversazione posticipata",
+ "Could not snooze thread" : "Non è possibile posticipare la conversazione",
+ "Thread was unsnoozed" : "Posicipo della conversazione annullato",
+ "Could not unsnooze thread" : "Non è stato possibile annullare il posticipo della conversazione",
+ "This summary was AI generated" : "Questo riepilogo è stato generato tramite IA",
"Encrypted message" : "Messaggio cifrato",
"This message is unread" : "Questo messaggio è non letto",
"Unfavorite" : "Rimuovi preferito",
@@ -273,6 +309,8 @@
"Mark not spam" : "Marca come posta non indesiderata",
"Mark as spam" : "Marca come posta indesiderata",
"Edit tags" : "Modifica etichette",
+ "Snooze" : "Posticipa",
+ "Unsnooze" : "Annulla posticipo",
"Move thread" : "Sposta conversazione",
"Move Message" : "Sposta messaggio",
"Archive thread" : "Archivia la discussione",
@@ -281,7 +319,9 @@
"Delete message" : "Elimina messaggio",
"More actions" : "Altre azioni",
"Back" : "Indietro",
+ "Set custom snooze" : "Imposta posticipo personalizzato",
"Edit as new message" : "Modifica come nuovo messaggio",
+ "Reply with meeting" : "Rispondi proponendo una riunione",
"Create task" : "Crea attività",
"Download message" : "Scarica messaggio",
"Back to all actions" : "Torna a tutte le azioni",
@@ -294,16 +334,22 @@
"_Unfavorite {number}_::_Unfavorite {number}_" : ["Rimuovi dai preferiti {number}","Rimuovi dai preferiti {number}","Rimuovi dai preferiti {number}"],
"_Favorite {number}_::_Favorite {number}_" : ["Aggiungi ai preferiti {number}","Aggiungi ai preferiti {number}","Aggiungi ai preferiti {number}"],
"_Unselect {number}_::_Unselect {number}_" : ["Deseleziona {number}","Deseleziona {number}","Deseleziona {number}"],
+ "_Mark {number} as spam_::_Mark {number} as spam_" : ["Segna {number} come spam","Segna {number} come spam","Segna {number} come spam"],
+ "_Mark {number} as not spam_::_Mark {number} as not spam_" : ["Segna {number} come non spam","Segna {number} come non spam","Segna {number} come non spam"],
+ "_Edit tags for {number}_::_Edit tags for {number}_" : ["Modifica etichetta per {number}","Modifica etichette per {number}","Modifica etichette per {number}"],
"_Move {number} thread_::_Move {number} threads_" : ["Sposta {number} conversazione","Sposta {number} conversazioni","Sposta {number} conversazioni"],
"_Forward {number} as attachment_::_Forward {number} as attachment_" : ["Inoltra {number} come allegato","Inoltra {number} come allegati","Inoltra {number} come allegati"],
"Mark as unread" : "Segna come non letto",
"Mark as read" : "Segna come letto",
+ "Mark as unimportant" : "Segna come non importante",
+ "Mark as important" : "Segna come importante",
"Report this bug" : "Segnala questo bug",
"Event created" : "Evento creato",
"Could not create event" : "Impossibile creare l'evento",
"Create event" : "Crea evento",
"All day" : "Tutto il giorno",
"Attendees" : "Partecipanti",
+ "You can only invite attendees if your account has an email address set" : "Puoi invitare partecipanti solo se il tuo account ha un indirizzo email configurato",
"Select calendar" : "Seleziona calendario",
"Description" : "Descrizione",
"Create" : "Crea",
@@ -326,43 +372,79 @@
"Decline" : "Rifiuta",
"Tentatively accept" : "Accetta provvisoriamente",
"More options" : "Altre opzioni",
+ "This message has an attached invitation but the invitation dates are in the past" : "Questo messaggio contiene un invito, ma le date dell’invito sono già passate.",
+ "This message has an attached invitation but the invitation does not contain a participant that matches any configured mail account address" : "Questo messaggio contiene un invito, ma nell’invito non è presente alcun partecipante associato agli indirizzi email configurati.",
+ "Could not remove internal address {sender}" : "Non è stato possibile rimuovere l’indirizzo interno {sender}",
+ "Could not add internal address {address}" : "Non è stato possibile aggiungere l’indirizzo interno {address}",
"individual" : "individuale",
"domain" : "dominio",
"Remove" : "Rimuovi",
"Add internal address" : "Aggiungi indirizzo interno",
+ "Add internal email or domain" : "Aggiungi indirizzo email o dominio interno",
"Itinerary for {type} is not supported yet" : "L'itinerario per {type} non è ancora supportato",
+ "To archive a message please configure an archive folder in account settings" : "Per archiviare un messaggio, configura prima una cartella Archivio nelle impostazioni dell’account",
"You are not allowed to move this message to the archive folder and/or delete this message from the current folder" : "Non ti è consentito spostare questo messaggio nella cartella degli archivi e/o eliminare questo messaggio dalla cartella corrente.",
+ "Your IMAP server does not support storing the seen/unseen state." : "Il server IMAP non supporta il salvataggio dello stato letto/non letto.",
+ "Could not mark message as seen/unseen" : "Non è stato possibile segnare il messaggio come letto/non letto",
"Last hour" : "Ultima ora",
"Today" : "Oggi",
"Yesterday" : "Ieri",
"Last week" : "Ultima settimana",
"Last month" : "Ultimo mese",
+ "Could not open folder" : "Non è possibile aprire la cartella",
+ "Loading messages …" : "Caricamento messaggi in corso …",
+ "Indexing your messages. This can take a bit longer for larger folders." : "Indicizzazione dei messaggi in corso. Per le cartelle più grandi l’operazione potrebbe richiedere più tempo.",
"Choose target folder" : "Scegli la cartella di destinazione",
"No more submailboxes in here" : "Qui non ci sono altre sotto-caselle di posta",
+ "Messages will automatically be marked as important using AI. The system learns from which messages you interact with or mark as important. In the beginning you might have to manually change the importance to teach it, but it will improve over time" : "I messaggi verranno contrassegnati automaticamente come importanti tramite l’IA. Il sistema impara dai messaggi con cui interagisci o che segni come importanti. All’inizio potresti dover modificare manualmente il livello di importanza per addestrarlo, ma la precisione migliorerà nel tempo.",
+ "Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "I messaggi che hai aggiunto ai preferiti verranno mostrati in cima alle cartelle. Puoi disattivare questa opzione dalle impostazioni di Posta.",
+ "AI identifies messages sent by you that likely require a reply but did not receive one after a couple of days and shows them here" : "L’IA identifica i messaggi inviati da te che probabilmente richiedono una risposta ma che non ne hanno ricevuta dopo alcuni giorni, e li mostra qui.",
"Favorites" : "Preferiti",
+ "Favorites info" : "Informazioni sui preferiti",
+ "Load more favorites" : "Carica altri preferiti",
+ "Follow up" : "Follow-up",
+ "Follow up info" : "Informazioni sui follow-up",
+ "Load more follow ups" : "Carica altri follow-up",
"Important info" : "Informazione importante",
+ "Load more important messages" : "Carica altri messaggi importanti",
"Other" : "Altro",
+ "Load more other messages" : "Carica altri messaggi",
"Could not send mdn" : "Impossibile inviare mdn",
"The sender of this message has asked to be notified when you read this message." : "Il mittente di questo messaggio ha chiesto di essere avvisato quando leggi questo messaggio.",
"Notify the sender" : "Notifica al mittente",
"You sent a read confirmation to the sender of this message." : "Hai inviato una conferma di lettura al mittente di questo messaggio.",
+ "Message was snoozed" : "Messaggio posticipato",
+ "Could not snooze message" : "Non è possibile posticipare il messaggio",
+ "Message was unsnoozed" : "Posticipo del messaggio annullato",
+ "Could not unsnooze message" : "Non è stato possibile annullare il posticipo del messaggio",
"Forward" : "Inoltra",
"Move message" : "Sposta messaggio",
"Translate" : "Traduci",
+ "Forward message as attachment" : "Inoltra il messaggio come allegato",
"View source" : "Visualizza sorgente",
"Print message" : "Stampa messaggio",
+ "Create mail filter" : "Crea filtro email",
"Download thread data for debugging" : "Scarica i dati del conversazione per il debug",
+ "Suggested replies are using AI" : "Le risposte suggerite sono generate tramite IA",
"Message body" : "Corpo del messaggio",
+ "Warning: The S/MIME signature of this message is unverified. The sender might be impersonating someone!" : "Attenzione: la firma S/MIME di questo messaggio non è verificata. Il mittente potrebbe non essere chi dichiara di essere.",
+ "AI info" : "IA informazioni",
"Unnamed" : "Senza nome",
"Embedded message" : "Messaggio incorporato",
+ "Attachment saved to Files" : "Allegato salvato in Files",
+ "Attachment could not be saved" : "L'allegato non può essere salvato",
"calendar imported" : "calendario importato",
"Choose a folder to store the attachment in" : "Scegli una cartella dove salvare l'allegato",
"Import into calendar" : "Importa nel calendario",
"Download attachment" : "Scarica allegato",
"Save to Files" : "Salva in File",
+ "Attachments saved to Files" : "Allegati salvati in Files",
+ "Error while saving attachments" : "Errore durante il salvataggio degli allegati",
+ "View fewer attachments" : "Mostra meno allegati",
"Choose a folder to store the attachments in" : "Scegli una cartella in cui salvare gli allegati",
"Save all to Files" : "Salva tutto in File",
"Download Zip" : "Scarica Zip",
+ "_View {count} more attachment_::_View {count} more attachments_" : ["Mostra altri {count} allegati","Mostra altri {count} allegati","Mostra altri {count} allegati"],
"This message is encrypted with PGP. Install Mailvelope to decrypt it." : "Questo messaggio è cifrato con PGP. Installa Mailvelope per decifrarlo.",
"The images have been blocked to protect your privacy." : "Le immagini sono state bloccate per proteggere la tua riservatezza.",
"Show images" : "Mostra le immagini",
@@ -375,11 +457,18 @@
"Moving" : "Spostamento",
"Moving thread" : "Spostamento conversazione",
"Moving message" : "Spostamento messaggio",
+ "This account cannot connect" : "Questo account non riesce a connettersi",
+ "Connection failed. Please verify your information and try again" : "Connessione non riuscita. Verifica i dati inseriti e riprova.",
"Used quota: {quota}% ({limit})" : "Spazio utilizzato: {quota} % ({limit})",
"Used quota: {quota}%" : "Spazio utilizzato: {quota}%",
+ "Unable to create mailbox. The name likely contains invalid characters. Please try another name." : "Non è stato possibile creare la cartella. Il nome contiene probabilmente caratteri non validi. Prova a usare un altro nome.",
"Remove account" : "Rimuovi account",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "L'account per {email} e i dati di posta elettronica memorizzati nella cache saranno rimossi da Nextcloud, ma non dal tuo fornitore di posta elettronica.",
"Remove {email}" : "Rimuovi {email}",
+ "could not delete account" : "Non è stato possibile eliminare l’account",
+ "Provisioned account is disabled" : "L’account configurato automaticamente è disattivato",
+ "Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Accedi con password per abilitare questo account. La sessione corrente usa un accesso senza password, ad esempio SSO o WebAuthn.",
+ "Delegate account" : "Account delegato",
"Show only subscribed folders" : "Mostra solo le cartelle sottoscritte",
"Add folder" : "Aggiungi cartella",
"Folder name" : "Nome della cartella",
@@ -392,19 +481,26 @@
"_{total} message_::_{total} messages_" : ["{total} messaggio","{total} messaggi","{total} messaggi"],
"_{unread} unread of {total}_::_{unread} unread of {total}_" : ["{unread} non letto di {total}","{unread} non letti di {total}","{unread} non letti di {total}"],
"Loading …" : "Caricamento in corso...",
+ "All messages in mailbox will be deleted." : "Tutti i messaggi presenti nella cartella verranno eliminati.",
+ "Clear mailbox {name}" : "Svuota cartella {name}",
+ "Clear folder" : "Svuota cartella",
"The folder and all messages in it will be deleted." : "La cartella e tutti i messaggi in essa saranno eliminati.",
"Delete folder" : "Elimina cartella",
"Delete folder {name}" : "Elimina cartella {name}",
"An error occurred, unable to rename the mailbox." : "Si è verificato un errore, impossibile rinominare la casella di posta.",
+ "Please wait 10 minutes before repairing again" : "Attendi 10 minuti prima di ripetere la riparazione",
"Mark all as read" : "Marca tutti come letti",
"Add subfolder" : "Aggiungi sottocartella",
"Rename" : "Rinomina",
"Move folder" : "Sposta cartella",
+ "Repair folder" : "Ripara cartella",
"Clear cache" : "Svuota cache",
"Clear locally cached data, in case there are issues with synchronization." : "Cancella i dati locali in cache, nel caso ci siano problemi di sincronizzazione.",
"Subscribed" : "Sottoscritta",
"Sync in background" : "Sincronizza in background",
+ "Delete all messages" : "Elimina tutti i messaggi",
"Outbox" : "Posta in uscita",
+ "Translate this message to {language}" : "Traduci questo messaggio in {language}",
"New message" : "Nuovo messaggio",
"Edit message" : "Modifica messaggio",
"Draft" : "Bozza",
@@ -414,36 +510,59 @@
"Failed to save draft" : "Impossibile salvare la bozza",
"attachment" : "allegato",
"attached" : "allegato",
+ "No \"sent\" folder configured. Please pick one in the account settings." : "Nessuna cartella “Posta inviata” configurata. Selezionane una nelle impostazioni dell’account.",
"You are trying to send to many recipients in To and/or Cc. Consider using Bcc to hide recipient addresses." : "Stai tentando di inviare a troppi destinatari in A e/o CC. Considera l'idea di utilizzare CCN per nascondere gli indirizzi dei destinatari.",
"Your message has no subject. Do you want to send it anyway?" : "Il tuo messaggio non ha oggetto. Vuoi inviarlo comunque?",
"You mentioned an attachment. Did you forget to add it?" : "Hai menzionato un allegato. Hai dimenticato di aggiungerlo?",
"Message discarded" : "Messaggio scartato",
"Could not discard message" : "Impossibile eliminare il messaggio",
+ "Maximize composer" : "Espandi finestra",
+ "Show recipient details" : "Mostra dettagli dei destinatari",
+ "Hide recipient details" : "Nascondi dettagli dei destinatari",
+ "Minimize composer" : "Riduci finestra",
"Error sending your message" : "Errore di invio del messaggio",
"Retry" : "Riprova",
"Warning sending your message" : "Avviso durante l'invio del tuo messaggio",
"Send anyway" : "Invia comunque",
- "Autoresponder off" : "Risponditore automatico spento",
- "Autoresponder on" : "Risponditore automatico attivo",
+ "Welcome to {productName} Mail" : "Benvenuto in {productName} Mail",
+ "Start writing a message by clicking below or select an existing message to display its contents" : "Inizia a scrivere un messaggio cliccando qui sotto oppure seleziona un messaggio esistente per visualizzarne il contenuto",
+ "Autoresponder off" : "Risposta automatica disattivata",
+ "Autoresponder on" : "Risposta automatica attiva",
+ "Autoresponder follows system settings" : "La risposta automatica segue le impostazioni di sistema",
+ "The autoresponder follows your personal absence period settings." : "La risposta automatica segue le impostazioni del tuo periodo di assenza.",
+ "Edit absence settings" : "Modifica impostazioni di assenza",
"First day" : "Primo giorno",
"Last day (optional)" : "Ultimo giorno (facoltativo)",
+ "${subject} will be replaced with the subject of the message you are responding to" : "${subject} verrà sostituito con l’oggetto del messaggio a cui stai rispondendo",
"Message" : "Messaggio",
"Oh Snap!" : "Accidenti!",
- "Save autoresponder" : "Salva risponditore automatico",
+ "Save autoresponder" : "Salva risposta automatica",
"Could not open outbox" : "Impossibile aprire la posta in uscita",
+ "Pending or not sent messages will show up here" : "Qui verranno mostrati i messaggi in sospeso o non ancora inviati",
+ "Could not copy to \"Sent\" folder" : "Non è possibile copiare nella cartella \"Posta inviata\"",
+ "Mail server error" : "Errore del server di posta",
"Message could not be sent" : "Il messaggio non può essere inviato",
"Message deleted" : "Messaggio eliminato",
+ "Copy to \"Sent\" Folder" : "Copia nella cartella \"Posta inviata\"",
+ "Copy to Sent Folder" : "Copia nella cartella Posta inviata",
+ "Phishing email" : "Email di phishing",
+ "This email might be a phishing attempt" : "Questa email potrebbe essere un tentativo di phishing",
+ "Hide suspicious links" : "Nascondi link sospetti",
+ "Show suspicious links" : "Mostra link sospetti",
+ "link text" : "testo del link",
"Copied email address to clipboard" : "Indirizzo email copiato negli appunti",
"Could not copy email address to clipboard" : "Impossibile copiare l'indirizzo email negli appunti",
"Contacts with this address" : "Contatti con questo indirizzo",
"Add to Contact" : "Aggiungi ai contatti",
"New Contact" : "Nuovo contatto",
"Copy to clipboard" : "Copia negli appunti",
+ "Contact name …" : "Nome contatto …",
"Add" : "Aggiungi",
"Show less" : "Mostra meno",
"Show more" : "Mostra più",
"Clear" : "Pulisci",
"Search in folder" : "Cerca nella cartella",
+ "Open search modal" : "Apri finestra di ricerca",
"Close" : "Chiudi",
"Search parameters" : "Parametri di ricerca",
"Search subject" : "Cerca nell'oggetto",
@@ -458,9 +577,13 @@
"Select BCC recipients" : "Seleziona i destinatari CCN",
"Tags" : "Etichette",
"Select tags" : "Seleziona etichette",
+ "Marked as" : "Contrassegnato come",
"Has attachments" : "Ha allegati",
+ "Mentions me" : "Mi menziona",
+ "Has attachment" : "Con allegato",
+ "To me" : "A me",
"Enable mail body search" : "Abilita ricerca nel corpo del messaggio",
- "Sieve is a powerful language for writing filters for your mailbox. You can manage the sieve scripts in Mail if your email service supports it. Sieve is also required to use Autoresponder and Filters." : "Sieve è un potente linguaggio per la creazione di filtri per la tua casella di posta. Puoi gestire gli script Sieve nell’app Posta se il tuo servizio email lo supporta. Sieve è inoltre necessario per utilizzare il risponditore automatico e i filtri.",
+ "Sieve is a powerful language for writing filters for your mailbox. You can manage the sieve scripts in Mail if your email service supports it. Sieve is also required to use Autoresponder and Filters." : "Sieve è un potente linguaggio per la creazione di filtri per la tua casella di posta. Puoi gestire gli script Sieve nell’app Posta se il tuo servizio email lo supporta. Sieve è inoltre necessario per utilizzare le risposte automatiche e i filtri.",
"Enable sieve filter" : "Abilita filtri Sieve",
"Sieve host" : "Host Sieve",
"Sieve security" : "Sicurezza Sieve",
@@ -470,33 +593,67 @@
"Custom" : "Personalizzato",
"Sieve User" : "Utente Sieve",
"Sieve Password" : "Password Sieve",
+ "Oh snap!" : "Ops!",
"Save sieve settings" : "Salva impostazione Sieve",
+ "The syntax seems to be incorrect:" : "La sintassi non sembra corretta:",
"Save sieve script" : "Salva script Sieve",
"Signature …" : "Scrivi firma …",
+ "Your signature is larger than 2 MB. This may affect the performance of your editor." : "La firma supera i 2 MB e potrebbe rallentare l’editor.",
"Save signature" : "Salva firma",
"Place signature above quoted text" : "Posiziona la firma sopra il testo citato",
"Message source" : "Sorgente del messaggio",
"An error occurred, unable to rename the tag." : "Si è verificato un errore, impossibile rinominare l'etichetta.",
"Edit name or color" : "Modifica nome o colore",
+ "Saving new tag name …" : "Salvataggio del nuovo nome dell’etichetta in corso …",
"Delete tag" : "Elimina etichetta",
+ "Set tag" : "Assegna etichetta",
+ "Unset tag" : "Rimuovi etichetta",
+ "Tag name is a hidden system tag" : "Questo nome è riservato a un’etichetta di sistema nascosta",
"Tag already exists" : "L'etichetta esiste già",
+ "Tag name cannot be empty" : "Il nome dell’etichetta non può essere vuoto",
"An error occurred, unable to create the tag." : "Si è verificato un errore, impossibile creare l'etichetta.",
"Add default tags" : "Aggiungi etichette predefiniti",
"Add tag" : "Aggiungi etichetta",
+ "Saving tag …" : "Salvataggio etichetta in corso …",
"Task created" : "Attività creata",
"Could not create task" : "Impossibile creare l'attività",
+ "No calendars with task list support" : "Nessun calendario supporta le liste di attività",
+ "Summarizing thread failed." : "Non è stato possibile generare il riepilogo della conversazione.",
"Could not load your message thread" : "Impossibile caricare la tua discussione",
+ "The thread doesn't exist or has been deleted" : "La conversazione non esiste oppure è stata eliminata",
+ "Email was not able to be opened" : "Non è stato possibile aprire l’email",
"Print" : "Stampa",
"Could not print message" : "Impossibile stampare il messaggio",
+ "Loading thread" : "Caricamento conversazione in corso",
"Not found" : "Non trovato",
"Encrypted & verified " : "Cifrato e verificato",
"Signature verified" : "Firma verificata",
"Signature unverified " : "Firma non verificata",
"This message was encrypted by the sender before it was sent." : "Questo messaggio è stato cifrato dal mittente prima di essere inviato.",
+ "This message contains a verified digital S/MIME signature. The message wasn't changed since it was sent." : "Questo messaggio contiene una firma digitale S/MIME verificata. Il messaggio non è stato modificato dopo l’invio.",
+ "This message contains an unverified digital S/MIME signature. The message might have been changed since it was sent or the certificate of the signer is untrusted." : "Questo messaggio contiene una firma digitale S/MIME non verificata. Il messaggio potrebbe essere stato modificato dopo l’invio oppure il certificato del firmatario potrebbe non essere attendibile.",
"Reply all" : "Rispondi a tutti",
+ "Unsubscribe request sent" : "Richiesta di disiscrizione inviata",
+ "Could not unsubscribe from mailing list" : "Non è stato possibile disiscriversi dalla mailing list",
+ "Please wait for the message to load" : "Attendi il caricamento del messaggio",
+ "Disable reminder" : "Disattiva promemoria",
"Unsubscribe" : "Rimuovi sottoscrizione",
"Reply to sender only" : "Rispondi solo al mittente",
+ "Mark as unfavorite" : "Rimuovi dai preferiti",
+ "Mark as favorite" : "Aggiungi ai preferiti",
+ "To:" : "A: ",
+ "Cc:" : "Cc:",
+ "Bcc:" : "Bcc:",
+ "Unsubscribe via link" : "Disiscriviti tramite link",
+ "Unsubscribing will stop all messages from the mailing list {sender}" : "Disiscrivendoti non riceverai più messaggi da questa mailing list {sender}",
+ "Send unsubscribe email" : "Invia email di disiscrizione",
+ "Unsubscribe via email" : "Disiscriviti tramite email",
+ "{name} Assistant" : "{name} Assistente",
+ "Thread summary" : "Riepilogo della conversazione",
"Go to latest message" : "Vai all'ultimo messaggio",
+ "Newest message" : "Messaggio più recente",
+ "This summary is AI generated and may contain mistakes." : "Questo riepilogo è stato generato tramite IA e potrebbe contenere imprecisioni.",
+ "Please select languages to translate to and from" : "Seleziona la lingua di partenza e quella di destinazione per la traduzione",
"The message could not be translated" : "Questo messaggio non può essere tradotto",
"Translation copied to clipboard" : "Traduzione copiata negli appunti",
"Translation could not be copied" : "La traduzione non può essere copiata",
@@ -506,6 +663,7 @@
"Target language to translate into" : "Lingua di destinazione in cui tradurre",
"Translate to" : "Traduci in",
"Translating" : "Traduco",
+ "This translation is generated using AI and may contain inaccuracies" : "Questa traduzione è stata generata con l’IA e potrebbe contenere imprecisioni",
"Copy translated text" : "Copia testo tradotto",
"Disable trash retention by leaving the field empty or setting it to 0. Only mails deleted after enabling trash retention will be processed." : "Disattiva la conservazione nel cestino lasciando il campo vuoto o impostandolo a 0. Verranno elaborati solo i messaggi eliminati dopo l’attivazione della conservazione.",
"Could not remove trusted sender {sender}" : "Impossibile rimuovere il mittente fidato {sender}",
@@ -520,15 +678,48 @@
"{trainNr} from {depStation} to {arrStation}" : "{trainNr} da {depStation} a {arrStation}",
"Train from {depStation} to {arrStation}" : "Treno da {depStation} a {arrStation}",
"Train" : "Treno",
+ "Mark message as" : "Contrassegna il messaggio come",
+ "Add flag" : "Aggiungi contrassegno",
"Move into folder" : "Sposta nella cartella",
"Stop" : "Ferma",
+ "Delete action" : "Elimina azione",
+ "Answered" : "Risposto",
"Deleted" : "Eliminato",
+ "Flagged" : "Contrassegnato",
+ "Seen" : "Letto",
+ "Enter flag" : "Inserisci contrassegno",
+ "Stop ends all processing" : "Interrompi: termina tutte le elaborazioni",
+ "Sender" : "Mittente",
"Recipient" : "Destinatario",
+ "Create a new mail filter" : "Crea un nuovo filtro email",
+ "Choose the headers you want to use to create your filter. In the next step, you will be able to refine the filter conditions and specify the actions to be taken on messages that match your criteria." : "Scegli le intestazioni da usare per creare il filtro. Nel passaggio successivo potrai definire meglio le condizioni e indicare quali azioni applicare ai messaggi che corrispondono ai criteri scelti.",
"Delete filter" : "Elimina filtro",
+ "Delete mail filter {filterName}?" : "Cancella filtro email {filterName}?",
+ "Are you sure to delete the mail filter?" : "Sei sicuro di cancellare il filtro email?",
+ "New filter" : "Nuovo filtro",
+ "Filter saved" : "Filtro salvato",
+ "Could not save filter" : "Impossibile salvare il filtro",
+ "Filter deleted" : "Filtro cancellato",
+ "Could not delete filter" : "Impossibile cancellare il filtro",
+ "Take control of your email chaos. Filters help you to prioritize what matters and eliminate clutter." : "Metti ordine nella tua posta. I filtri ti aiutano a dare priorità ai messaggi importanti e a ridurre il superfluo.",
+ "Hang tight while the filters load" : "Caricamento dei filtri in corso",
+ "Filter is active" : "Il filtro è attivo",
+ "Filter is not active" : "Il filtro non è attivo",
+ "If all the conditions are met, the actions will be performed" : "Se tutte le condizioni sono soddisfatte, verranno eseguite le azioni previste",
+ "If any of the conditions are met, the actions will be performed" : "Se almeno una delle condizioni è soddisfatta, verranno eseguite le azioni previste",
"Help" : "Assistenza",
"contains" : "contiene",
+ "A substring match. The field matches if the provided value is contained within it. For example, \"report\" would match \"port\"." : "Corrispondenza parziale. Il campo corrisponde se contiene il valore indicato. Ad esempio, “report” può corrispondere a “Business report 2024”.",
"matches" : "corrisponde",
+ "A pattern match using wildcards. The \"*\" symbol represents any number of characters (including none), while \"?\" represents exactly one character. For example, \"*report*\" would match \"Business report 2024\"." : "Corrispondenza tramite caratteri jolly. Il simbolo “*” rappresenta qualsiasi numero di caratteri (anche nessuno), mentre “?” rappresenta esattamente un carattere. Ad esempio, “*report*” può corrispondere a “Business report 2024”.",
+ "Enter subject" : "Inserisci oggetto",
+ "Enter sender" : "Inserisci mittente",
+ "Enter recipient" : "Inserisci destinatario",
+ "is exactly" : "è esattamente",
+ "Conditions" : "Condizioni",
+ "Add condition" : "Aggiungi condizione",
"Actions" : "Azioni",
+ "Add action" : "Aggiungi azione",
"Priority" : "Priorità",
"Enable filter" : "Abilita filtri",
"Tag" : "Etichetta",
@@ -536,11 +727,19 @@
"Edit quick action" : "Modifica azione rapida",
"Add quick action" : "Aggiungi azione rapida",
"Quick action deleted" : "Azione rapida eliminata",
+ "Failed to delete quick action" : "Non è stato possibile eliminare l’azione rapida",
+ "Failed to update quick action" : "Non è stato possibile aggiornare l’azione rapida",
+ "Failed to update step in quick action" : "Non è stato possibile aggiornare il passaggio dell’azione rapida",
"Quick action updated" : "Azione rapida aggiornata",
+ "Failed to create quick action" : "Non è stato possibile creare l’azione rapida",
+ "Failed to add steps to quick action" : "Non è stato possibile aggiungere passaggi all’azione rapida",
"Quick action created" : "Azione rapida creata",
+ "Failed to delete action step" : "Non è stato possibile eliminare il passaggio dell’azione",
"No quick actions yet." : "Nessuna azione rapida disponibile al momento.",
"Edit" : "Modifica",
"Quick action name" : "Azione rapida nome",
+ "Do the following actions" : "Esegui le seguenti azioni",
+ "Add another action" : "Aggiungi un’altra azione",
"Successfully updated config for \"{domain}\"" : "Configurazione aggiornata con successo per \"{domain}\"",
"Error saving config" : "Errore durante il salvataggio della configurazione",
"Saved config for \"{domain}\"" : "Configurazione salvata per \"{domain}\"",
@@ -549,6 +748,7 @@
"There was an error when provisioning accounts." : "Si è verificato un errore durante il approvvigionamento degli account.",
"Successfully deleted and deprovisioned accounts for \"{domain}\"" : " Account eliminati e approvvigionato correttamente per \"{domain}\"",
"Error when deleting and deprovisioning accounts for \"{domain}\"" : "Errore durante l'eliminazione e il approvvigionamento degli account per \"{domain}\"",
+ "Could not save default classification setting" : "Non è stato possibile salvare l’impostazione di classificazione predefinita",
"Mail app" : "Applicazione di posta",
"The mail app allows users to read mails on their IMAP accounts." : "L'applicazione di posta consente agli utenti di leggere i messaggi dei propri account IMAP.",
"Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Qui puoi trovare le impostazioni a livello di istanza. Le impostazioni specifiche dell'utente si trovano nell'applicazione stessa (angolo in basso a sinistra).",
@@ -564,11 +764,28 @@
"Provisioning Configurations" : "Configurazione di approvvigionamento",
"Add new config" : "Aggiungi nuova configurazione",
"Provision all accounts" : "Predisponi tutti gli account",
+ "Allow additional mail accounts" : "Consenti account email aggiuntivi",
+ "Allow additional Mail accounts from User Settings" : "Consenti account Mail aggiuntivi dalle impostazioni utente",
+ "Enable text processing through LLMs" : "Abilita elaborazione del testo tramite LLM",
+ "The Mail app can process user data with the help of the configured large language model and provide assistance features like thread summaries, smart replies and event agendas." : "L’app Mail può elaborare i dati dell’utente tramite il modello linguistico configurato e offrire funzionalità avanzate come riepiloghi delle conversazioni, risposte intelligenti e agenda degli eventi.",
+ "Enable LLM processing" : "Abilita elaborazione tramite LLM",
+ "Enable classification by importance by default" : "Abilita di default la classificazione per importanza",
+ "The Mail app can classify incoming emails by importance using machine learning. This feature is enabled by default but can be disabled by default here. Individual users will still be able to toggle the feature for their accounts." : "L’app Mail può classificare automaticamente le email in arrivo in base alla loro importanza tramite machine learning. La funzionalità è attiva per impostazione predefinita, ma può essere disattivata qui. I singoli utenti potranno comunque abilitarla o disabilitarla per il proprio account.",
+ "Enable classification of important mails by default" : "Abilita di default la classificazione delle email importanti",
"Anti Spam Service" : "Servizio anti-spam",
"You can set up an anti spam service email address here." : "È possibile impostare un indirizzo e-mail del servizio Anti-Spam qui.",
"Any email that is marked as spam will be sent to the anti spam service." : "Qualsiasi email contrassegnata come posta indesiderata verrà inviata al servizio anti-spam.",
"Gmail integration" : "Integrazione Gmail",
+ "Gmail allows users to access their email via IMAP. For security reasons this access is only possible with an OAuth 2.0 connection or Google accounts that use two-factor authentication and app passwords." : "Gmail consente l’accesso alle email tramite IMAP. Per motivi di sicurezza, questa modalità è disponibile solo tramite una connessione OAuth 2.0 oppure per gli account Google con autenticazione a due fattori e password per le app.",
+ "You have to register a new Client ID for a \"Web application\" in the Google Cloud console. Add the URL {url} as authorized redirect URI." : "Devi registrare un nuovo Client ID di tipo “Applicazione web” nella console Google Cloud. Aggiungi l’URL {url} come URI di reindirizzamento autorizzato.",
"Microsoft integration" : "Integrazione Microsoft",
+ "Microsoft requires you to access your emails via IMAP using OAuth 2.0 authentication. To do this, you need to register an app with Microsoft Entra ID, formerly known as Microsoft Azure Active Directory." : "Microsoft richiede l’accesso alle email tramite IMAP con autenticazione OAuth 2.0. Per configurarlo, devi registrare un’app in Microsoft Entra ID, in precedenza noto come Microsoft Azure Active Directory.",
+ "Redirect URI" : "URI di reindirizzamento",
+ "For more details, please click here to open our documentation." : "Per maggiori dettagli, fai clic qui per aprire la documentazione.",
+ "User Interface Preference Defaults" : "Preferenze predefinite dell’interfaccia utente",
+ "These settings are used to pre-configure the user interface preferences they can be overridden by the user in the mail settings" : "Queste impostazioni servono a preconfigurare le preferenze dell’interfaccia utente. L’utente potrà comunque modificarle dalle impostazioni di Posta.",
+ "Message View Mode" : "Modalità di visualizzazione dei messaggi",
+ "Show only the selected message" : "Mostra solo il messaggio selezionato",
"Successfully set up anti spam email addresses" : "Impostare correttamente gli indirizzi e-mail anti-spam",
"Error saving anti spam email addresses" : "Errore durante il salvataggio degli indirizzi email anti-spam",
"Successfully deleted anti spam reporting email" : "Email di segnalazione anti-spam eliminata con successo",
@@ -621,6 +838,7 @@
"The provided PKCS #12 certificate must contain at least one certificate and exactly one private key." : "Il certificato PKCS #12 fornito deve contenere almeno un certificato ed esattamente una chiave privata.",
"Failed to import the certificate. Please check the password." : "Impossibile importare il certificato. Controlla la password.",
"Certificate imported successfully" : "Certificato importato correttamente",
+ "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Non è stato possibile importare il certificato. Verifica che la chiave privata corrisponda al certificato e che non sia protetta da passphrase.",
"Failed to import the certificate" : "Importare del certificato non riuscita",
"S/MIME certificates" : "Certificati S/MIME",
"Certificate name" : "Nome del certificato",
@@ -637,13 +855,24 @@
"The private key is only required if you intend to send signed and encrypted emails using this certificate." : "La chiave privata è necessaria solo se si intende inviare email firmate e cifrate utilizzando questo certificato.",
"Submit" : "Invia",
"No text blocks available" : "Nessun blocco di testo disponibile",
+ "Text block deleted" : "Blocco di testo cancellato",
+ "Failed to delete text block" : "Cancellazione testo di blocco fallita",
+ "Text block shared with {sharee}" : "Blocco di testo condiviso con {sharee}",
+ "Failed to share text block with {sharee}" : "Non è stato possibile condividere il blocco di testo con {sharee}",
+ "Share deleted for {name}" : "Condivisione rimossa per {name}",
+ "Failed to delete share with {name}" : "Non è stato possibile rimuovere la condivisione con {name}",
"Guest" : "Ospite",
"Group" : "Gruppo",
+ "Failed to save text block" : "Salvataggio testo di blocco fallito",
"Shared" : "Condiviso",
"Edit {title}" : "Modifica {title}",
"Delete {title}" : "Elimina {title}",
+ "Edit text block" : "Modifica blocco di testo",
"Shares" : "Condivisioni",
+ "Search for users or groups" : "Cerca utenti o gruppi",
+ "Choose a text block to insert at the cursor" : "Scegli un blocco di testo da inserire nel punto selezionato",
"Insert" : "Inserisci",
+ "Insert text block" : "Inserisci testo di blocco",
"Account connected" : "Account connesso",
"You can close this window" : "Puoi chiudere questa finestra",
"Connect your mail account" : "Connetti il tuo account di posta",
@@ -665,15 +894,22 @@
"Discard changes" : "Scarta le modifiche",
"Discard unsaved changes" : "Scartare le modifiche non salvate",
"Keep editing message" : "Continua a modificare il messaggio",
+ "(All or part of this reply was generated by AI)" : "(Questa risposta è stata generata interamente o parzialmente dall'IA)",
"Attachments were not copied. Please add them manually." : "Gli allegati non sono stati copiati. Aggiungili manualmente.",
+ "Could not create snooze mailbox" : "Non è stato possibile creare la cartella per i messaggi posticipati",
+ "Sorry, the message could not be loaded. The draft may no longer exist. Please refresh the page and try again." : "Non è stato possibile caricare il messaggio. La bozza potrebbe non esistere più. Aggiorna la pagina e riprova.",
+ "Sending message…" : "Invio del messaggio in corso...",
"Message sent" : "Messaggio inviato",
"Could not send message" : "Impossibile inviare il messaggio",
+ "Message copied to \"Sent\" folder" : "Messaggio copiato nella cartella “Posta inviata”",
+ "Could not copy message to \"Sent\" folder" : "Non è possibile copiare messaggi nella cartella \"Posta inviata\"",
"Could not load {tag}{name}{endtag}" : "Impossibile caricare {tag}{name}{endtag}",
"There was a problem loading {tag}{name}{endtag}" : "Si è verificato un programma durante il caricamento di {tag}{name}{endtag}",
"Could not load your message" : "Impossibile caricare il tuo messaggio",
"Could not load the desired message" : "Impossibile caricare messaggio desiderato",
"Could not load the message" : "Impossibile caricare il messaggio",
"Error loading message" : "Errore durante il caricamento del messaggio",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "I messaggi saranno automaticamente contrassegnati come importanti in base ai messaggi con cui hai interagito o contrassegnati come importanti. All'inizio potresti dover cambiare manualmente l'importanza per addestrare il sistema, ma migliorerà nel tempo."
+ "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "I messaggi saranno automaticamente contrassegnati come importanti in base ai messaggi con cui hai interagito o contrassegnati come importanti. All'inizio potresti dover cambiare manualmente l'importanza per addestrare il sistema, ma migliorerà nel tempo.",
+ "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Qui verranno mostrati i messaggi che hai inviato e che richiedono una risposta, ma che non ne hanno ricevuta una dopo alcuni giorni."
},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}
\ No newline at end of file
diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js
index 471ed796f5..e0495d6924 100644
--- a/l10n/zh_TW.js
+++ b/l10n/zh_TW.js
@@ -137,6 +137,7 @@ OC.L10N.register(
"Mail settings" : "電子郵件設定",
"General" : "一般",
"Set as default mail app" : "設定為預設的郵件應用程式",
+ "{email} (delegated)" : "{email}(已委派)",
"Add mail account" : "新增郵件帳號",
"Appearance" : "外觀",
"Show all messages in thread" : "在討論串中顯示所有訊息",
@@ -255,7 +256,21 @@ OC.L10N.register(
"Expand composer" : "展開編輯器",
"Close composer" : "關閉編輯器",
"Confirm" : "確認",
+ "Delegate access" : "委派存取權",
"Revoke" : "撤銷",
+ "{userId} will no longer be able to act on your behalf" : "{userId} 將無法再代表您執行操作",
+ "Could not fetch delegates" : "無法擷取委派使用者",
+ "Delegated access to {userId}" : "已向 {userId} 委派存取權",
+ "Could not delegate access" : "無法委派存取權",
+ "Revoked access for {userId}" : "已撤銷對 {userId} 的存取",
+ "Could not revoke delegation" : "無法撤銷委派",
+ "Delegation" : "委派",
+ "Allow users to send, receive, and delete mail on your behalf" : "允許使用者代表您傳送、接收與刪除郵件",
+ "Revoke access" : "撤銷存取權",
+ "Add delegate" : "新增委派",
+ "Select a user" : "選取使用者",
+ "They will be able to send, receive, and delete mail on your behalf" : "他們將能代表您傳送、接收與刪除郵件",
+ "Revoke access?" : "撤銷存取權",
"Tag: {name} deleted" : "標籤:{name} 已刪除",
"An error occurred, unable to delete the tag." : "遇到錯誤,無法刪除標籤。",
"The tag will be deleted from all messages." : "該標籤將從所有訊息刪除。",
@@ -452,8 +467,10 @@ OC.L10N.register(
"Remove account" : "移除帳號",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email} 帳號與已快取的電子郵件將會從 Nextcloud 移除,但不會從您的電子郵件提供商移除。",
"Remove {email}" : "移除 {email}",
+ "could not delete account" : "無法刪除帳號",
"Provisioned account is disabled" : "預先設定的帳號已停用",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "請使用密碼登入以啟用此帳號。目前的工作階段正在使用無密碼身份驗證,例如 SSO 或 WebAuthn。",
+ "Delegate account" : "委派帳號",
"Show only subscribed folders" : "僅顯示已訂閱的資料夾",
"Add folder" : "新增資料夾",
"Folder name" : "資料夾名稱",
diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json
index 2510b5cf9b..985eaa449d 100644
--- a/l10n/zh_TW.json
+++ b/l10n/zh_TW.json
@@ -135,6 +135,7 @@
"Mail settings" : "電子郵件設定",
"General" : "一般",
"Set as default mail app" : "設定為預設的郵件應用程式",
+ "{email} (delegated)" : "{email}(已委派)",
"Add mail account" : "新增郵件帳號",
"Appearance" : "外觀",
"Show all messages in thread" : "在討論串中顯示所有訊息",
@@ -253,7 +254,21 @@
"Expand composer" : "展開編輯器",
"Close composer" : "關閉編輯器",
"Confirm" : "確認",
+ "Delegate access" : "委派存取權",
"Revoke" : "撤銷",
+ "{userId} will no longer be able to act on your behalf" : "{userId} 將無法再代表您執行操作",
+ "Could not fetch delegates" : "無法擷取委派使用者",
+ "Delegated access to {userId}" : "已向 {userId} 委派存取權",
+ "Could not delegate access" : "無法委派存取權",
+ "Revoked access for {userId}" : "已撤銷對 {userId} 的存取",
+ "Could not revoke delegation" : "無法撤銷委派",
+ "Delegation" : "委派",
+ "Allow users to send, receive, and delete mail on your behalf" : "允許使用者代表您傳送、接收與刪除郵件",
+ "Revoke access" : "撤銷存取權",
+ "Add delegate" : "新增委派",
+ "Select a user" : "選取使用者",
+ "They will be able to send, receive, and delete mail on your behalf" : "他們將能代表您傳送、接收與刪除郵件",
+ "Revoke access?" : "撤銷存取權",
"Tag: {name} deleted" : "標籤:{name} 已刪除",
"An error occurred, unable to delete the tag." : "遇到錯誤,無法刪除標籤。",
"The tag will be deleted from all messages." : "該標籤將從所有訊息刪除。",
@@ -450,8 +465,10 @@
"Remove account" : "移除帳號",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email} 帳號與已快取的電子郵件將會從 Nextcloud 移除,但不會從您的電子郵件提供商移除。",
"Remove {email}" : "移除 {email}",
+ "could not delete account" : "無法刪除帳號",
"Provisioned account is disabled" : "預先設定的帳號已停用",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "請使用密碼登入以啟用此帳號。目前的工作階段正在使用無密碼身份驗證,例如 SSO 或 WebAuthn。",
+ "Delegate account" : "委派帳號",
"Show only subscribed folders" : "僅顯示已訂閱的資料夾",
"Add folder" : "新增資料夾",
"Folder name" : "資料夾名稱",
From cdd65ce03f389efe2542914efc73acbb4001edb5 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Tue, 19 May 2026 09:57:36 +0200
Subject: [PATCH 039/228] chore(agents): switch AI attribution trailer to
Assisted-by format
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
AGENTS.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index b91db95b1a..3283688d64 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -124,8 +124,8 @@ The branch will be rebased and squashed into a clean history before merge (CI en
### Commit Message Format
-All commits must include two lines at the end:
-1. Agent/model attribution: `AI-assisted: (model)`
+All commits must include two trailers at the end:
+1. Agent/model attribution: `Assisted-by: :`
2. DCO sign-off: Use `git commit -s` to add automatically
When committing, use: `git commit -m "message" -s`
@@ -139,7 +139,7 @@ fix(deps): Update package dependencies
- Updated package X to latest stable version
- Verified all tests pass
-AI-assisted: OpenCode (Claude Haiku 4.5)
+Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Name
```
From 3cb80369336a34dbd12940bc60ad0fa977e0fddb Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Tue, 19 May 2026 09:57:46 +0200
Subject: [PATCH 040/228] chore(agents): use lowercase present-tense verbs in
commit example
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
AGENTS.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 3283688d64..2826b4299d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -134,10 +134,10 @@ This ensures the sign-off includes your configured Git user email.
Example:
```
-fix(deps): Update package dependencies
+fix(deps): update package dependencies
-- Updated package X to latest stable version
-- Verified all tests pass
+- update package X to latest stable version
+- verify all tests pass
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Name
From 2e1ddaec2d45636f69a70c338fe5caa7b659ffd2 Mon Sep 17 00:00:00 2001
From: Hamza
Date: Wed, 8 Apr 2026 14:28:29 +0200
Subject: [PATCH 041/228] feat: add notifications for account delegation
Signed-off-by: Hamza
---
lib/Controller/DelegationController.php | 4 +-
lib/Notification/Notifier.php | 54 +++++++++-
lib/Service/DelegationService.php | 51 ++++++++-
.../Controller/DelegationControllerTest.php | 6 +-
tests/Unit/Service/DelegationServiceTest.php | 101 ++++++++++++++++--
5 files changed, 198 insertions(+), 18 deletions(-)
diff --git a/lib/Controller/DelegationController.php b/lib/Controller/DelegationController.php
index 487e094ef9..5e5502372e 100644
--- a/lib/Controller/DelegationController.php
+++ b/lib/Controller/DelegationController.php
@@ -86,7 +86,7 @@ public function delegate(int $accountId, string $userId): JSONResponse {
}
try {
- $delegation = $this->delegationService->delegate($accountId, $userId);
+ $delegation = $this->delegationService->delegate($account, $userId, $this->currentUserId);
} catch (DelegationExistsException) {
return new JSONResponse(['message' => 'Delegation already exists'], Http::STATUS_CONFLICT);
}
@@ -111,7 +111,7 @@ public function unDelegate(int $accountId, string $userId): JSONResponse {
return new JSONResponse([], Http::STATUS_UNAUTHORIZED);
}
- $this->delegationService->unDelegate($accountId, $userId);
+ $this->delegationService->unDelegate($account, $userId, $this->currentUserId);
return new JSONResponse([], Http::STATUS_OK);
}
}
diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php
index dedd2e7ebd..f3402b3cee 100644
--- a/lib/Notification/Notifier.php
+++ b/lib/Notification/Notifier.php
@@ -72,8 +72,60 @@ public function prepare(INotification $notification, string $languageCode): INot
]
]);
break;
+ case 'account_delegation':
+ $notification->setIcon($this->url->getAbsoluteURL(
+ $this->url->linkTo('mail', 'img/delegation.svg')
+ ));
+ $parameters = $notification->getSubjectParameters();
+ $messageParameters = $notification->getMessageParameters();
+ $delegated = $messageParameters['delegated'];
+ if ($delegated) {
+ $notification->setRichSubject($l->t('{account_email} has been delegated to you'), [
+ 'account_email' => [
+ 'type' => 'highlight',
+ 'id' => (string)$parameters['id'],
+ 'name' => $parameters['account_email']
+ ]
+ ]);
+ $notification->setRichMessage($l->t('{user} delegated {account} to you'),
+ [
+ 'user' => [
+ 'type' => 'user',
+ 'id' => $messageParameters['current_user_id'],
+ 'name' => $messageParameters['current_user_display_name'],
+ ],
+ 'account' => [
+ 'type' => 'highlight',
+ 'id' => (string)$messageParameters['id'],
+ 'name' => $messageParameters['account_email']
+ ]
+ ]);
+ } else {
+ $notification->setRichSubject($l->t('{account_email} is no longer delegated to you'), [
+ 'account_email' => [
+ 'type' => 'highlight',
+ 'id' => (string)$parameters['id'],
+ 'name' => $parameters['account_email']
+ ]
+ ]);
+ $notification->setRichMessage($l->t('{user} revoked delagation for {account}'),
+ [
+ 'user' => [
+ 'type' => 'user',
+ 'id' => $messageParameters['current_user_id'],
+ 'name' => $messageParameters['current_user_display_name'],
+ ],
+ 'account' => [
+ 'type' => 'highlight',
+ 'id' => (string)$messageParameters['id'],
+ 'name' => $messageParameters['account_email']
+ ]
+ ]);
+ }
+
+ break;
default:
- throw new UnknownNotificationException();
+ throw new UnknownNotificationException();
}
return $notification;
diff --git a/lib/Service/DelegationService.php b/lib/Service/DelegationService.php
index d94e9fdbf8..79b335b7cf 100644
--- a/lib/Service/DelegationService.php
+++ b/lib/Service/DelegationService.php
@@ -9,6 +9,7 @@
namespace OCA\Mail\Service;
+use OCA\Mail\Account;
use OCA\Mail\Db\AliasMapper;
use OCA\Mail\Db\Delegation;
use OCA\Mail\Db\DelegationMapper;
@@ -18,6 +19,9 @@
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\DelegationExistsException;
use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IUserManager;
+use OCP\Notification\IManager;
class DelegationService {
@@ -28,10 +32,14 @@ public function __construct(
private MessageMapper $messageMapper,
private AliasMapper $aliasMapper,
private LocalMessageMapper $localMessageMapper,
+ private IUserManager $userManager,
+ private IManager $notificationManager,
+ private ITimeFactory $time,
) {
}
- public function delegate(int $accountId, string $userId): Delegation {
+ public function delegate(Account $account, string $userId, string $currentUserId): Delegation {
+ $accountId = $account->getId();
try {
$this->delegationMapper->find($accountId, $userId);
throw new DelegationExistsException("Delegation already exists for account $accountId and user $userId");
@@ -42,17 +50,21 @@ public function delegate(int $accountId, string $userId): Delegation {
$delegation = new Delegation();
$delegation->setAccountId($accountId);
$delegation->setUserId($userId);
- return $this->delegationMapper->insert($delegation);
+ $result = $this->delegationMapper->insert($delegation);
+ $this->notify($userId, $currentUserId, $account, true);
+ return $result;
}
public function findDelegatedToUsersForAccount(int $accountId): array {
return $this->delegationMapper->findDelegatedToUsers($accountId);
}
- public function unDelegate(int $accountId, string $userId): void {
+ public function unDelegate(Account $account, string $userId, string $currentUserId): void {
try {
+ $accountId = $account->getId();
$delegation = $this->delegationMapper->find($accountId, $userId);
$this->delegationMapper->delete($delegation);
+ $this->notify($userId, $currentUserId, $account, false);
} catch (DoesNotExistException $e) {
// shouldn't end up here
// delegation not found nothing to undelegate
@@ -112,4 +124,37 @@ public function resolveLocalMessageUserId(int $localMessageId, string $currentUs
$accountId = $this->localMessageMapper->findAccountIdForLocalMessage($localMessageId);
return $this->resolveAccountUserId($accountId, $currentUserId);
}
+
+ /**
+ * Send a notification on delegation
+ * @param string $userId The user the account is being delegated to
+ * @param string $currentUserId Current user
+ * @param Account $account The delegated account
+ * @param bool $delegated true for delegate|false for undelegate
+ * @return void
+ */
+ private function notify(string $userId, string $currentUserId, Account $account, bool $delegated) {
+ $notification = $this->notificationManager->createNotification();
+ $displayName = $this->userManager->getExistingUser($currentUserId)->getDisplayName();
+ $time = $this->time->getDateTime('now');
+ $notification
+ ->setApp('mail')
+ ->setUser($userId)
+ ->setObject('delegation', (string)$account->getId())
+ ->setSubject('account_delegation', [
+ 'id' => $account->getId(),
+ 'account_email' => $account->getEmail(),
+
+ ])
+ ->setDateTime($time)
+ ->setMessage('account_delegation_changed', [
+ 'id' => $account->getId(),
+ 'delegated' => $delegated,
+ 'current_user_id' => $currentUserId,
+ 'current_user_display_name' => $displayName,
+ 'account_email' => $account->getEmail(),
+ ]
+ );
+ $this->notificationManager->notify($notification);
+ }
}
diff --git a/tests/Unit/Controller/DelegationControllerTest.php b/tests/Unit/Controller/DelegationControllerTest.php
index e0a6798c71..582ff6ce91 100644
--- a/tests/Unit/Controller/DelegationControllerTest.php
+++ b/tests/Unit/Controller/DelegationControllerTest.php
@@ -122,7 +122,7 @@ public function testDelegateSuccess(): void {
$this->delegationService->expects($this->once())
->method('delegate')
- ->with(1, 'delegatee')
+ ->with($this->ownAccount, 'delegatee', $this->currentUserId)
->willReturn($delegation);
$response = $this->controller->delegate(1, 'delegatee');
@@ -217,7 +217,7 @@ public function testDelegateAlreadyExists(): void {
$this->delegationService->expects($this->once())
->method('delegate')
- ->with(1, 'delegatee')
+ ->with($this->ownAccount, 'delegatee', $this->currentUserId)
->willThrowException(new DelegationExistsException('Delegation already exists'));
$response = $this->controller->delegate(1, 'delegatee');
@@ -235,7 +235,7 @@ public function testUnDelegateSuccess(): void {
$this->delegationService->expects($this->once())
->method('unDelegate')
- ->with(1, 'delegatee');
+ ->with($this->ownAccount, 'delegatee', $this->currentUserId);
$response = $this->controller->unDelegate(1, 'delegatee');
diff --git a/tests/Unit/Service/DelegationServiceTest.php b/tests/Unit/Service/DelegationServiceTest.php
index c0ab17becf..70ad916c41 100644
--- a/tests/Unit/Service/DelegationServiceTest.php
+++ b/tests/Unit/Service/DelegationServiceTest.php
@@ -24,7 +24,6 @@
use OCA\Mail\Service\DelegationService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
@@ -41,7 +40,6 @@ class DelegationServiceTest extends TestCase {
private IUserManager&MockObject $userManager;
private IManager&MockObject $notificationManager;
private ITimeFactory&MockObject $timeFactory;
- private IEventDispatcher&MockObject $eventDispatcher;
private DelegationService $service;
private Account $account;
@@ -58,7 +56,6 @@ protected function setUp(): void {
$this->userManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(IManager::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->service = new DelegationService(
$this->delegationMapper,
@@ -67,6 +64,9 @@ protected function setUp(): void {
$this->messageMapper,
$this->aliasMapper,
$this->localMessageMapper,
+ $this->userManager,
+ $this->notificationManager,
+ $this->timeFactory,
);
$mailAccount = new MailAccount();
@@ -76,7 +76,7 @@ protected function setUp(): void {
$this->account = new Account($mailAccount);
}
- private function mockNotification(): void {
+ private function mockNotification(): INotification&MockObject {
$notification = $this->createMock(INotification::class);
$notification->method('setApp')->willReturnSelf();
$notification->method('setUser')->willReturnSelf();
@@ -89,8 +89,10 @@ private function mockNotification(): void {
$user = $this->createMock(IUser::class);
$user->method('getDisplayName')->willReturn('Owner User');
- $this->userManager->method('get')->with('owner')->willReturn($user);
+ $this->userManager->method('getExistingUser')->with('owner')->willReturn($user);
$this->timeFactory->method('getDateTime')->willReturn(new \DateTime());
+
+ return $notification;
}
public function testDelegateSuccess(): void {
@@ -112,7 +114,7 @@ public function testDelegateSuccess(): void {
return $d;
});
- $result = $this->service->delegate($this->account->getId(), 'delegatee');
+ $result = $this->service->delegate($this->account, 'delegatee', 'owner');
$this->assertEquals(1, $result->getAccountId());
$this->assertEquals('delegatee', $result->getUserId());
@@ -133,7 +135,7 @@ public function testDelegateThrowsWhenAlreadyExists(): void {
$this->expectException(DelegationExistsException::class);
- $this->service->delegate($this->account->getId(), 'delegatee');
+ $this->service->delegate($this->account, 'delegatee', 'owner');
}
public function testFindDelegatedToUsersForAccount(): void {
@@ -169,10 +171,12 @@ public function testUnDelegateSuccess(): void {
->method('delete')
->with($delegation);
- $this->service->unDelegate($this->account->getId(), 'delegatee');
+ $this->service->unDelegate($this->account, 'delegatee', 'owner');
}
public function testUnDelegateWhenNotFound(): void {
+ $this->mockNotification();
+
$this->delegationMapper->expects($this->once())
->method('find')
->with(1, 'delegatee')
@@ -181,7 +185,7 @@ public function testUnDelegateWhenNotFound(): void {
$this->delegationMapper->expects($this->never())
->method('delete');
- $this->service->unDelegate($this->account->getId(), 'delegatee');
+ $this->service->unDelegate($this->account, 'delegatee', 'owner');
}
public function testResolveAccountUserIdOwner(): void {
@@ -310,4 +314,83 @@ public function testResolveLocalMessageUserId(): void {
$this->assertEquals('owner', $result);
}
+
+ public function testDelegateSendsNotification(): void {
+ $notification = $this->mockNotification();
+ $now = new \DateTime();
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->timeFactory->method('getDateTime')->willReturn($now);
+
+ $this->delegationMapper->method('find')
+ ->willThrowException(new DoesNotExistException('Not found'));
+ $this->delegationMapper->method('insert')
+ ->willReturnCallback(function (Delegation $d) {
+ $d->setId(10);
+ return $d;
+ });
+
+ $notification->expects($this->once())->method('setApp')->with('mail')->willReturnSelf();
+ $notification->expects($this->once())->method('setUser')->with('delegatee')->willReturnSelf();
+ $notification->expects($this->once())->method('setObject')->with('delegation', '1')->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setSubject')
+ ->with('account_delegation', [
+ 'id' => 1,
+ 'account_email' => 'owner@example.com',
+ ])
+ ->willReturnSelf();
+ $notification->expects($this->once())->method('setDateTime')->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setMessage')
+ ->with('account_delegation_changed', [
+ 'id' => 1,
+ 'delegated' => true,
+ 'current_user_id' => 'owner',
+ 'current_user_display_name' => 'Owner User',
+ 'account_email' => 'owner@example.com',
+ ])
+ ->willReturnSelf();
+ $this->notificationManager->expects($this->once())
+ ->method('notify')
+ ->with($notification);
+
+ $this->service->delegate($this->account, 'delegatee', 'owner');
+ }
+
+ public function testUnDelegateSendsRevokedNotification(): void {
+ $notification = $this->mockNotification();
+
+ $delegation = new Delegation();
+ $delegation->setId(10);
+ $delegation->setAccountId(1);
+ $delegation->setUserId('delegatee');
+
+ $this->delegationMapper->method('find')->willReturn($delegation);
+
+ $notification->expects($this->once())->method('setApp')->with('mail')->willReturnSelf();
+ $notification->expects($this->once())->method('setUser')->with('delegatee')->willReturnSelf();
+ $notification->expects($this->once())->method('setObject')->with('delegation', '1')->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setSubject')
+ ->with('account_delegation', [
+ 'id' => 1,
+ 'account_email' => 'owner@example.com',
+ ])
+ ->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setMessage')
+ ->with('account_delegation_changed', [
+ 'id' => 1,
+ 'delegated' => false,
+ 'current_user_id' => 'owner',
+ 'current_user_display_name' => 'Owner User',
+ 'account_email' => 'owner@example.com',
+ ])
+ ->willReturnSelf();
+ $this->notificationManager->expects($this->once())
+ ->method('notify')
+ ->with($notification);
+
+ $this->service->unDelegate($this->account, 'delegatee', 'owner');
+ }
}
From dc0799b51fd8545e3069ed9dc344565e2f5ca208 Mon Sep 17 00:00:00 2001
From: Hamza
Date: Thu, 14 May 2026 12:14:59 +0200
Subject: [PATCH 042/228] test: cover delegation branches in Notifier
AI-assisted: Claude Opus 4.7 (1M context)
Signed-off-by: Hamza
---
lib/Notification/Notifier.php | 2 +-
lib/Service/DelegationService.php | 12 +-
tests/Unit/Notification/NotifierTest.php | 185 +++++++++++++++++++
tests/Unit/Service/DelegationServiceTest.php | 6 +-
4 files changed, 201 insertions(+), 4 deletions(-)
create mode 100644 tests/Unit/Notification/NotifierTest.php
diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php
index f3402b3cee..a89684a382 100644
--- a/lib/Notification/Notifier.php
+++ b/lib/Notification/Notifier.php
@@ -108,7 +108,7 @@ public function prepare(INotification $notification, string $languageCode): INot
'name' => $parameters['account_email']
]
]);
- $notification->setRichMessage($l->t('{user} revoked delagation for {account}'),
+ $notification->setRichMessage($l->t('{user} revoked delegation for {account}'),
[
'user' => [
'type' => 'user',
diff --git a/lib/Service/DelegationService.php b/lib/Service/DelegationService.php
index 79b335b7cf..588ca42731 100644
--- a/lib/Service/DelegationService.php
+++ b/lib/Service/DelegationService.php
@@ -22,6 +22,8 @@
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IUserManager;
use OCP\Notification\IManager;
+use OCP\Notification\IncompleteNotificationException;
+use Psr\Log\LoggerInterface;
class DelegationService {
@@ -35,6 +37,7 @@ public function __construct(
private IUserManager $userManager,
private IManager $notificationManager,
private ITimeFactory $time,
+ private LoggerInterface $logger,
) {
}
@@ -135,7 +138,7 @@ public function resolveLocalMessageUserId(int $localMessageId, string $currentUs
*/
private function notify(string $userId, string $currentUserId, Account $account, bool $delegated) {
$notification = $this->notificationManager->createNotification();
- $displayName = $this->userManager->getExistingUser($currentUserId)->getDisplayName();
+ $displayName = $this->userManager->get($currentUserId)?->getDisplayName() ?? $currentUserId;
$time = $this->time->getDateTime('now');
$notification
->setApp('mail')
@@ -155,6 +158,11 @@ private function notify(string $userId, string $currentUserId, Account $account,
'account_email' => $account->getEmail(),
]
);
- $this->notificationManager->notify($notification);
+
+ try {
+ $this->notificationManager->notify($notification);
+ } catch (IncompleteNotificationException $e) {
+ $this->logger->warning('Failed to send delegation notification to {userId}', ['userId' => $userId,'exception' => $e]);
+ }
}
}
diff --git a/tests/Unit/Notification/NotifierTest.php b/tests/Unit/Notification/NotifierTest.php
new file mode 100644
index 0000000000..9ac2fb716d
--- /dev/null
+++ b/tests/Unit/Notification/NotifierTest.php
@@ -0,0 +1,185 @@
+factory = $this->createMock(IFactory::class);
+ $this->url = $this->createMock(IURLGenerator::class);
+ $this->l10n = $this->createMock(IL10N::class);
+ $this->l10n->method('t')->willReturnArgument(0);
+ $this->factory->method('get')->willReturn($this->l10n);
+
+ $this->notifier = new Notifier($this->factory, $this->url);
+ }
+
+ public function testGetID(): void {
+ $this->assertEquals('mail', $this->notifier->getID());
+ }
+
+ public function testGetName(): void {
+ $this->assertEquals('Mail', $this->notifier->getName());
+ }
+
+ public function testPrepareForeignAppThrows(): void {
+ $notification = $this->createMock(INotification::class);
+ $notification->method('getApp')->willReturn('other');
+
+ $this->expectException(UnknownNotificationException::class);
+
+ $this->notifier->prepare($notification, 'en');
+ }
+
+ public function testPrepareUnknownSubjectThrows(): void {
+ $notification = $this->createMock(INotification::class);
+ $notification->method('getApp')->willReturn('mail');
+ $notification->method('getSubject')->willReturn('something_unknown');
+
+ $this->expectException(UnknownNotificationException::class);
+
+ $this->notifier->prepare($notification, 'en');
+ }
+
+ public function testPrepareAccountDelegationDelegated(): void {
+ $notification = $this->createMock(INotification::class);
+ $notification->method('getApp')->willReturn('mail');
+ $notification->method('getSubject')->willReturn('account_delegation');
+ $notification->method('getSubjectParameters')->willReturn([
+ 'id' => 1,
+ 'account_email' => 'owner@example.com',
+ ]);
+ $notification->method('getMessageParameters')->willReturn([
+ 'id' => 1,
+ 'delegated' => true,
+ 'current_user_id' => 'owner',
+ 'current_user_display_name' => 'Owner User',
+ 'account_email' => 'owner@example.com',
+ ]);
+
+ $this->url->method('linkTo')->with('mail', 'img/delegation.svg')->willReturn('/apps/mail/img/delegation.svg');
+ $this->url->method('getAbsoluteURL')->with('/apps/mail/img/delegation.svg')->willReturn('https://example.com/apps/mail/img/delegation.svg');
+
+ $notification->expects($this->once())
+ ->method('setIcon')
+ ->with('https://example.com/apps/mail/img/delegation.svg')
+ ->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setRichSubject')
+ ->with(
+ '{account_email} has been delegated to you',
+ [
+ 'account_email' => [
+ 'type' => 'highlight',
+ 'id' => '1',
+ 'name' => 'owner@example.com',
+ ],
+ ]
+ )
+ ->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setRichMessage')
+ ->with(
+ '{user} delegated {account} to you',
+ [
+ 'user' => [
+ 'type' => 'user',
+ 'id' => 'owner',
+ 'name' => 'Owner User',
+ ],
+ 'account' => [
+ 'type' => 'highlight',
+ 'id' => '1',
+ 'name' => 'owner@example.com',
+ ],
+ ]
+ )
+ ->willReturnSelf();
+
+ $result = $this->notifier->prepare($notification, 'en');
+
+ $this->assertSame($notification, $result);
+ }
+
+ public function testPrepareAccountDelegationRevoked(): void {
+ $notification = $this->createMock(INotification::class);
+ $notification->method('getApp')->willReturn('mail');
+ $notification->method('getSubject')->willReturn('account_delegation');
+ $notification->method('getSubjectParameters')->willReturn([
+ 'id' => 1,
+ 'account_email' => 'owner@example.com',
+ ]);
+ $notification->method('getMessageParameters')->willReturn([
+ 'id' => 1,
+ 'delegated' => false,
+ 'current_user_id' => 'owner',
+ 'current_user_display_name' => 'Owner User',
+ 'account_email' => 'owner@example.com',
+ ]);
+
+ $this->url->method('linkTo')->with('mail', 'img/delegation.svg')->willReturn('/apps/mail/img/delegation.svg');
+ $this->url->method('getAbsoluteURL')->with('/apps/mail/img/delegation.svg')->willReturn('https://example.com/apps/mail/img/delegation.svg');
+
+ $notification->expects($this->once())
+ ->method('setIcon')
+ ->with('https://example.com/apps/mail/img/delegation.svg')
+ ->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setRichSubject')
+ ->with(
+ '{account_email} is no longer delegated to you',
+ [
+ 'account_email' => [
+ 'type' => 'highlight',
+ 'id' => '1',
+ 'name' => 'owner@example.com',
+ ],
+ ]
+ )
+ ->willReturnSelf();
+ $notification->expects($this->once())
+ ->method('setRichMessage')
+ ->with(
+ '{user} revoked delegation for {account}',
+ [
+ 'user' => [
+ 'type' => 'user',
+ 'id' => 'owner',
+ 'name' => 'Owner User',
+ ],
+ 'account' => [
+ 'type' => 'highlight',
+ 'id' => '1',
+ 'name' => 'owner@example.com',
+ ],
+ ]
+ )
+ ->willReturnSelf();
+
+ $result = $this->notifier->prepare($notification, 'en');
+
+ $this->assertSame($notification, $result);
+ }
+}
diff --git a/tests/Unit/Service/DelegationServiceTest.php b/tests/Unit/Service/DelegationServiceTest.php
index 70ad916c41..14b84275e3 100644
--- a/tests/Unit/Service/DelegationServiceTest.php
+++ b/tests/Unit/Service/DelegationServiceTest.php
@@ -29,6 +29,7 @@
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
class DelegationServiceTest extends TestCase {
private DelegationMapper&MockObject $delegationMapper;
@@ -40,6 +41,7 @@ class DelegationServiceTest extends TestCase {
private IUserManager&MockObject $userManager;
private IManager&MockObject $notificationManager;
private ITimeFactory&MockObject $timeFactory;
+ private LoggerInterface&MockObject $logger;
private DelegationService $service;
private Account $account;
@@ -56,6 +58,7 @@ protected function setUp(): void {
$this->userManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(IManager::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->service = new DelegationService(
$this->delegationMapper,
@@ -67,6 +70,7 @@ protected function setUp(): void {
$this->userManager,
$this->notificationManager,
$this->timeFactory,
+ $this->logger,
);
$mailAccount = new MailAccount();
@@ -89,7 +93,7 @@ private function mockNotification(): INotification&MockObject {
$user = $this->createMock(IUser::class);
$user->method('getDisplayName')->willReturn('Owner User');
- $this->userManager->method('getExistingUser')->with('owner')->willReturn($user);
+ $this->userManager->method('get')->with('owner')->willReturn($user);
$this->timeFactory->method('getDateTime')->willReturn(new \DateTime());
return $notification;
From 98f6282008460663bd312d66d4398ae01aa7c188 Mon Sep 17 00:00:00 2001
From: Andrii Rublov
Date: Thu, 15 Feb 2024 21:12:21 +0100
Subject: [PATCH 043/228] feat(ui): paste or copy several e-mail addresses into
address fields at once
Signed-off-by: Andrii Rublov
---
src/components/Composer.vue | 99 +++++++----
src/tests/unit/util/emailAddress.spec.js | 213 +++++++++++++++++++++++
src/util/emailAddress.js | 132 ++++++++++++++
3 files changed, 414 insertions(+), 30 deletions(-)
create mode 100644 src/tests/unit/util/emailAddress.spec.js
create mode 100644 src/util/emailAddress.js
diff --git a/src/components/Composer.vue b/src/components/Composer.vue
index 6bbf7cc0fe..e8c217aeb1 100644
--- a/src/components/Composer.vue
+++ b/src/components/Composer.vue
@@ -509,7 +509,6 @@ import { showError, showWarning } from '@nextcloud/dialogs'
import { getCanonicalLocale, getFirstDay, getLocale, translate as t } from '@nextcloud/l10n'
import moment from '@nextcloud/moment'
import { NcActionButton as ActionButton, NcActionCheckbox as ActionCheckbox, NcActionInput as ActionInput, NcActionRadio as ActionRadio, NcActions as Actions, NcButton as ButtonVue, NcListItemIcon as ListItemIcon, NcIconSvgWrapper, NcSelect } from '@nextcloud/vue'
-import addressParser from 'address-rfc2822'
import debouncePromise from 'debounce-promise'
import debounce from 'lodash/fp/debounce.js'
import trimStart from 'lodash/fp/trimCharsStart.js'
@@ -544,6 +543,7 @@ import { findRecipient } from '../service/AutocompleteService.js'
import { savePreference } from '../service/PreferenceService.js'
import { EDITOR_MODE_HTML, EDITOR_MODE_TEXT } from '../store/constants.js'
import useMainStore from '../store/mainStore.js'
+import { parseEmailList } from '../util/emailAddress.js'
import { formatDateTime } from '../util/formatDateTime.js'
import { detect, html, toHtml, toPlain } from '../util/text.js'
import textBlockSvg from './../../img/text_snippet.svg'
@@ -1130,8 +1130,9 @@ export default {
/**
* Called once a user leaves the recipient picker.
*
- * If the user is typing something that looks like a valid email address, we clear the input (return true)
- * because the related code in onNewAddr will add the value as a recipient.
+ * If the user is typing something that looks like a valid email address (or a
+ * pasted list of addresses), we clear the input (return true) because the
+ * related code in onNewAddr will add the value as a recipient.
*
* Otherwise, the user is still typing and we don't clear the input.
*
@@ -1140,7 +1141,7 @@ export default {
*/
clearOnBlur(event) {
if (this.recipientSearchTerms[event]) {
- return this.seemsValidEmailAddress(this.recipientSearchTerms[event])
+ return parseEmailList(this.recipientSearchTerms[event]).length > 0
}
return false
},
@@ -1470,27 +1471,71 @@ export default {
},
onNewAddr(option, list, type) {
+ // Build a Set of already-selected emails for O(1) case-insensitive dedup.
+ const existing = new Set(list.map((r) => r.email.toLowerCase()))
+
if (
(option === null || option === undefined)
&& this.recipientSearchTerms[type] !== undefined
&& this.recipientSearchTerms[type] !== ''
) {
- if (!this.seemsValidEmailAddress(this.recipientSearchTerms[type])) {
+ const parsedFromSearch = parseEmailList(this.recipientSearchTerms[type])
+ if (parsedFromSearch.length === 0) {
return
}
- option = {}
- option.email = this.recipientSearchTerms[type]
- option.label = this.recipientSearchTerms[type]
this.recipientSearchTerms[type] = ''
+
+ let changed = false
+ for (const addr of parsedFromSearch) {
+ if (!existing.has(addr.email.toLowerCase())) {
+ const recipient = { ...addr }
+ this.newRecipients.push(recipient)
+ list.push(recipient)
+ existing.add(addr.email.toLowerCase())
+ changed = true
+ }
+ }
+ if (changed) {
+ this.saveDraftDebounced()
+ }
+ return
}
- if (list.some((recipient) => recipient.email === option?.email) || !option) {
+ if (!option) {
return
}
- const recipient = { ...option }
- this.newRecipients.push(recipient)
- list.push(recipient)
- this.saveDraftDebounced()
+
+ let changed = false
+ if (option.id) {
+ if (!existing.has(option.email.toLowerCase())) {
+ const recipient = { ...option }
+ this.newRecipients.push(recipient)
+ list.push(recipient)
+ changed = true
+ }
+ } else {
+ const emailList = parseEmailList(option.email)
+ // When createRecipientOption normalised a named address like
+ // "Jane Doe " it stored the display name in
+ // option.label but reduced option.email to the bare address.
+ // Re-parsing that bare address loses the display name, so for
+ // single-address options we trust option.label directly.
+ const recipientsToAdd = emailList.length === 1
+ ? [{ email: option.email, label: option.label ?? option.email }]
+ : emailList
+ for (const addr of recipientsToAdd) {
+ if (!existing.has(addr.email.toLowerCase())) {
+ const recipient = { ...addr }
+ this.newRecipients.push(recipient)
+ list.push(recipient)
+ existing.add(addr.email.toLowerCase())
+ changed = true
+ }
+ }
+ }
+ if (changed) {
+ this.saveDraftDebounced()
+ }
},
async onSend() {
@@ -1659,10 +1704,18 @@ export default {
* @return {{email: string, label: string}} The new option
*/
createRecipientOption(value) {
- if (!this.seemsValidEmailAddress(value)) {
- throw new Error('Skipping because it does not look like a valid email address')
+ const parsed = parseEmailList(value)
+ if (parsed.length === 0) {
+ throw new Error('Skipping because it does not look like valid email address(es)')
+ }
+ // For a single address, return the normalised email/label so the chip
+ // shows a clean address rather than the raw typed/pasted string.
+ if (parsed.length === 1) {
+ return { email: parsed[0].email, label: parsed[0].label }
}
- return { email: value, label: value }
+ // For multi-address pastes keep the raw value so onNewAddr can expand
+ // all addresses from option.email.
+ return { email: value.trim(), label: value.trim() }
},
/**
@@ -1686,20 +1739,6 @@ export default {
return option.email
},
- /**
- * True when value looks like a valid email address
- *
- * @param {string} value to check if email address
- * @return {boolean}
- */
- seemsValidEmailAddress(value) {
- try {
- addressParser.parse(value)
- return true
- } catch (error) {
- return false
- }
- },
},
}
diff --git a/src/tests/unit/util/emailAddress.spec.js b/src/tests/unit/util/emailAddress.spec.js
new file mode 100644
index 0000000000..92a442db27
--- /dev/null
+++ b/src/tests/unit/util/emailAddress.spec.js
@@ -0,0 +1,213 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { getLabelAndAddress, parseEmailList } from '../../../util/emailAddress.js'
+
+describe('getLabelAndAddress', () => {
+ it('parses a plain email address', () => {
+ expect(getLabelAndAddress('alice@example.com')).toEqual({
+ label: 'alice@example.com',
+ email: 'alice@example.com',
+ })
+ })
+
+ it('parses an email with angle brackets', () => {
+ expect(getLabelAndAddress('')).toEqual({
+ label: 'alice@example.com',
+ email: 'alice@example.com',
+ })
+ })
+
+ it('parses a display name with angle bracket email', () => {
+ expect(getLabelAndAddress('Alice Smith ')).toEqual({
+ label: 'Alice Smith',
+ email: 'alice@example.com',
+ })
+ })
+
+ it('preserves uppercase email addresses', () => {
+ expect(getLabelAndAddress('User@Example.COM')).toEqual({
+ label: 'User@Example.COM',
+ email: 'User@Example.COM',
+ })
+ })
+
+ it('handles mixed case with display name', () => {
+ expect(getLabelAndAddress('Alice ')).toEqual({
+ label: 'Alice',
+ email: 'Alice@Example.COM',
+ })
+ })
+
+ it('returns null for invalid input', () => {
+ expect(getLabelAndAddress('not an email')).toBeNull()
+ })
+
+ it('returns null for empty string', () => {
+ expect(getLabelAndAddress('')).toBeNull()
+ })
+
+ it('returns null for null or undefined', () => {
+ expect(getLabelAndAddress(null)).toBeNull()
+ expect(getLabelAndAddress(undefined)).toBeNull()
+ })
+
+ it('handles trailing delimiter with trailing whitespace', () => {
+ expect(getLabelAndAddress('alice@example.com, ')).toEqual({
+ label: 'alice@example.com',
+ email: 'alice@example.com',
+ })
+ })
+
+ it('does not include trailing delimiters in the email', () => {
+ expect(getLabelAndAddress('alice@example.com,')).toEqual({
+ label: 'alice@example.com',
+ email: 'alice@example.com',
+ })
+ })
+
+ it('does not include trailing semicolons in the email', () => {
+ expect(getLabelAndAddress('alice@example.com;')).toEqual({
+ label: 'alice@example.com',
+ email: 'alice@example.com',
+ })
+ })
+
+ it('handles email with subdomains', () => {
+ expect(getLabelAndAddress('user@mail.example.co.uk')).toEqual({
+ label: 'user@mail.example.co.uk',
+ email: 'user@mail.example.co.uk',
+ })
+ })
+
+ it('handles email with special characters in local part', () => {
+ expect(getLabelAndAddress('user+tag@example.com')).toEqual({
+ label: 'user+tag@example.com',
+ email: 'user+tag@example.com',
+ })
+ })
+})
+
+describe('parseEmailList', () => {
+ it('parses a single email', () => {
+ expect(parseEmailList('alice@example.com')).toEqual([
+ { label: 'alice@example.com', email: 'alice@example.com' },
+ ])
+ })
+
+ it('parses comma-separated emails', () => {
+ expect(parseEmailList('alice@example.com, bob@example.com')).toEqual([
+ { label: 'alice@example.com', email: 'alice@example.com' },
+ { label: 'bob@example.com', email: 'bob@example.com' },
+ ])
+ })
+
+ it('parses semicolon-separated emails', () => {
+ expect(parseEmailList('alice@example.com; bob@example.com')).toEqual([
+ { label: 'alice@example.com', email: 'alice@example.com' },
+ { label: 'bob@example.com', email: 'bob@example.com' },
+ ])
+ })
+
+ it('parses space-separated emails', () => {
+ expect(parseEmailList('alice@example.com bob@example.com')).toEqual([
+ { label: 'alice@example.com', email: 'alice@example.com' },
+ { label: 'bob@example.com', email: 'bob@example.com' },
+ ])
+ })
+
+ it('parses emails with display names', () => {
+ expect(parseEmailList('Alice , Bob ')).toEqual([
+ { label: 'Alice', email: 'alice@example.com' },
+ { label: 'Bob', email: 'bob@example.com' },
+ ])
+ })
+
+ it('preserves uppercase email addresses', () => {
+ expect(parseEmailList('User@Example.COM, Another@TEST.org')).toEqual([
+ { label: 'User@Example.COM', email: 'User@Example.COM' },
+ { label: 'Another@TEST.org', email: 'Another@TEST.org' },
+ ])
+ })
+
+ it('handles mixed delimiters', () => {
+ expect(parseEmailList('a@example.com, b@example.com; c@example.com')).toEqual([
+ { label: 'a@example.com', email: 'a@example.com' },
+ { label: 'b@example.com', email: 'b@example.com' },
+ { label: 'c@example.com', email: 'c@example.com' },
+ ])
+ })
+
+ it('ignores non-email entries in a list', () => {
+ expect(parseEmailList('not-an-email, alice@example.com')).toEqual([
+ { label: 'alice@example.com', email: 'alice@example.com' },
+ ])
+ })
+
+ it('skips entries without any email address', () => {
+ expect(parseEmailList('just-text')).toEqual([])
+ })
+
+ it('returns empty array for empty string', () => {
+ expect(parseEmailList('')).toEqual([])
+ })
+
+ it('returns empty array for string without emails', () => {
+ expect(parseEmailList('just some text without emails')).toEqual([])
+ })
+
+ it('handles trailing delimiters', () => {
+ expect(parseEmailList('alice@example.com, bob@example.com,')).toEqual([
+ { label: 'alice@example.com', email: 'alice@example.com' },
+ { label: 'bob@example.com', email: 'bob@example.com' },
+ ])
+ })
+
+ it('handles multiple addresses with angle brackets and display names', () => {
+ expect(parseEmailList('Alice Smith ; Bob Jones ')).toEqual([
+ { label: 'Alice Smith', email: 'alice@example.com' },
+ { label: 'Bob Jones', email: 'bob@example.com' },
+ ])
+ })
+
+ it('handles quoted display names containing commas', () => {
+ // address-rfc2822 normalizes "Last, First" to "First Last" per RFC 2822
+ expect(parseEmailList('"Smith, Alice" , "Jones, Bob" ')).toEqual([
+ { label: 'Alice Smith', email: 'alice@example.com' },
+ { label: 'Bob Jones', email: 'bob@example.com' },
+ ])
+ })
+
+ it('extracts valid addresses from mixed input with invalid tokens', () => {
+ expect(parseEmailList('invalid-entry, "Smith, Alice" , not-an-email, bob@example.com')).toEqual([
+ { label: 'Alice Smith', email: 'alice@example.com' },
+ { label: 'bob@example.com', email: 'bob@example.com' },
+ ])
+ })
+
+ it('returns empty array for null or undefined', () => {
+ expect(parseEmailList(null)).toEqual([])
+ expect(parseEmailList(undefined)).toEqual([])
+ })
+
+ // Regression tests from PR description / issue #6013
+ it('handles real-world paste: plain addresses with display name (issue #6013 case 1)', () => {
+ const result = parseEmailList('test@test.com, Jane Doe, MSc jane@doe.tld')
+ expect(result).toEqual([
+ { label: 'test@test.com', email: 'test@test.com' },
+ { label: 'jane@doe.tld', email: 'jane@doe.tld' },
+ ])
+ })
+
+ it('handles real-world paste: messy mixed input (issue #6013 case 2)', () => {
+ const input = 'ian eiloart iane@example.ac.uk>;shuf6@example.ac.uk,, test+user@company.c, "ian,eiloart", <@example.com:foo@example.ac.uk>, foo@#,ian@-example.com, ian@one@two;asdas< test@test.com> test@test.com, Newasd Na@,me >; testaaaa@aasd.com'
+ const result = parseEmailList(input)
+ const emails = result.map((r) => r.email)
+ expect(emails).toContain('shuf6@example.ac.uk')
+ expect(emails).toContain('ian@example.ac.uk')
+ expect(emails).toContain('test@test.com')
+ expect(emails).toContain('testaaaa@aasd.com')
+ })
+})
diff --git a/src/util/emailAddress.js b/src/util/emailAddress.js
new file mode 100644
index 0000000000..8a6ed6e0b1
--- /dev/null
+++ b/src/util/emailAddress.js
@@ -0,0 +1,132 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import addressParser from 'address-rfc2822'
+
+/**
+ * Try to parse a string with address-rfc2822.
+ * Returns an array of {label, email} objects, or an empty array on failure.
+ *
+ * @param {string} str The input string
+ * @return {Array<{ label: string, email: string }>}
+ */
+function tryParse(str) {
+ if (!str) {
+ return []
+ }
+
+ try {
+ return addressParser.parse(str).map((addr) => ({
+ label: addr.name() || addr.address,
+ email: addr.address,
+ }))
+ } catch {
+ return []
+ }
+}
+
+/**
+ * Split a string on delimiter characters (commas and semicolons) that are
+ * not inside quotes or angle brackets.
+ *
+ * @param {string} str The input string
+ * @return {string[]} The parts
+ */
+function splitOnDelimiters(str) {
+ const parts = []
+ let current = ''
+ let inQuotes = false
+ let inAngle = false
+
+ for (let i = 0; i < str.length; i++) {
+ const ch = str[i]
+
+ if (ch === '"' && (i === 0 || str[i - 1] !== '\\')) {
+ inQuotes = !inQuotes
+ } else if (!inQuotes && ch === '<') {
+ inAngle = true
+ } else if (!inQuotes && ch === '>') {
+ inAngle = false
+ }
+
+ if ((ch === ',' || ch === ';') && !inQuotes && !inAngle) {
+ parts.push(current)
+ current = ''
+ } else {
+ current += ch
+ }
+ }
+ parts.push(current)
+ return parts
+}
+
+/**
+ * Extract a label and email address from a string like "John Doe "
+ * or just "john@example.com".
+ *
+ * @param {string|null|undefined} str The input string
+ * @return {{ label: string, email: string } | null} Parsed result or null if no email found
+ */
+export function getLabelAndAddress(str) {
+ if (!str) {
+ return null
+ }
+
+ // Trim first so trailing delimiters followed by whitespace are still removed
+ const cleaned = str.trim().replace(/[,;]+$/, '').trim()
+ const results = tryParse(cleaned)
+ return results.length > 0 ? results[0] : null
+}
+
+/**
+ * Parse a string containing one or more email addresses separated by
+ * commas or semicolons, with limited support for spaces between bare
+ * email addresses.
+ *
+ * Supports formats like:
+ * - "alice@example.com, bob@example.com"
+ * - "Alice ; Bob "
+ * - "alice@example.com bob@example.com" (bare email addresses only)
+ *
+ * @param {string|null|undefined} str The input string containing email addresses
+ * @return {Array<{ label: string, email: string }>} List of parsed addresses
+ */
+export function parseEmailList(str) {
+ if (!str) {
+ return []
+ }
+
+ // Split on commas and semicolons (respecting quotes/angle brackets),
+ // then normalize to a comma-separated string for address-rfc2822.
+ const parts = splitOnDelimiters(str)
+ const normalized = parts.map((p) => p.trim()).filter(Boolean).join(', ')
+
+ // First try: parse the whole normalized string (handles clean lists)
+ const results = tryParse(normalized)
+ if (results.length > 0) {
+ return results
+ }
+
+ // Second try: parse each part individually. This handles cases like
+ // "not-an-email, alice@example.com" where the library rejects the whole string.
+ const list = []
+ for (const part of parts) {
+ const trimmed = part.trim()
+ if (!trimmed) {
+ continue
+ }
+
+ const parsed = tryParse(trimmed)
+ if (parsed.length > 0) {
+ list.push(...parsed)
+ } else if (trimmed.includes(' ') && trimmed.includes('@')) {
+ // Try splitting on spaces for space-separated bare emails
+ for (const word of trimmed.split(/\s+/)) {
+ list.push(...tryParse(word))
+ }
+ }
+ }
+ return list
+}
From 6d20e3f06afb127e5e5f19fca8fd6a810747eb46 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 20 May 2026 18:42:54 +0200
Subject: [PATCH 044/228] fix(package): exclude dev config and patch files from
release tarball
eslint.config.mjs (flat config), stylelint.config.js, playwright.config.js,
tsconfig.json, .patches/, patches.json, and patches.lock.json were all
missing from .nextcloudignore and ended up in the v5.8.0 release tarball.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.nextcloudignore | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/.nextcloudignore b/.nextcloudignore
index a9ec6055e6..4605780a89 100644
--- a/.nextcloudignore
+++ b/.nextcloudignore
@@ -11,6 +11,7 @@ codecov.yml
/coverage
/.editorconfig
/.eslintrc.js
+/eslint.config.mjs
.git
.git-blame-ignore-revs
.gitattributes
@@ -45,3 +46,9 @@ codecov.yml
/webpack.*
/vitest.config.*
/patches
+/.patches
+/patches.json
+/patches.lock.json
+/playwright.config.js
+/stylelint.config.js
+/tsconfig.json
From 525c3ab9d53f19082c137cc0050f4038c54f0b70 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 20 May 2026 20:06:16 +0200
Subject: [PATCH 045/228] fix(ui): add NcModal name prop to
SmimeCertificateModal for accessibility
NcModal requires either `name` or `labelId` so screen readers can
announce the dialog. Use a dynamic value matching the two h2 headings
already rendered in the list and import views.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/components/smime/SmimeCertificateModal.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/smime/SmimeCertificateModal.vue b/src/components/smime/SmimeCertificateModal.vue
index bdfbe4383b..9e3386df87 100644
--- a/src/components/smime/SmimeCertificateModal.vue
+++ b/src/components/smime/SmimeCertificateModal.vue
@@ -4,7 +4,7 @@
-->
-
+
{{ t('mail', 'S/MIME certificates') }}
From b37655d8d5fd9ad84f2ddb1ef94b2e60e7488140 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Thu, 21 May 2026 01:45:41 +0000
Subject: [PATCH 046/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/de.js | 4 ++++
l10n/de.json | 4 ++++
l10n/de_DE.js | 4 ++++
l10n/de_DE.json | 4 ++++
l10n/fr.js | 25 ++++++++++++++++++++++++-
l10n/fr.json | 25 ++++++++++++++++++++++++-
l10n/ga.js | 4 ++++
l10n/ga.json | 4 ++++
l10n/pt_BR.js | 4 ++++
l10n/pt_BR.json | 4 ++++
10 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/l10n/de.js b/l10n/de.js
index c9dde59a99..62ef267ff3 100644
--- a/l10n/de.js
+++ b/l10n/de.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "E-Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Du erreichst die Grenze deines Postfach-Kontingents für {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Du nutzt derzeit {percentage} deines Postfachspeichers. Bitte schaffe etwas Platz, indem du nicht benötigte E-Mails löscht.",
+ "{account_email} has been delegated to you" : "{account_email} wurde an dich delegiert",
+ "{user} delegated {account} to you" : "{user} hat {account} an dich delegiert",
+ "{account_email} is no longer delegated to you" : "{account_email} ist nicht mehr an dich delegiert",
+ "{user} revoked delegation for {account}" : "{user} hat die Delegation von {account} widerrufen",
"Mail Application" : "E-Mail Anwendung",
"Mails" : "E-Mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "E-Mail-Adresse des Absenders %1$s ist nicht im Adressbuch, aber der Name des Absenders %2$s ist mit der folgender E-Mail-Adresse im Adressbuch %3$s",
diff --git a/l10n/de.json b/l10n/de.json
index 0b20de310c..4fbca88922 100644
--- a/l10n/de.json
+++ b/l10n/de.json
@@ -12,6 +12,10 @@
"Mail" : "E-Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Du erreichst die Grenze deines Postfach-Kontingents für {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Du nutzt derzeit {percentage} deines Postfachspeichers. Bitte schaffe etwas Platz, indem du nicht benötigte E-Mails löscht.",
+ "{account_email} has been delegated to you" : "{account_email} wurde an dich delegiert",
+ "{user} delegated {account} to you" : "{user} hat {account} an dich delegiert",
+ "{account_email} is no longer delegated to you" : "{account_email} ist nicht mehr an dich delegiert",
+ "{user} revoked delegation for {account}" : "{user} hat die Delegation von {account} widerrufen",
"Mail Application" : "E-Mail Anwendung",
"Mails" : "E-Mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "E-Mail-Adresse des Absenders %1$s ist nicht im Adressbuch, aber der Name des Absenders %2$s ist mit der folgender E-Mail-Adresse im Adressbuch %3$s",
diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index 56a61a1bdd..8dedbd7b12 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "E-Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Sie erreichen die Grenze Ihres Postfach-Kontingents für {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Sie nutzen derzeit {percentage} Ihres Postfachspeichers. Bitte schaffen Sie etwas Platz, indem Sie nicht benötigte E-Mails löschen.",
+ "{account_email} has been delegated to you" : "{account_email} wurde an Sie delegiert",
+ "{user} delegated {account} to you" : "{user} hat {account} an Sie delegiert",
+ "{account_email} is no longer delegated to you" : "{account_email} ist nicht mehr an Sie delegiert",
+ "{user} revoked delegation for {account}" : "{user} hat die Delegation von {account} widerrufen",
"Mail Application" : "E-Mail Anwendung",
"Mails" : "E-Mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "E-Mail-Adresse des Absenders %1$s ist nicht im Adressbuch, aber der Name des Absenders %2$s ist mit der folgender E-Mail-Adresse im Adressbuch %3$s",
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index cf774af40c..28c596eb20 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -12,6 +12,10 @@
"Mail" : "E-Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Sie erreichen die Grenze Ihres Postfach-Kontingents für {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Sie nutzen derzeit {percentage} Ihres Postfachspeichers. Bitte schaffen Sie etwas Platz, indem Sie nicht benötigte E-Mails löschen.",
+ "{account_email} has been delegated to you" : "{account_email} wurde an Sie delegiert",
+ "{user} delegated {account} to you" : "{user} hat {account} an Sie delegiert",
+ "{account_email} is no longer delegated to you" : "{account_email} ist nicht mehr an Sie delegiert",
+ "{user} revoked delegation for {account}" : "{user} hat die Delegation von {account} widerrufen",
"Mail Application" : "E-Mail Anwendung",
"Mails" : "E-Mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "E-Mail-Adresse des Absenders %1$s ist nicht im Adressbuch, aber der Name des Absenders %2$s ist mit der folgender E-Mail-Adresse im Adressbuch %3$s",
diff --git a/l10n/fr.js b/l10n/fr.js
index 1d3ac44134..5efd923f5e 100644
--- a/l10n/fr.js
+++ b/l10n/fr.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Vous atteignez la limite de quota de votre boîte mail pour {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Vous utilisez actuellement {pourcentage} de l'espace de stockage de votre boîte aux lettres. Veuillez faire de la place en supprimant les e-mails inutiles.",
+ "{account_email} has been delegated to you" : "{account_email} vous a été délégué",
+ "{user} delegated {account} to you" : "{user} vous a délégué {account}",
+ "{account_email} is no longer delegated to you" : "{account_email} ne vous est plus délégué",
+ "{user} revoked delegation for {account}" : "{user} a révoqué la délégation de {account}",
"Mail Application" : "Application Mail",
"Mails" : "E-mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "L'e-mail de l'expéditeur %1$s n'est pas dans le carnet d'adresses, mais le nom de l'expéditeur : %2$s est dans le carnet d'adresse avec l'adresse mail suivante : %3$s",
@@ -135,6 +139,7 @@ OC.L10N.register(
"Mail settings" : "Paramètres de Mail",
"General" : "Général",
"Set as default mail app" : "Définir comme application de messagerie par défaut",
+ "{email} (delegated)" : "{email} (délégué)",
"Add mail account" : "Ajouter un compte mail",
"Appearance" : "Apparence",
"Show all messages in thread" : "Afficher tous les messages du fil de discussion",
@@ -253,7 +258,21 @@ OC.L10N.register(
"Expand composer" : "Déplier la fenêtre de composition",
"Close composer" : "Fermer la fenêtre de composition",
"Confirm" : "Confirmer",
+ "Delegate access" : "Déléguer l'accès",
"Revoke" : "Révoquer",
+ "{userId} will no longer be able to act on your behalf" : "{userId} ne pourra plus agir en votre nom",
+ "Could not fetch delegates" : "Impossible de récupérer les délégués",
+ "Delegated access to {userId}" : "Déléguer l'accès à {userId}",
+ "Could not delegate access" : "Impossible de déléguer l'accès",
+ "Revoked access for {userId}" : "Accès révoqué pour {userId}",
+ "Could not revoke delegation" : "Impossible de révoquer la délégation",
+ "Delegation" : "Délégation",
+ "Allow users to send, receive, and delete mail on your behalf" : "Autoriser des utilisateurs à envoyer, recevoir et supprimer des e-mails en votre nom",
+ "Revoke access" : "Révoquer l'accès",
+ "Add delegate" : "Ajouter un délégué",
+ "Select a user" : "Sélectionner un utilisateur",
+ "They will be able to send, receive, and delete mail on your behalf" : "Ils pourront envoyer, recevoir et supprimer des e-mails en votre nom",
+ "Revoke access?" : "Révoquer l'accès ?",
"Tag: {name} deleted" : "Étiquette : {name} supprimée",
"An error occurred, unable to delete the tag." : "Une erreur est survenue, impossible de supprimer l'étiquette.",
"The tag will be deleted from all messages." : "L'étiquette sera supprimée de tous les messages.",
@@ -381,7 +400,7 @@ OC.L10N.register(
"Indexing your messages. This can take a bit longer for larger folders." : "Indexation de vos messages. Cela peut prendre un peu plus de temps pour les dossiers volumineux.",
"Choose target folder" : "Sélectionner le dossier cible",
"No more submailboxes in here" : "Plus aucun sous-dossier ici",
- "Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "Les messages que vos avez marqués comme favoris seront affichés en haut des dossiers. Vous pouvez désactiver ce comportement dans les paramètres de l'application",
+ "Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "Les messages que vous avez marqués comme favoris seront affichés en haut des dossiers. Vous pouvez désactiver ce comportement dans les paramètres de l'application",
"Favorites" : "Favoris",
"Load more favorites" : "Charger plus de favoris",
"Follow up" : "Suivre",
@@ -445,8 +464,10 @@ OC.L10N.register(
"Remove account" : "Retirer le compte",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Le compte pour {email} et les données de messagerie mises en cache seront supprimés de Nextcloud, mais pas de votre fournisseur de messagerie.",
"Remove {email}" : "Supprimer {email}",
+ "could not delete account" : "impossible de supprimer le compte",
"Provisioned account is disabled" : "Le compte fourni est désactivé",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Veuillez vous connecter en utilisant un mot de passe pour activer ce compte. La session actuelle utilise une authentification sans mot de passe, c'est-à-dire via SSO ou WebAuthn.",
+ "Delegate account" : "Déléguer le compte",
"Show only subscribed folders" : "Afficher uniquement les dossiers suivis",
"Add folder" : "Ajouter un dossier",
"Folder name" : "Nom du dossier",
@@ -620,6 +641,8 @@ OC.L10N.register(
"Mark as unfavorite" : "Ne plus marquer comme favori",
"Mark as favorite" : "Marquer comme favori",
"To:" : "Au :",
+ "Cc:" : "Cc:",
+ "Bcc:" : "Bcc:",
"Unsubscribe via link" : "Se désabonner via un lien",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Le désabonnement stoppera la réception des messages de la liste de diffusion {sender}",
"Send unsubscribe email" : "Envoyer le mail de désinscription",
diff --git a/l10n/fr.json b/l10n/fr.json
index ed4c50c434..2da69fb39a 100644
--- a/l10n/fr.json
+++ b/l10n/fr.json
@@ -12,6 +12,10 @@
"Mail" : "Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Vous atteignez la limite de quota de votre boîte mail pour {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Vous utilisez actuellement {pourcentage} de l'espace de stockage de votre boîte aux lettres. Veuillez faire de la place en supprimant les e-mails inutiles.",
+ "{account_email} has been delegated to you" : "{account_email} vous a été délégué",
+ "{user} delegated {account} to you" : "{user} vous a délégué {account}",
+ "{account_email} is no longer delegated to you" : "{account_email} ne vous est plus délégué",
+ "{user} revoked delegation for {account}" : "{user} a révoqué la délégation de {account}",
"Mail Application" : "Application Mail",
"Mails" : "E-mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "L'e-mail de l'expéditeur %1$s n'est pas dans le carnet d'adresses, mais le nom de l'expéditeur : %2$s est dans le carnet d'adresse avec l'adresse mail suivante : %3$s",
@@ -133,6 +137,7 @@
"Mail settings" : "Paramètres de Mail",
"General" : "Général",
"Set as default mail app" : "Définir comme application de messagerie par défaut",
+ "{email} (delegated)" : "{email} (délégué)",
"Add mail account" : "Ajouter un compte mail",
"Appearance" : "Apparence",
"Show all messages in thread" : "Afficher tous les messages du fil de discussion",
@@ -251,7 +256,21 @@
"Expand composer" : "Déplier la fenêtre de composition",
"Close composer" : "Fermer la fenêtre de composition",
"Confirm" : "Confirmer",
+ "Delegate access" : "Déléguer l'accès",
"Revoke" : "Révoquer",
+ "{userId} will no longer be able to act on your behalf" : "{userId} ne pourra plus agir en votre nom",
+ "Could not fetch delegates" : "Impossible de récupérer les délégués",
+ "Delegated access to {userId}" : "Déléguer l'accès à {userId}",
+ "Could not delegate access" : "Impossible de déléguer l'accès",
+ "Revoked access for {userId}" : "Accès révoqué pour {userId}",
+ "Could not revoke delegation" : "Impossible de révoquer la délégation",
+ "Delegation" : "Délégation",
+ "Allow users to send, receive, and delete mail on your behalf" : "Autoriser des utilisateurs à envoyer, recevoir et supprimer des e-mails en votre nom",
+ "Revoke access" : "Révoquer l'accès",
+ "Add delegate" : "Ajouter un délégué",
+ "Select a user" : "Sélectionner un utilisateur",
+ "They will be able to send, receive, and delete mail on your behalf" : "Ils pourront envoyer, recevoir et supprimer des e-mails en votre nom",
+ "Revoke access?" : "Révoquer l'accès ?",
"Tag: {name} deleted" : "Étiquette : {name} supprimée",
"An error occurred, unable to delete the tag." : "Une erreur est survenue, impossible de supprimer l'étiquette.",
"The tag will be deleted from all messages." : "L'étiquette sera supprimée de tous les messages.",
@@ -379,7 +398,7 @@
"Indexing your messages. This can take a bit longer for larger folders." : "Indexation de vos messages. Cela peut prendre un peu plus de temps pour les dossiers volumineux.",
"Choose target folder" : "Sélectionner le dossier cible",
"No more submailboxes in here" : "Plus aucun sous-dossier ici",
- "Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "Les messages que vos avez marqués comme favoris seront affichés en haut des dossiers. Vous pouvez désactiver ce comportement dans les paramètres de l'application",
+ "Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "Les messages que vous avez marqués comme favoris seront affichés en haut des dossiers. Vous pouvez désactiver ce comportement dans les paramètres de l'application",
"Favorites" : "Favoris",
"Load more favorites" : "Charger plus de favoris",
"Follow up" : "Suivre",
@@ -443,8 +462,10 @@
"Remove account" : "Retirer le compte",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Le compte pour {email} et les données de messagerie mises en cache seront supprimés de Nextcloud, mais pas de votre fournisseur de messagerie.",
"Remove {email}" : "Supprimer {email}",
+ "could not delete account" : "impossible de supprimer le compte",
"Provisioned account is disabled" : "Le compte fourni est désactivé",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Veuillez vous connecter en utilisant un mot de passe pour activer ce compte. La session actuelle utilise une authentification sans mot de passe, c'est-à-dire via SSO ou WebAuthn.",
+ "Delegate account" : "Déléguer le compte",
"Show only subscribed folders" : "Afficher uniquement les dossiers suivis",
"Add folder" : "Ajouter un dossier",
"Folder name" : "Nom du dossier",
@@ -618,6 +639,8 @@
"Mark as unfavorite" : "Ne plus marquer comme favori",
"Mark as favorite" : "Marquer comme favori",
"To:" : "Au :",
+ "Cc:" : "Cc:",
+ "Bcc:" : "Bcc:",
"Unsubscribe via link" : "Se désabonner via un lien",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Le désabonnement stoppera la réception des messages de la liste de diffusion {sender}",
"Send unsubscribe email" : "Envoyer le mail de désinscription",
diff --git a/l10n/ga.js b/l10n/ga.js
index 0582fc15e5..2821fa6d6a 100644
--- a/l10n/ga.js
+++ b/l10n/ga.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "Post",
"You are reaching your mailbox quota limit for {account_email}" : "Tá teorainn chuóta do bhosca poist le haghaidh {account_email} sroichte agat",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Tá {percentage} de do stór bosca ríomhphoist in úsáid agat faoi láthair. Déan roinnt spáis trí ríomhphoist nach bhfuil ag teastáil a scriosadh le do thoil.",
+ "{account_email} has been delegated to you" : "Tá {account_email} tarmligthe chugat",
+ "{user} delegated {account} to you" : "{user} thug {account} duit",
+ "{account_email} is no longer delegated to you" : "Níl {account_email} tarmligthe chugat a thuilleadh",
+ "{user} revoked delegation for {account}" : "Chuir {user} tarmligean ar ceal do {account}",
"Mail Application" : "Feidhmchlár Ríomhphoist",
"Mails" : "Ríomhphoist",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Ríomhphost an tseoltóra: níl %1$s sa leabhar seoltaí, ach tá ainm an tseoltóra: %2$s sa leabhar seoltaí leis an ríomhphost seo a leanas: %3$s",
diff --git a/l10n/ga.json b/l10n/ga.json
index 5060b634b3..ccdc28a6d3 100644
--- a/l10n/ga.json
+++ b/l10n/ga.json
@@ -12,6 +12,10 @@
"Mail" : "Post",
"You are reaching your mailbox quota limit for {account_email}" : "Tá teorainn chuóta do bhosca poist le haghaidh {account_email} sroichte agat",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Tá {percentage} de do stór bosca ríomhphoist in úsáid agat faoi láthair. Déan roinnt spáis trí ríomhphoist nach bhfuil ag teastáil a scriosadh le do thoil.",
+ "{account_email} has been delegated to you" : "Tá {account_email} tarmligthe chugat",
+ "{user} delegated {account} to you" : "{user} thug {account} duit",
+ "{account_email} is no longer delegated to you" : "Níl {account_email} tarmligthe chugat a thuilleadh",
+ "{user} revoked delegation for {account}" : "Chuir {user} tarmligean ar ceal do {account}",
"Mail Application" : "Feidhmchlár Ríomhphoist",
"Mails" : "Ríomhphoist",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Ríomhphost an tseoltóra: níl %1$s sa leabhar seoltaí, ach tá ainm an tseoltóra: %2$s sa leabhar seoltaí leis an ríomhphost seo a leanas: %3$s",
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index be010e9abc..95a1cee804 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "E-Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Você está atingindo seu limite de cota de caixa de correio para {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "No momento, você está usando {percentage} do armazenamento da sua caixa de correio. Por favor, libere algum espaço excluindo e-mails desnecessários.",
+ "{account_email} has been delegated to you" : "{account_email} foi delegado a você",
+ "{user} delegated {account} to you" : "{user} delegou {account} a você",
+ "{account_email} is no longer delegated to you" : "{account_email} não está mais delegado a você",
+ "{user} revoked delegation for {account}" : "{user} revogou a delegação para {account}",
"Mail Application" : "Aplicativo de E-Mails",
"Mails" : "E-Mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "E-mail do remetente: %1$s não está no catálogo de endereços, mas o nome do remetente: %2$s está no catálogo de endereços com o seguinte e-mail: %3$s",
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index 4c61eec5d5..b7019d09f7 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -12,6 +12,10 @@
"Mail" : "E-Mail",
"You are reaching your mailbox quota limit for {account_email}" : "Você está atingindo seu limite de cota de caixa de correio para {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "No momento, você está usando {percentage} do armazenamento da sua caixa de correio. Por favor, libere algum espaço excluindo e-mails desnecessários.",
+ "{account_email} has been delegated to you" : "{account_email} foi delegado a você",
+ "{user} delegated {account} to you" : "{user} delegou {account} a você",
+ "{account_email} is no longer delegated to you" : "{account_email} não está mais delegado a você",
+ "{user} revoked delegation for {account}" : "{user} revogou a delegação para {account}",
"Mail Application" : "Aplicativo de E-Mails",
"Mails" : "E-Mails",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "E-mail do remetente: %1$s não está no catálogo de endereços, mas o nome do remetente: %2$s está no catálogo de endereços com o seguinte e-mail: %3$s",
From 0e81d91f3b4f2a86a2fa80e08f63907f104978f8 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Thu, 21 May 2026 09:42:10 +0200
Subject: [PATCH 047/228] fix(ui): sub-mailbox drops blocked by parent cascade
Two bugs in the droppable-mailbox directive:
1. [droppable-mailbox="disabled"] applied pointer-events:none and opacity:.3
to the whole element, cascading into sub-mailboxes rendered in the slot
and making them unreachable as drop targets.
2. With pointer-events:none unscoped, drag events reached the wrapper div of
disabled mailboxes; onDragLeave unconditionally called setStatus('enabled'),
visually re-enabling them mid-drag.
Scope the disabled styling to > div > a (matching the dragover state) and
add canBeDropped() guards to onDragOver/onDragLeave/onDrop.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.../drag-and-drop/droppable-mailbox/droppable-mailbox.js | 6 +++---
src/directives/drag-and-drop/styles/droppable-mailbox.scss | 6 ++++--
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/directives/drag-and-drop/droppable-mailbox/droppable-mailbox.js b/src/directives/drag-and-drop/droppable-mailbox/droppable-mailbox.js
index 792b531e89..d0e1017f1d 100644
--- a/src/directives/drag-and-drop/droppable-mailbox/droppable-mailbox.js
+++ b/src/directives/drag-and-drop/droppable-mailbox/droppable-mailbox.js
@@ -83,7 +83,7 @@ export class DroppableMailbox {
}
onDragOver(event) {
- if (!this.isCurrentlyDragging) {
+ if (!this.isCurrentlyDragging || !this.canBeDropped()) {
return
}
@@ -102,7 +102,7 @@ export class DroppableMailbox {
}
onDragLeave(event) {
- if (!this.isCurrentlyDragging) {
+ if (!this.isCurrentlyDragging || !this.canBeDropped()) {
return
}
@@ -111,7 +111,7 @@ export class DroppableMailbox {
}
async onDrop(event) {
- if (!this.isCurrentlyDragging) {
+ if (!this.isCurrentlyDragging || !this.canBeDropped()) {
return
}
diff --git a/src/directives/drag-and-drop/styles/droppable-mailbox.scss b/src/directives/drag-and-drop/styles/droppable-mailbox.scss
index c698ee3132..2d016331c7 100644
--- a/src/directives/drag-and-drop/styles/droppable-mailbox.scss
+++ b/src/directives/drag-and-drop/styles/droppable-mailbox.scss
@@ -41,8 +41,10 @@
}
[droppable-mailbox="disabled"] {
- pointer-events: none;
- opacity: .3;
+ > div > a {
+ pointer-events: none;
+ opacity: .3;
+ }
}
[droppable-mailbox="dragover"] {
From fba580735f9f0b89269b7885adb00a264c4ee397 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Fri, 22 May 2026 01:41:41 +0000
Subject: [PATCH 048/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/ar.js | 2 +-
l10n/ar.json | 2 +-
l10n/bg.js | 2 +-
l10n/bg.json | 2 +-
l10n/ca.js | 2 +-
l10n/ca.json | 2 +-
l10n/cs.js | 2 +-
l10n/cs.json | 2 +-
l10n/da.js | 2 +-
l10n/da.json | 2 +-
l10n/de.js | 2 +-
l10n/de.json | 2 +-
l10n/de_DE.js | 2 +-
l10n/de_DE.json | 2 +-
l10n/el.js | 2 +-
l10n/el.json | 2 +-
l10n/en_GB.js | 2 +-
l10n/en_GB.json | 2 +-
l10n/es.js | 2 +-
l10n/es.json | 2 +-
l10n/es_EC.js | 2 +-
l10n/es_EC.json | 2 +-
l10n/et_EE.js | 2 +-
l10n/et_EE.json | 2 +-
l10n/eu.js | 2 +-
l10n/eu.json | 2 +-
l10n/fa.js | 2 +-
l10n/fa.json | 2 +-
l10n/fi.js | 2 +-
l10n/fi.json | 2 +-
l10n/fr.js | 2 +-
l10n/fr.json | 2 +-
l10n/ga.js | 2 +-
l10n/ga.json | 2 +-
l10n/gl.js | 2 +-
l10n/gl.json | 2 +-
l10n/hr.js | 2 +-
l10n/hr.json | 2 +-
l10n/hu.js | 2 +-
l10n/hu.json | 2 +-
l10n/id.js | 2 +-
l10n/id.json | 2 +-
l10n/is.js | 2 +-
l10n/is.json | 2 +-
l10n/it.js | 2 +-
l10n/it.json | 2 +-
l10n/ja.js | 2 +-
l10n/ja.json | 2 +-
l10n/ka.js | 2 +-
l10n/ka.json | 2 +-
l10n/ko.js | 2 +-
l10n/ko.json | 2 +-
l10n/lo.js | 2 +-
l10n/lo.json | 2 +-
l10n/lt_LT.js | 2 +-
l10n/lt_LT.json | 2 +-
l10n/lv.js | 2 +-
l10n/lv.json | 2 +-
l10n/mk.js | 2 +-
l10n/mk.json | 2 +-
l10n/mn.js | 2 +-
l10n/mn.json | 2 +-
l10n/nb.js | 2 +-
l10n/nb.json | 2 +-
l10n/nl.js | 2 +-
l10n/nl.json | 2 +-
l10n/pl.js | 2 +-
l10n/pl.json | 2 +-
l10n/pt_BR.js | 2 +-
l10n/pt_BR.json | 2 +-
l10n/ru.js | 2 +-
l10n/ru.json | 2 +-
l10n/sk.js | 2 +-
l10n/sk.json | 2 +-
l10n/sl.js | 6 +++---
l10n/sl.json | 6 +++---
l10n/sr.js | 2 +-
l10n/sr.json | 2 +-
l10n/sv.js | 2 +-
l10n/sv.json | 2 +-
l10n/tr.js | 50 ++++++++++++++++++++++++++++++++++++++-----------
l10n/tr.json | 50 ++++++++++++++++++++++++++++++++++++++-----------
l10n/ug.js | 2 +-
l10n/ug.json | 2 +-
l10n/uk.js | 2 +-
l10n/uk.json | 2 +-
l10n/zh_CN.js | 2 +-
l10n/zh_CN.json | 2 +-
l10n/zh_HK.js | 6 +++++-
l10n/zh_HK.json | 6 +++++-
l10n/zh_TW.js | 6 +++++-
l10n/zh_TW.json | 6 +++++-
92 files changed, 188 insertions(+), 116 deletions(-)
diff --git a/l10n/ar.js b/l10n/ar.js
index 64976130f3..32e3af19e0 100644
--- a/l10n/ar.js
+++ b/l10n/ar.js
@@ -667,6 +667,7 @@ OC.L10N.register(
"Certificate imported successfully" : "تمّ بنجاح استيراد الشهادة",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "فشل استيراد الشهادة. يرجى التأكد من أن المفتاح الخاص يطابق الشهادة وأنه غير محمي بعبارة مرور.",
"Failed to import the certificate" : "فشل استيراد الشهادة",
+ "Import S/MIME certificate" : "إستيراد شهادة S/MIME ",
"S/MIME certificates" : "شهادات S/MIME",
"Certificate name" : "اسم الشهادة",
"E-mail address" : "عنوان البريد الالكتروني",
@@ -674,7 +675,6 @@ OC.L10N.register(
"Delete certificate" : "حذف الشهادة",
"No certificate imported yet" : "لم يتمّ استيراد أي شهادةٍ حتى الآن",
"Import certificate" : "إستيراد شهادة",
- "Import S/MIME certificate" : "إستيراد شهادة S/MIME ",
"PKCS #12 Certificate" : "شهادة PKCS ـ #12 ",
"PEM Certificate" : "شهادة PEM ",
"Certificate" : "الشهادة",
diff --git a/l10n/ar.json b/l10n/ar.json
index af0f86b7fd..64347d55e0 100644
--- a/l10n/ar.json
+++ b/l10n/ar.json
@@ -665,6 +665,7 @@
"Certificate imported successfully" : "تمّ بنجاح استيراد الشهادة",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "فشل استيراد الشهادة. يرجى التأكد من أن المفتاح الخاص يطابق الشهادة وأنه غير محمي بعبارة مرور.",
"Failed to import the certificate" : "فشل استيراد الشهادة",
+ "Import S/MIME certificate" : "إستيراد شهادة S/MIME ",
"S/MIME certificates" : "شهادات S/MIME",
"Certificate name" : "اسم الشهادة",
"E-mail address" : "عنوان البريد الالكتروني",
@@ -672,7 +673,6 @@
"Delete certificate" : "حذف الشهادة",
"No certificate imported yet" : "لم يتمّ استيراد أي شهادةٍ حتى الآن",
"Import certificate" : "إستيراد شهادة",
- "Import S/MIME certificate" : "إستيراد شهادة S/MIME ",
"PKCS #12 Certificate" : "شهادة PKCS ـ #12 ",
"PEM Certificate" : "شهادة PEM ",
"Certificate" : "الشهادة",
diff --git a/l10n/bg.js b/l10n/bg.js
index 3eafd0b9f6..c7487a63ae 100644
--- a/l10n/bg.js
+++ b/l10n/bg.js
@@ -505,6 +505,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Успешно импортиране на сертификата",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Неуспешно импортиране на сертификата. Моля, уверете се, че частният ключ съответства на сертификата и не е защитен с парола.",
"Failed to import the certificate" : "Неуспешно импортиране на сертификата",
+ "Import S/MIME certificate" : "Импортиране на S/MIME сертификат",
"S/MIME certificates" : "S/MIME сертификати",
"Certificate name" : "Име на сертификата",
"E-mail address" : "Имейл адрес",
@@ -512,7 +513,6 @@ OC.L10N.register(
"Delete certificate" : "Изтриване на сертификат",
"No certificate imported yet" : "Все още няма импортиран сертификат",
"Import certificate" : "Импортиране /внасяне/ на сертификат",
- "Import S/MIME certificate" : "Импортиране на S/MIME сертификат",
"PKCS #12 Certificate" : "Сертификат PKCS #12",
"PEM Certificate" : "Сертификат PEM",
"Certificate" : "Сертификат",
diff --git a/l10n/bg.json b/l10n/bg.json
index ebebb16e2c..b3a9ab5b1e 100644
--- a/l10n/bg.json
+++ b/l10n/bg.json
@@ -503,6 +503,7 @@
"Certificate imported successfully" : "Успешно импортиране на сертификата",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Неуспешно импортиране на сертификата. Моля, уверете се, че частният ключ съответства на сертификата и не е защитен с парола.",
"Failed to import the certificate" : "Неуспешно импортиране на сертификата",
+ "Import S/MIME certificate" : "Импортиране на S/MIME сертификат",
"S/MIME certificates" : "S/MIME сертификати",
"Certificate name" : "Име на сертификата",
"E-mail address" : "Имейл адрес",
@@ -510,7 +511,6 @@
"Delete certificate" : "Изтриване на сертификат",
"No certificate imported yet" : "Все още няма импортиран сертификат",
"Import certificate" : "Импортиране /внасяне/ на сертификат",
- "Import S/MIME certificate" : "Импортиране на S/MIME сертификат",
"PKCS #12 Certificate" : "Сертификат PKCS #12",
"PEM Certificate" : "Сертификат PEM",
"Certificate" : "Сертификат",
diff --git a/l10n/ca.js b/l10n/ca.js
index 7f738c8917..a01514870e 100644
--- a/l10n/ca.js
+++ b/l10n/ca.js
@@ -670,6 +670,7 @@ OC.L10N.register(
"Certificate imported successfully" : "El certificat s'ha importat correctament",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "No s'ha pogut importar el certificat. Assegureu-vos que la clau privada coincideixi amb el certificat i que no estigui protegida per una frase de contrasenya.",
"Failed to import the certificate" : "No s'ha pogut importar el certificat",
+ "Import S/MIME certificate" : "Importa el certificat S/MIME",
"S/MIME certificates" : "Certificats S/MIME",
"Certificate name" : "Nom del certificat",
"E-mail address" : "Adreça de correu electrònic",
@@ -677,7 +678,6 @@ OC.L10N.register(
"Delete certificate" : "Suprimeix el certificat",
"No certificate imported yet" : "Encara no s'ha importat cap certificat",
"Import certificate" : "Importa el certificat",
- "Import S/MIME certificate" : "Importa el certificat S/MIME",
"PKCS #12 Certificate" : "Certificat PKCS #12",
"PEM Certificate" : "Certificat PEM",
"Certificate" : "Certificat",
diff --git a/l10n/ca.json b/l10n/ca.json
index dd6a9189ee..be6d4929fd 100644
--- a/l10n/ca.json
+++ b/l10n/ca.json
@@ -668,6 +668,7 @@
"Certificate imported successfully" : "El certificat s'ha importat correctament",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "No s'ha pogut importar el certificat. Assegureu-vos que la clau privada coincideixi amb el certificat i que no estigui protegida per una frase de contrasenya.",
"Failed to import the certificate" : "No s'ha pogut importar el certificat",
+ "Import S/MIME certificate" : "Importa el certificat S/MIME",
"S/MIME certificates" : "Certificats S/MIME",
"Certificate name" : "Nom del certificat",
"E-mail address" : "Adreça de correu electrònic",
@@ -675,7 +676,6 @@
"Delete certificate" : "Suprimeix el certificat",
"No certificate imported yet" : "Encara no s'ha importat cap certificat",
"Import certificate" : "Importa el certificat",
- "Import S/MIME certificate" : "Importa el certificat S/MIME",
"PKCS #12 Certificate" : "Certificat PKCS #12",
"PEM Certificate" : "Certificat PEM",
"Certificate" : "Certificat",
diff --git a/l10n/cs.js b/l10n/cs.js
index 19f6dc7be7..594f4f1f4c 100644
--- a/l10n/cs.js
+++ b/l10n/cs.js
@@ -818,6 +818,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certifikát úspěšně naimportován",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Certifikát se nepodařilo naimportovat. Ověřte, že se soukromý klíč shoduje s certifikátem a že není chráněn heslovou frází.",
"Failed to import the certificate" : "Certifikát se nepodařilo naimportovat",
+ "Import S/MIME certificate" : "Naimportovat S/MIME certifikát",
"S/MIME certificates" : "S/MIME certifikáty",
"Certificate name" : "Název certifikátu",
"E-mail address" : "E-mailová adresa",
@@ -825,7 +826,6 @@ OC.L10N.register(
"Delete certificate" : "Smazat certifikát",
"No certificate imported yet" : "Zatím nenaimportovány žádné certifikáty",
"Import certificate" : "Naimportovat certifikát",
- "Import S/MIME certificate" : "Naimportovat S/MIME certifikát",
"PKCS #12 Certificate" : "PKCS #12 certifkát",
"PEM Certificate" : "PEM certifikát",
"Certificate" : "Certifikát",
diff --git a/l10n/cs.json b/l10n/cs.json
index e55d26b08d..4849f66217 100644
--- a/l10n/cs.json
+++ b/l10n/cs.json
@@ -816,6 +816,7 @@
"Certificate imported successfully" : "Certifikát úspěšně naimportován",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Certifikát se nepodařilo naimportovat. Ověřte, že se soukromý klíč shoduje s certifikátem a že není chráněn heslovou frází.",
"Failed to import the certificate" : "Certifikát se nepodařilo naimportovat",
+ "Import S/MIME certificate" : "Naimportovat S/MIME certifikát",
"S/MIME certificates" : "S/MIME certifikáty",
"Certificate name" : "Název certifikátu",
"E-mail address" : "E-mailová adresa",
@@ -823,7 +824,6 @@
"Delete certificate" : "Smazat certifikát",
"No certificate imported yet" : "Zatím nenaimportovány žádné certifikáty",
"Import certificate" : "Naimportovat certifikát",
- "Import S/MIME certificate" : "Naimportovat S/MIME certifikát",
"PKCS #12 Certificate" : "PKCS #12 certifkát",
"PEM Certificate" : "PEM certifikát",
"Certificate" : "Certifikát",
diff --git a/l10n/da.js b/l10n/da.js
index 5be3d62f6a..81dfb9acd3 100644
--- a/l10n/da.js
+++ b/l10n/da.js
@@ -541,6 +541,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certifikatet blev importeret",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Kunne ikke importere certifikatet. Sørg for, at den private nøgle matcher certifikatet og ikke er beskyttet af en kode.",
"Failed to import the certificate" : "Kunne ikke importere certifikatet",
+ "Import S/MIME certificate" : "Importér S/MIME-certifikat",
"S/MIME certificates" : "S/MIME certifikater",
"Certificate name" : "Certifikatnavn",
"E-mail address" : "E-mail adresse",
@@ -548,7 +549,6 @@ OC.L10N.register(
"Delete certificate" : "Slet certifikat",
"No certificate imported yet" : "Intet certifikat importeret endnu",
"Import certificate" : "Importér certifikat",
- "Import S/MIME certificate" : "Importér S/MIME-certifikat",
"PKCS #12 Certificate" : "PKCS #12 Certifikat",
"PEM Certificate" : "PEM Certifikat",
"Certificate" : "Certifikat",
diff --git a/l10n/da.json b/l10n/da.json
index 262589fde3..8ed33a5003 100644
--- a/l10n/da.json
+++ b/l10n/da.json
@@ -539,6 +539,7 @@
"Certificate imported successfully" : "Certifikatet blev importeret",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Kunne ikke importere certifikatet. Sørg for, at den private nøgle matcher certifikatet og ikke er beskyttet af en kode.",
"Failed to import the certificate" : "Kunne ikke importere certifikatet",
+ "Import S/MIME certificate" : "Importér S/MIME-certifikat",
"S/MIME certificates" : "S/MIME certifikater",
"Certificate name" : "Certifikatnavn",
"E-mail address" : "E-mail adresse",
@@ -546,7 +547,6 @@
"Delete certificate" : "Slet certifikat",
"No certificate imported yet" : "Intet certifikat importeret endnu",
"Import certificate" : "Importér certifikat",
- "Import S/MIME certificate" : "Importér S/MIME-certifikat",
"PKCS #12 Certificate" : "PKCS #12 Certifikat",
"PEM Certificate" : "PEM Certifikat",
"Certificate" : "Certifikat",
diff --git a/l10n/de.js b/l10n/de.js
index 62ef267ff3..c35acf7256 100644
--- a/l10n/de.js
+++ b/l10n/de.js
@@ -846,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Zertifikat importiert",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Das Zertifikat konnte nicht importiert werden. Bitte sicherstellen, dass der private Schlüssel zum Zertifikat passt und nicht durch eine Passphrase geschützt ist.",
"Failed to import the certificate" : "Das Zertifikat konnte nicht importiert werden",
+ "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"S/MIME certificates" : "S/MIME Zertifikate",
"Certificate name" : "Zertifikatsname",
"E-mail address" : "E-Mail-Adresse",
@@ -853,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "Zertifikat löschen",
"No certificate imported yet" : "Bislang wurde kein Zertifikat importiert",
"Import certificate" : "Zertifikat importieren",
- "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"PKCS #12 Certificate" : "PKCS #12-Zertifikat",
"PEM Certificate" : "PEM-Zertifikat",
"Certificate" : "Zertifikat",
diff --git a/l10n/de.json b/l10n/de.json
index 4fbca88922..cf8d826504 100644
--- a/l10n/de.json
+++ b/l10n/de.json
@@ -844,6 +844,7 @@
"Certificate imported successfully" : "Zertifikat importiert",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Das Zertifikat konnte nicht importiert werden. Bitte sicherstellen, dass der private Schlüssel zum Zertifikat passt und nicht durch eine Passphrase geschützt ist.",
"Failed to import the certificate" : "Das Zertifikat konnte nicht importiert werden",
+ "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"S/MIME certificates" : "S/MIME Zertifikate",
"Certificate name" : "Zertifikatsname",
"E-mail address" : "E-Mail-Adresse",
@@ -851,7 +852,6 @@
"Delete certificate" : "Zertifikat löschen",
"No certificate imported yet" : "Bislang wurde kein Zertifikat importiert",
"Import certificate" : "Zertifikat importieren",
- "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"PKCS #12 Certificate" : "PKCS #12-Zertifikat",
"PEM Certificate" : "PEM-Zertifikat",
"Certificate" : "Zertifikat",
diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index 8dedbd7b12..1fc3456604 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -846,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Zertifikat importiert",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Das Zertifikat konnte nicht importiert werden. Bitte stellen Sie sicher, dass der private Schlüssel zum Zertifikat passt und nicht durch eine Passphrase geschützt ist.",
"Failed to import the certificate" : "Das Zertifikat konnte nicht importiert werden",
+ "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"S/MIME certificates" : "S/MIME-Zertifikate",
"Certificate name" : "Zertifikatsname",
"E-mail address" : "E-Mail-Adresse",
@@ -853,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "Zertifikat löschen",
"No certificate imported yet" : "Bislang wurde kein Zertifikat importiert",
"Import certificate" : "Zertifikat importieren",
- "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"PKCS #12 Certificate" : "PKCS #12-Zertifikat",
"PEM Certificate" : "PEM-Zertifikat",
"Certificate" : "Zertifikat",
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index 28c596eb20..cf2dcd885f 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -844,6 +844,7 @@
"Certificate imported successfully" : "Zertifikat importiert",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Das Zertifikat konnte nicht importiert werden. Bitte stellen Sie sicher, dass der private Schlüssel zum Zertifikat passt und nicht durch eine Passphrase geschützt ist.",
"Failed to import the certificate" : "Das Zertifikat konnte nicht importiert werden",
+ "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"S/MIME certificates" : "S/MIME-Zertifikate",
"Certificate name" : "Zertifikatsname",
"E-mail address" : "E-Mail-Adresse",
@@ -851,7 +852,6 @@
"Delete certificate" : "Zertifikat löschen",
"No certificate imported yet" : "Bislang wurde kein Zertifikat importiert",
"Import certificate" : "Zertifikat importieren",
- "Import S/MIME certificate" : "S/MIME-Zertifikat importieren",
"PKCS #12 Certificate" : "PKCS #12-Zertifikat",
"PEM Certificate" : "PEM-Zertifikat",
"Certificate" : "Zertifikat",
diff --git a/l10n/el.js b/l10n/el.js
index 5ba84d308c..edef2bae05 100644
--- a/l10n/el.js
+++ b/l10n/el.js
@@ -764,6 +764,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Το πιστοποιητικό εισήχθη με επιτυχία",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Αποτυχία εισαγωγής του πιστοποιητικού. Βεβαιωθείτε ότι το ιδιωτικό κλειδί ταιριάζει με το πιστοποιητικό και δεν προστατεύεται από φράση πρόσβασης.",
"Failed to import the certificate" : "Αποτυχία εισαγωγής του πιστοποιητικού",
+ "Import S/MIME certificate" : "Εισαγωγή πιστοποιητικού S/MIME",
"S/MIME certificates" : "Πιστοποιητικά S/MIME",
"Certificate name" : "Όνομα πιστοποιητικού",
"E-mail address" : "E-mail διεύθυνση",
@@ -771,7 +772,6 @@ OC.L10N.register(
"Delete certificate" : "Διαγραφή πιστοποιητικού",
"No certificate imported yet" : "Δεν έχει εισαχθεί ακόμα πιστοποιητικό",
"Import certificate" : "Εισαγωγή πιστοποιητικού",
- "Import S/MIME certificate" : "Εισαγωγή πιστοποιητικού S/MIME",
"PKCS #12 Certificate" : "Πιστοποιητικό PKCS #12",
"PEM Certificate" : "Πιστοποιητικό PEM",
"Certificate" : "Πιστοποιητικό",
diff --git a/l10n/el.json b/l10n/el.json
index a6a3825c81..005fe1cb67 100644
--- a/l10n/el.json
+++ b/l10n/el.json
@@ -762,6 +762,7 @@
"Certificate imported successfully" : "Το πιστοποιητικό εισήχθη με επιτυχία",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Αποτυχία εισαγωγής του πιστοποιητικού. Βεβαιωθείτε ότι το ιδιωτικό κλειδί ταιριάζει με το πιστοποιητικό και δεν προστατεύεται από φράση πρόσβασης.",
"Failed to import the certificate" : "Αποτυχία εισαγωγής του πιστοποιητικού",
+ "Import S/MIME certificate" : "Εισαγωγή πιστοποιητικού S/MIME",
"S/MIME certificates" : "Πιστοποιητικά S/MIME",
"Certificate name" : "Όνομα πιστοποιητικού",
"E-mail address" : "E-mail διεύθυνση",
@@ -769,7 +770,6 @@
"Delete certificate" : "Διαγραφή πιστοποιητικού",
"No certificate imported yet" : "Δεν έχει εισαχθεί ακόμα πιστοποιητικό",
"Import certificate" : "Εισαγωγή πιστοποιητικού",
- "Import S/MIME certificate" : "Εισαγωγή πιστοποιητικού S/MIME",
"PKCS #12 Certificate" : "Πιστοποιητικό PKCS #12",
"PEM Certificate" : "Πιστοποιητικό PEM",
"Certificate" : "Πιστοποιητικό",
diff --git a/l10n/en_GB.js b/l10n/en_GB.js
index 70eae8260d..d09888d9cf 100644
--- a/l10n/en_GB.js
+++ b/l10n/en_GB.js
@@ -821,6 +821,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "E-mail address",
@@ -828,7 +829,6 @@ OC.L10N.register(
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "Certificate",
diff --git a/l10n/en_GB.json b/l10n/en_GB.json
index 4f9e7a7e70..c4632fdcbe 100644
--- a/l10n/en_GB.json
+++ b/l10n/en_GB.json
@@ -819,6 +819,7 @@
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "E-mail address",
@@ -826,7 +827,6 @@
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "Certificate",
diff --git a/l10n/es.js b/l10n/es.js
index eb96be8257..afd9727b69 100644
--- a/l10n/es.js
+++ b/l10n/es.js
@@ -764,6 +764,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificado importado exitosamente",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Fallo al importar el certificado. Asegúrese de que la clave privada coincida con el certificado y no esté protegida por una contraseña.",
"Failed to import the certificate" : "Fallo al importar el certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nombre del certificado",
"E-mail address" : "Dirección de correo electrónico",
@@ -771,7 +772,6 @@ OC.L10N.register(
"Delete certificate" : "Eliminar certificado",
"No certificate imported yet" : "No se ha importado un certificado todavía",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/es.json b/l10n/es.json
index b84f1abe7e..59cc13c3ce 100644
--- a/l10n/es.json
+++ b/l10n/es.json
@@ -762,6 +762,7 @@
"Certificate imported successfully" : "Certificado importado exitosamente",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Fallo al importar el certificado. Asegúrese de que la clave privada coincida con el certificado y no esté protegida por una contraseña.",
"Failed to import the certificate" : "Fallo al importar el certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nombre del certificado",
"E-mail address" : "Dirección de correo electrónico",
@@ -769,7 +770,6 @@
"Delete certificate" : "Eliminar certificado",
"No certificate imported yet" : "No se ha importado un certificado todavía",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/es_EC.js b/l10n/es_EC.js
index b80c8dea8f..045c881c35 100644
--- a/l10n/es_EC.js
+++ b/l10n/es_EC.js
@@ -517,6 +517,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificado importado con éxito",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Error al importar el certificado. Por favor, asegúrate de que la clave privada coincida con el certificado y no esté protegida por una contraseña.",
"Failed to import the certificate" : "Error al importar el certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nombre del certificado",
"E-mail address" : "Dirección de correo electrónico",
@@ -524,7 +525,6 @@ OC.L10N.register(
"Delete certificate" : "Eliminar certificado",
"No certificate imported yet" : "Aún no se ha importado ningún certificado",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/es_EC.json b/l10n/es_EC.json
index ff168249cd..b339f8cadd 100644
--- a/l10n/es_EC.json
+++ b/l10n/es_EC.json
@@ -515,6 +515,7 @@
"Certificate imported successfully" : "Certificado importado con éxito",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Error al importar el certificado. Por favor, asegúrate de que la clave privada coincida con el certificado y no esté protegida por una contraseña.",
"Failed to import the certificate" : "Error al importar el certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nombre del certificado",
"E-mail address" : "Dirección de correo electrónico",
@@ -522,7 +523,6 @@
"Delete certificate" : "Eliminar certificado",
"No certificate imported yet" : "Aún no se ha importado ningún certificado",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/et_EE.js b/l10n/et_EE.js
index 0176552669..dc482455ff 100644
--- a/l10n/et_EE.js
+++ b/l10n/et_EE.js
@@ -781,6 +781,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Sertifikaadi importimine õnnestus",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Sertifikaadi importimine ei õnnestunud. Palun kontrolli, et privaatvõti vastab sertifikaadile ja ta ei ole salafraasiga krüptitud.",
"Failed to import the certificate" : "Sertifikaadi importimine ei õnnestunud",
+ "Import S/MIME certificate" : "Impordi S/MIME sertifikaat",
"S/MIME certificates" : "S/MIME sertifikaadid",
"Certificate name" : "Sertifikaadi nimi",
"E-mail address" : "E-posti aadress",
@@ -788,7 +789,6 @@ OC.L10N.register(
"Delete certificate" : "Kustuta sertifikaat",
"No certificate imported yet" : "Ühtegi sertifikaati pole imporditud",
"Import certificate" : "Impordi sertifikaat",
- "Import S/MIME certificate" : "Impordi S/MIME sertifikaat",
"PKCS #12 Certificate" : "PKCS #12 sertifikaat",
"PEM Certificate" : "PEM sertifikaat",
"Certificate" : "Sertifikaat",
diff --git a/l10n/et_EE.json b/l10n/et_EE.json
index ea1154c801..7b3830602b 100644
--- a/l10n/et_EE.json
+++ b/l10n/et_EE.json
@@ -779,6 +779,7 @@
"Certificate imported successfully" : "Sertifikaadi importimine õnnestus",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Sertifikaadi importimine ei õnnestunud. Palun kontrolli, et privaatvõti vastab sertifikaadile ja ta ei ole salafraasiga krüptitud.",
"Failed to import the certificate" : "Sertifikaadi importimine ei õnnestunud",
+ "Import S/MIME certificate" : "Impordi S/MIME sertifikaat",
"S/MIME certificates" : "S/MIME sertifikaadid",
"Certificate name" : "Sertifikaadi nimi",
"E-mail address" : "E-posti aadress",
@@ -786,7 +787,6 @@
"Delete certificate" : "Kustuta sertifikaat",
"No certificate imported yet" : "Ühtegi sertifikaati pole imporditud",
"Import certificate" : "Impordi sertifikaat",
- "Import S/MIME certificate" : "Impordi S/MIME sertifikaat",
"PKCS #12 Certificate" : "PKCS #12 sertifikaat",
"PEM Certificate" : "PEM sertifikaat",
"Certificate" : "Sertifikaat",
diff --git a/l10n/eu.js b/l10n/eu.js
index 1d8c77eb93..8d22122705 100644
--- a/l10n/eu.js
+++ b/l10n/eu.js
@@ -656,6 +656,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Ziurtagiria ongi inportatu da",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Ezin izan da ziurtagiria inportatu. Mesedez, ziurtatu gako pribatua ziurtagiriarekin bat datorrela eta ez dagoela pasaesaldi batek babestuta.",
"Failed to import the certificate" : "Ezin izan da ziurtagiria inportatu",
+ "Import S/MIME certificate" : "Inportatu S/MIME ziurtagiria",
"S/MIME certificates" : "S/MIME ziurtagiriak",
"Certificate name" : "Ziurtagiriaren izena",
"E-mail address" : "E-mail helbidea",
@@ -663,7 +664,6 @@ OC.L10N.register(
"Delete certificate" : "Ezabatu ziurtagiria",
"No certificate imported yet" : "Oraindik ez da inportatu ziurtagiririk",
"Import certificate" : "Inportatu ziurtagiria",
- "Import S/MIME certificate" : "Inportatu S/MIME ziurtagiria",
"PKCS #12 Certificate" : "PKCS #12 Ziurtagiria",
"PEM Certificate" : "PEM Ziurtagiria",
"Certificate" : "Ziurtagiria",
diff --git a/l10n/eu.json b/l10n/eu.json
index 99c437fece..9557046c8c 100644
--- a/l10n/eu.json
+++ b/l10n/eu.json
@@ -654,6 +654,7 @@
"Certificate imported successfully" : "Ziurtagiria ongi inportatu da",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Ezin izan da ziurtagiria inportatu. Mesedez, ziurtatu gako pribatua ziurtagiriarekin bat datorrela eta ez dagoela pasaesaldi batek babestuta.",
"Failed to import the certificate" : "Ezin izan da ziurtagiria inportatu",
+ "Import S/MIME certificate" : "Inportatu S/MIME ziurtagiria",
"S/MIME certificates" : "S/MIME ziurtagiriak",
"Certificate name" : "Ziurtagiriaren izena",
"E-mail address" : "E-mail helbidea",
@@ -661,7 +662,6 @@
"Delete certificate" : "Ezabatu ziurtagiria",
"No certificate imported yet" : "Oraindik ez da inportatu ziurtagiririk",
"Import certificate" : "Inportatu ziurtagiria",
- "Import S/MIME certificate" : "Inportatu S/MIME ziurtagiria",
"PKCS #12 Certificate" : "PKCS #12 Ziurtagiria",
"PEM Certificate" : "PEM Ziurtagiria",
"Certificate" : "Ziurtagiria",
diff --git a/l10n/fa.js b/l10n/fa.js
index c28c7d8f0c..85630df9cf 100644
--- a/l10n/fa.js
+++ b/l10n/fa.js
@@ -540,6 +540,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "آدرس ایمیل",
@@ -547,7 +548,6 @@ OC.L10N.register(
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "گواهی",
diff --git a/l10n/fa.json b/l10n/fa.json
index 67ac3fb0df..830ee2b57b 100644
--- a/l10n/fa.json
+++ b/l10n/fa.json
@@ -538,6 +538,7 @@
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "آدرس ایمیل",
@@ -545,7 +546,6 @@
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "گواهی",
diff --git a/l10n/fi.js b/l10n/fi.js
index 3d8a1a1fba..ee28e8db6f 100644
--- a/l10n/fi.js
+++ b/l10n/fi.js
@@ -549,6 +549,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Varmenne tuotu onnistuneesti",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Varmenteen tuonti epäonnistui. Varmista, että yksityinen avain vastaa varmennetta ja ettei se ole suojattu tunnuslauseella.",
"Failed to import the certificate" : "Varmenteen tuominen epäonnistui",
+ "Import S/MIME certificate" : "Tuo S/MIME-varmenne",
"S/MIME certificates" : "S/MIME-varmenteet",
"Certificate name" : "Varmenteen nimi",
"E-mail address" : "Sähköpostiosoite",
@@ -556,7 +557,6 @@ OC.L10N.register(
"Delete certificate" : "Poista varmenne",
"No certificate imported yet" : "Varmennetta ei ole vielä tuotu",
"Import certificate" : "Tuo varmenne",
- "Import S/MIME certificate" : "Tuo S/MIME-varmenne",
"PKCS #12 Certificate" : "PKCS #12 -varmenne",
"PEM Certificate" : "PEM-varmenne",
"Certificate" : "Varmenne",
diff --git a/l10n/fi.json b/l10n/fi.json
index 092d55d7e6..efecce2dbf 100644
--- a/l10n/fi.json
+++ b/l10n/fi.json
@@ -547,6 +547,7 @@
"Certificate imported successfully" : "Varmenne tuotu onnistuneesti",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Varmenteen tuonti epäonnistui. Varmista, että yksityinen avain vastaa varmennetta ja ettei se ole suojattu tunnuslauseella.",
"Failed to import the certificate" : "Varmenteen tuominen epäonnistui",
+ "Import S/MIME certificate" : "Tuo S/MIME-varmenne",
"S/MIME certificates" : "S/MIME-varmenteet",
"Certificate name" : "Varmenteen nimi",
"E-mail address" : "Sähköpostiosoite",
@@ -554,7 +555,6 @@
"Delete certificate" : "Poista varmenne",
"No certificate imported yet" : "Varmennetta ei ole vielä tuotu",
"Import certificate" : "Tuo varmenne",
- "Import S/MIME certificate" : "Tuo S/MIME-varmenne",
"PKCS #12 Certificate" : "PKCS #12 -varmenne",
"PEM Certificate" : "PEM-varmenne",
"Certificate" : "Varmenne",
diff --git a/l10n/fr.js b/l10n/fr.js
index 5efd923f5e..03dbbb7ea8 100644
--- a/l10n/fr.js
+++ b/l10n/fr.js
@@ -838,6 +838,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificat importé avec succès",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "L'import du certificat a échoué. Assurez-vous de la correspondance entre la clé privée et le certificat et que celle-ci n'est pas protégée par une phrase secrète.",
"Failed to import the certificate" : "Impossible d'importer le certificat",
+ "Import S/MIME certificate" : "Importer un certificat S/MIME",
"S/MIME certificates" : "Certificats S/MIME",
"Certificate name" : "Nom du certificat",
"E-mail address" : "Adresse e-mail",
@@ -845,7 +846,6 @@ OC.L10N.register(
"Delete certificate" : "Supprimer le certificat",
"No certificate imported yet" : "Pas encore de certificat importé",
"Import certificate" : "Importer un certificat",
- "Import S/MIME certificate" : "Importer un certificat S/MIME",
"PKCS #12 Certificate" : "Certificat PKCS #12",
"PEM Certificate" : "Certificat PEM",
"Certificate" : "Certificat",
diff --git a/l10n/fr.json b/l10n/fr.json
index 2da69fb39a..3c5a447cf9 100644
--- a/l10n/fr.json
+++ b/l10n/fr.json
@@ -836,6 +836,7 @@
"Certificate imported successfully" : "Certificat importé avec succès",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "L'import du certificat a échoué. Assurez-vous de la correspondance entre la clé privée et le certificat et que celle-ci n'est pas protégée par une phrase secrète.",
"Failed to import the certificate" : "Impossible d'importer le certificat",
+ "Import S/MIME certificate" : "Importer un certificat S/MIME",
"S/MIME certificates" : "Certificats S/MIME",
"Certificate name" : "Nom du certificat",
"E-mail address" : "Adresse e-mail",
@@ -843,7 +844,6 @@
"Delete certificate" : "Supprimer le certificat",
"No certificate imported yet" : "Pas encore de certificat importé",
"Import certificate" : "Importer un certificat",
- "Import S/MIME certificate" : "Importer un certificat S/MIME",
"PKCS #12 Certificate" : "Certificat PKCS #12",
"PEM Certificate" : "Certificat PEM",
"Certificate" : "Certificat",
diff --git a/l10n/ga.js b/l10n/ga.js
index 2821fa6d6a..38b6b897c3 100644
--- a/l10n/ga.js
+++ b/l10n/ga.js
@@ -846,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "D'éirigh leis an teastas a iompórtáil",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Theip ar an teastas a iompórtáil. Cinntigh le do thoil go bhfuil an eochair phríobháideach ag teacht leis an teastas agus nach bhfuil pasfhrása cosanta aici.",
"Failed to import the certificate" : "Theip ar an teastas a iompórtáil",
+ "Import S/MIME certificate" : "Iompórtáil teastas S/MIME",
"S/MIME certificates" : "Teastais S/MIME",
"Certificate name" : "Ainm an teastais",
"E-mail address" : "Seoladh ríomhphoist",
@@ -853,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "Scrios teastas",
"No certificate imported yet" : "Níor iompórtáladh aon teastas fós",
"Import certificate" : "Teastas iompórtála",
- "Import S/MIME certificate" : "Iompórtáil teastas S/MIME",
"PKCS #12 Certificate" : "Teastas PKCS #12",
"PEM Certificate" : "Deimhniú PEM",
"Certificate" : "Teastas",
diff --git a/l10n/ga.json b/l10n/ga.json
index ccdc28a6d3..0de0699d34 100644
--- a/l10n/ga.json
+++ b/l10n/ga.json
@@ -844,6 +844,7 @@
"Certificate imported successfully" : "D'éirigh leis an teastas a iompórtáil",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Theip ar an teastas a iompórtáil. Cinntigh le do thoil go bhfuil an eochair phríobháideach ag teacht leis an teastas agus nach bhfuil pasfhrása cosanta aici.",
"Failed to import the certificate" : "Theip ar an teastas a iompórtáil",
+ "Import S/MIME certificate" : "Iompórtáil teastas S/MIME",
"S/MIME certificates" : "Teastais S/MIME",
"Certificate name" : "Ainm an teastais",
"E-mail address" : "Seoladh ríomhphoist",
@@ -851,7 +852,6 @@
"Delete certificate" : "Scrios teastas",
"No certificate imported yet" : "Níor iompórtáladh aon teastas fós",
"Import certificate" : "Teastas iompórtála",
- "Import S/MIME certificate" : "Iompórtáil teastas S/MIME",
"PKCS #12 Certificate" : "Teastas PKCS #12",
"PEM Certificate" : "Deimhniú PEM",
"Certificate" : "Teastas",
diff --git a/l10n/gl.js b/l10n/gl.js
index e4a07bb861..2661e03684 100644
--- a/l10n/gl.js
+++ b/l10n/gl.js
@@ -819,6 +819,7 @@ OC.L10N.register(
"Certificate imported successfully" : "O certificado foi importado correctamente",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Produciuse un fallo ao importar o certificado. Asegúrese de que a chave privada coincide co certificado e non estea protexida por unha frase de contrasinal.",
"Failed to import the certificate" : "Produciuse un fallo ao importar o certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nome do certificado",
"E-mail address" : "Enderezo de correo",
@@ -826,7 +827,6 @@ OC.L10N.register(
"Delete certificate" : "Eliminar o certificado",
"No certificate imported yet" : "Aínda non se importou ningún certificado",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/gl.json b/l10n/gl.json
index e4c54ef0fa..5ba826d26f 100644
--- a/l10n/gl.json
+++ b/l10n/gl.json
@@ -817,6 +817,7 @@
"Certificate imported successfully" : "O certificado foi importado correctamente",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Produciuse un fallo ao importar o certificado. Asegúrese de que a chave privada coincide co certificado e non estea protexida por unha frase de contrasinal.",
"Failed to import the certificate" : "Produciuse un fallo ao importar o certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nome do certificado",
"E-mail address" : "Enderezo de correo",
@@ -824,7 +825,6 @@
"Delete certificate" : "Eliminar o certificado",
"No certificate imported yet" : "Aínda non se importou ningún certificado",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/hr.js b/l10n/hr.js
index 7465ef45d7..cb287a6068 100644
--- a/l10n/hr.js
+++ b/l10n/hr.js
@@ -820,6 +820,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certifikat je uspješno uvezen",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nije uspjelo uvesti certifikat. Provjerite odgovara li privatni ključcertifikatu i nije li zaštićen lozinkom.",
"Failed to import the certificate" : "Nije uspjelo uvesti certifikat",
+ "Import S/MIME certificate" : "Uvezi S/MIME certifikat",
"S/MIME certificates" : "S/MIME certifikati",
"Certificate name" : "Naziv certifikata",
"E-mail address" : "Adresa e-pošte",
@@ -827,7 +828,6 @@ OC.L10N.register(
"Delete certificate" : "Izbriši certifikat",
"No certificate imported yet" : "Još nije uvezen nijedan certifikat",
"Import certificate" : "Uvezi certifikat",
- "Import S/MIME certificate" : "Uvezi S/MIME certifikat",
"PKCS #12 Certificate" : "PKCS #12 certifikat",
"PEM Certificate" : "PEM certifikat",
"Certificate" : "Vjerodajnica",
diff --git a/l10n/hr.json b/l10n/hr.json
index 0780afa071..a4cf46a32f 100644
--- a/l10n/hr.json
+++ b/l10n/hr.json
@@ -818,6 +818,7 @@
"Certificate imported successfully" : "Certifikat je uspješno uvezen",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nije uspjelo uvesti certifikat. Provjerite odgovara li privatni ključcertifikatu i nije li zaštićen lozinkom.",
"Failed to import the certificate" : "Nije uspjelo uvesti certifikat",
+ "Import S/MIME certificate" : "Uvezi S/MIME certifikat",
"S/MIME certificates" : "S/MIME certifikati",
"Certificate name" : "Naziv certifikata",
"E-mail address" : "Adresa e-pošte",
@@ -825,7 +826,6 @@
"Delete certificate" : "Izbriši certifikat",
"No certificate imported yet" : "Još nije uvezen nijedan certifikat",
"Import certificate" : "Uvezi certifikat",
- "Import S/MIME certificate" : "Uvezi S/MIME certifikat",
"PKCS #12 Certificate" : "PKCS #12 certifikat",
"PEM Certificate" : "PEM certifikat",
"Certificate" : "Vjerodajnica",
diff --git a/l10n/hu.js b/l10n/hu.js
index 13084923d7..571d2a30d1 100644
--- a/l10n/hu.js
+++ b/l10n/hu.js
@@ -576,6 +576,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Tanúsítvány sikeresen importálva",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "A tanúsítvány importálása sikertelen. Győződjön meg arról, hogy a privát kulcs megfelel a tanúsítványnak, és nem védi jelszó.",
"Failed to import the certificate" : "A tanúsítvány importálása sikertelen",
+ "Import S/MIME certificate" : "S/MIME tanúsítvány importálása",
"S/MIME certificates" : "S/MIME tanúsítványok",
"Certificate name" : "Tanúsítvány neve",
"E-mail address" : "E-mail-cím",
@@ -583,7 +584,6 @@ OC.L10N.register(
"Delete certificate" : "Tanúsítvány törlése",
"No certificate imported yet" : "Még nincs tanúsítvány importálva",
"Import certificate" : "Tanúsítvány importálása",
- "Import S/MIME certificate" : "S/MIME tanúsítvány importálása",
"PKCS #12 Certificate" : "PKCS #12 tanúsítvány",
"PEM Certificate" : "PEM-tanúsítvány",
"Certificate" : "Tanúsítvány",
diff --git a/l10n/hu.json b/l10n/hu.json
index 7c27372476..328c5ca2e1 100644
--- a/l10n/hu.json
+++ b/l10n/hu.json
@@ -574,6 +574,7 @@
"Certificate imported successfully" : "Tanúsítvány sikeresen importálva",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "A tanúsítvány importálása sikertelen. Győződjön meg arról, hogy a privát kulcs megfelel a tanúsítványnak, és nem védi jelszó.",
"Failed to import the certificate" : "A tanúsítvány importálása sikertelen",
+ "Import S/MIME certificate" : "S/MIME tanúsítvány importálása",
"S/MIME certificates" : "S/MIME tanúsítványok",
"Certificate name" : "Tanúsítvány neve",
"E-mail address" : "E-mail-cím",
@@ -581,7 +582,6 @@
"Delete certificate" : "Tanúsítvány törlése",
"No certificate imported yet" : "Még nincs tanúsítvány importálva",
"Import certificate" : "Tanúsítvány importálása",
- "Import S/MIME certificate" : "S/MIME tanúsítvány importálása",
"PKCS #12 Certificate" : "PKCS #12 tanúsítvány",
"PEM Certificate" : "PEM-tanúsítvány",
"Certificate" : "Tanúsítvány",
diff --git a/l10n/id.js b/l10n/id.js
index d922917375..b3b7ccd709 100644
--- a/l10n/id.js
+++ b/l10n/id.js
@@ -815,6 +815,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Sertifikat berhasil diimpor",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Gagal mengimpor sertifikat. Pastikan kunci privat cocok dengan sertifikat dan tidak dilindungi oleh passphrase.",
"Failed to import the certificate" : "Gagal mengimpor sertifikat",
+ "Import S/MIME certificate" : "Impor sertifikat S/MIME",
"S/MIME certificates" : "Sertifikat S/MIME",
"Certificate name" : "Nama sertifikat",
"E-mail address" : "Alamat email",
@@ -822,7 +823,6 @@ OC.L10N.register(
"Delete certificate" : "Hapus sertifikat",
"No certificate imported yet" : "Belum ada sertifikat yang diimpor",
"Import certificate" : "Impor sertifikat",
- "Import S/MIME certificate" : "Impor sertifikat S/MIME",
"PKCS #12 Certificate" : "Sertifikat PKCS #12",
"PEM Certificate" : "Sertifikat PEM",
"Certificate" : "Sertifikat",
diff --git a/l10n/id.json b/l10n/id.json
index d66089a72b..9e0f7a5725 100644
--- a/l10n/id.json
+++ b/l10n/id.json
@@ -813,6 +813,7 @@
"Certificate imported successfully" : "Sertifikat berhasil diimpor",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Gagal mengimpor sertifikat. Pastikan kunci privat cocok dengan sertifikat dan tidak dilindungi oleh passphrase.",
"Failed to import the certificate" : "Gagal mengimpor sertifikat",
+ "Import S/MIME certificate" : "Impor sertifikat S/MIME",
"S/MIME certificates" : "Sertifikat S/MIME",
"Certificate name" : "Nama sertifikat",
"E-mail address" : "Alamat email",
@@ -820,7 +821,6 @@
"Delete certificate" : "Hapus sertifikat",
"No certificate imported yet" : "Belum ada sertifikat yang diimpor",
"Import certificate" : "Impor sertifikat",
- "Import S/MIME certificate" : "Impor sertifikat S/MIME",
"PKCS #12 Certificate" : "Sertifikat PKCS #12",
"PEM Certificate" : "Sertifikat PEM",
"Certificate" : "Sertifikat",
diff --git a/l10n/is.js b/l10n/is.js
index 912f970d72..9f841331eb 100644
--- a/l10n/is.js
+++ b/l10n/is.js
@@ -648,6 +648,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Tókst að flytja inn skilríki",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Mistókst að flytja inn skilríkið. Gakktu úr skugga um að einkalykillinn samsvari skilríkinu og sé ekki varinn með leynifrasa.",
"Failed to import the certificate" : "Mistókst að flytja inn skilríkið",
+ "Import S/MIME certificate" : "Flytja inn S/MIME-skilríki",
"S/MIME certificates" : "S/MIME-skilríki",
"Certificate name" : "Heiti skilríkis",
"E-mail address" : "Tölvupóstfang",
@@ -655,7 +656,6 @@ OC.L10N.register(
"Delete certificate" : "Eyða skilríki",
"No certificate imported yet" : "Ekkert skilríki ennþá flutt inn",
"Import certificate" : "Flytja inn skilríki",
- "Import S/MIME certificate" : "Flytja inn S/MIME-skilríki",
"PKCS #12 Certificate" : "PKCS #12 skilríki",
"PEM Certificate" : "PEM-skilríki",
"Certificate" : "Skilríki",
diff --git a/l10n/is.json b/l10n/is.json
index 45ffa9d032..58c2c4d014 100644
--- a/l10n/is.json
+++ b/l10n/is.json
@@ -646,6 +646,7 @@
"Certificate imported successfully" : "Tókst að flytja inn skilríki",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Mistókst að flytja inn skilríkið. Gakktu úr skugga um að einkalykillinn samsvari skilríkinu og sé ekki varinn með leynifrasa.",
"Failed to import the certificate" : "Mistókst að flytja inn skilríkið",
+ "Import S/MIME certificate" : "Flytja inn S/MIME-skilríki",
"S/MIME certificates" : "S/MIME-skilríki",
"Certificate name" : "Heiti skilríkis",
"E-mail address" : "Tölvupóstfang",
@@ -653,7 +654,6 @@
"Delete certificate" : "Eyða skilríki",
"No certificate imported yet" : "Ekkert skilríki ennþá flutt inn",
"Import certificate" : "Flytja inn skilríki",
- "Import S/MIME certificate" : "Flytja inn S/MIME-skilríki",
"PKCS #12 Certificate" : "PKCS #12 skilríki",
"PEM Certificate" : "PEM-skilríki",
"Certificate" : "Skilríki",
diff --git a/l10n/it.js b/l10n/it.js
index 3bab88b874..9823777e88 100644
--- a/l10n/it.js
+++ b/l10n/it.js
@@ -842,6 +842,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificato importato correttamente",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Non è stato possibile importare il certificato. Verifica che la chiave privata corrisponda al certificato e che non sia protetta da passphrase.",
"Failed to import the certificate" : "Importare del certificato non riuscita",
+ "Import S/MIME certificate" : "Importa certificato S/MIME",
"S/MIME certificates" : "Certificati S/MIME",
"Certificate name" : "Nome del certificato",
"E-mail address" : "Indirizzo di posta",
@@ -849,7 +850,6 @@ OC.L10N.register(
"Delete certificate" : "Elimina certificato",
"No certificate imported yet" : "Ancora nessun certificato importato",
"Import certificate" : "Importa certificato",
- "Import S/MIME certificate" : "Importa certificato S/MIME",
"PKCS #12 Certificate" : "Certificato PKCS #12",
"PEM Certificate" : "Certificato PEM",
"Certificate" : "Certificato",
diff --git a/l10n/it.json b/l10n/it.json
index f6928a3500..e059ffa6e9 100644
--- a/l10n/it.json
+++ b/l10n/it.json
@@ -840,6 +840,7 @@
"Certificate imported successfully" : "Certificato importato correttamente",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Non è stato possibile importare il certificato. Verifica che la chiave privata corrisponda al certificato e che non sia protetta da passphrase.",
"Failed to import the certificate" : "Importare del certificato non riuscita",
+ "Import S/MIME certificate" : "Importa certificato S/MIME",
"S/MIME certificates" : "Certificati S/MIME",
"Certificate name" : "Nome del certificato",
"E-mail address" : "Indirizzo di posta",
@@ -847,7 +848,6 @@
"Delete certificate" : "Elimina certificato",
"No certificate imported yet" : "Ancora nessun certificato importato",
"Import certificate" : "Importa certificato",
- "Import S/MIME certificate" : "Importa certificato S/MIME",
"PKCS #12 Certificate" : "Certificato PKCS #12",
"PEM Certificate" : "Certificato PEM",
"Certificate" : "Certificato",
diff --git a/l10n/ja.js b/l10n/ja.js
index fb1bc85104..d2b2633cb8 100644
--- a/l10n/ja.js
+++ b/l10n/ja.js
@@ -686,6 +686,7 @@ OC.L10N.register(
"Certificate imported successfully" : "証明書のインポートが成功しました",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "証明書のインポートに失敗しました。秘密鍵が証明書と一致し、パスフレーズで保護されていないことを確認してください。",
"Failed to import the certificate" : "証明書のインポートするが失敗した",
+ "Import S/MIME certificate" : "S/MIME 証明書をインポートする",
"S/MIME certificates" : "S/MIME証明書",
"Certificate name" : "証明書名",
"E-mail address" : "メールアドレス",
@@ -693,7 +694,6 @@ OC.L10N.register(
"Delete certificate" : "証明書を削除する",
"No certificate imported yet" : "証明書はまだインポートされていません",
"Import certificate" : "証明書をインポートする",
- "Import S/MIME certificate" : "S/MIME 証明書をインポートする",
"PKCS #12 Certificate" : "PKCS #12 証明書",
"PEM Certificate" : "PEM証明書",
"Certificate" : "証明",
diff --git a/l10n/ja.json b/l10n/ja.json
index 988a442ca5..470825fae4 100644
--- a/l10n/ja.json
+++ b/l10n/ja.json
@@ -684,6 +684,7 @@
"Certificate imported successfully" : "証明書のインポートが成功しました",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "証明書のインポートに失敗しました。秘密鍵が証明書と一致し、パスフレーズで保護されていないことを確認してください。",
"Failed to import the certificate" : "証明書のインポートするが失敗した",
+ "Import S/MIME certificate" : "S/MIME 証明書をインポートする",
"S/MIME certificates" : "S/MIME証明書",
"Certificate name" : "証明書名",
"E-mail address" : "メールアドレス",
@@ -691,7 +692,6 @@
"Delete certificate" : "証明書を削除する",
"No certificate imported yet" : "証明書はまだインポートされていません",
"Import certificate" : "証明書をインポートする",
- "Import S/MIME certificate" : "S/MIME 証明書をインポートする",
"PKCS #12 Certificate" : "PKCS #12 証明書",
"PEM Certificate" : "PEM証明書",
"Certificate" : "証明",
diff --git a/l10n/ka.js b/l10n/ka.js
index 73e28b32a9..d03c81769e 100644
--- a/l10n/ka.js
+++ b/l10n/ka.js
@@ -564,6 +564,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "E-mail address",
@@ -571,7 +572,6 @@ OC.L10N.register(
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "Certificate",
diff --git a/l10n/ka.json b/l10n/ka.json
index d8ab5fbf15..53935e7b59 100644
--- a/l10n/ka.json
+++ b/l10n/ka.json
@@ -562,6 +562,7 @@
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "E-mail address",
@@ -569,7 +570,6 @@
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "Certificate",
diff --git a/l10n/ko.js b/l10n/ko.js
index c745567553..5fa87f803d 100644
--- a/l10n/ko.js
+++ b/l10n/ko.js
@@ -575,6 +575,7 @@ OC.L10N.register(
"Certificate imported successfully" : "인증서를 성공적으로 불러옴",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "인증서를 불러올 수 없음. 개인 키와 인증서의 연동 및 개인 키의 암구호 미사용 여부를 확인하십시오.",
"Failed to import the certificate" : "인증서를 가져올 수 없음",
+ "Import S/MIME certificate" : "S/MIME 인증서 가져오기",
"S/MIME certificates" : "S/MIME 인증서",
"Certificate name" : "인증서 이름",
"E-mail address" : "이메일 주소",
@@ -582,7 +583,6 @@ OC.L10N.register(
"Delete certificate" : "인증서 삭제",
"No certificate imported yet" : "가져온 인증서 없음",
"Import certificate" : "인증서 가져오기",
- "Import S/MIME certificate" : "S/MIME 인증서 가져오기",
"PKCS #12 Certificate" : "PKCS #12 인증서",
"PEM Certificate" : "PEM 인증서",
"Certificate" : "인증서",
diff --git a/l10n/ko.json b/l10n/ko.json
index bd4f89f573..602911b739 100644
--- a/l10n/ko.json
+++ b/l10n/ko.json
@@ -573,6 +573,7 @@
"Certificate imported successfully" : "인증서를 성공적으로 불러옴",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "인증서를 불러올 수 없음. 개인 키와 인증서의 연동 및 개인 키의 암구호 미사용 여부를 확인하십시오.",
"Failed to import the certificate" : "인증서를 가져올 수 없음",
+ "Import S/MIME certificate" : "S/MIME 인증서 가져오기",
"S/MIME certificates" : "S/MIME 인증서",
"Certificate name" : "인증서 이름",
"E-mail address" : "이메일 주소",
@@ -580,7 +581,6 @@
"Delete certificate" : "인증서 삭제",
"No certificate imported yet" : "가져온 인증서 없음",
"Import certificate" : "인증서 가져오기",
- "Import S/MIME certificate" : "S/MIME 인증서 가져오기",
"PKCS #12 Certificate" : "PKCS #12 인증서",
"PEM Certificate" : "PEM 인증서",
"Certificate" : "인증서",
diff --git a/l10n/lo.js b/l10n/lo.js
index 3ce045b212..eddbe997f8 100644
--- a/l10n/lo.js
+++ b/l10n/lo.js
@@ -795,6 +795,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "E-mail address",
@@ -802,7 +803,6 @@ OC.L10N.register(
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "Certificate",
diff --git a/l10n/lo.json b/l10n/lo.json
index daa0c79779..ce4092003c 100644
--- a/l10n/lo.json
+++ b/l10n/lo.json
@@ -793,6 +793,7 @@
"Certificate imported successfully" : "Certificate imported successfully",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase.",
"Failed to import the certificate" : "Failed to import the certificate",
+ "Import S/MIME certificate" : "Import S/MIME certificate",
"S/MIME certificates" : "S/MIME certificates",
"Certificate name" : "Certificate name",
"E-mail address" : "E-mail address",
@@ -800,7 +801,6 @@
"Delete certificate" : "Delete certificate",
"No certificate imported yet" : "No certificate imported yet",
"Import certificate" : "Import certificate",
- "Import S/MIME certificate" : "Import S/MIME certificate",
"PKCS #12 Certificate" : "PKCS #12 Certificate",
"PEM Certificate" : "PEM Certificate",
"Certificate" : "Certificate",
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index d16af2a50d..7efd37a545 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -842,6 +842,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Liudijimas sėkmingai importuotas",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nepavyko importuoti sertifikato. Įsitikinkite, kad privatusis raktas atitinka sertifikatą ir nėra apsaugotas slaptafraze.",
"Failed to import the certificate" : "Nepavyko importuoti liudijimo",
+ "Import S/MIME certificate" : "Importuoti S/MIME liudijimą",
"S/MIME certificates" : "S/MIME liudijimai",
"Certificate name" : "Liudijimo pavadinimas",
"E-mail address" : "El. pašto adresas",
@@ -849,7 +850,6 @@ OC.L10N.register(
"Delete certificate" : "Ištrinti liudijimą",
"No certificate imported yet" : "Dar neimportuotas joks sertifikatas",
"Import certificate" : "Importuoti liudijimą",
- "Import S/MIME certificate" : "Importuoti S/MIME liudijimą",
"PKCS #12 Certificate" : "PKCS #12 liudijimas",
"PEM Certificate" : "PEM liudijimas",
"Certificate" : "Liudijimas",
diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json
index b16a0ae969..1fb23f47b5 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -840,6 +840,7 @@
"Certificate imported successfully" : "Liudijimas sėkmingai importuotas",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nepavyko importuoti sertifikato. Įsitikinkite, kad privatusis raktas atitinka sertifikatą ir nėra apsaugotas slaptafraze.",
"Failed to import the certificate" : "Nepavyko importuoti liudijimo",
+ "Import S/MIME certificate" : "Importuoti S/MIME liudijimą",
"S/MIME certificates" : "S/MIME liudijimai",
"Certificate name" : "Liudijimo pavadinimas",
"E-mail address" : "El. pašto adresas",
@@ -847,7 +848,6 @@
"Delete certificate" : "Ištrinti liudijimą",
"No certificate imported yet" : "Dar neimportuotas joks sertifikatas",
"Import certificate" : "Importuoti liudijimą",
- "Import S/MIME certificate" : "Importuoti S/MIME liudijimą",
"PKCS #12 Certificate" : "PKCS #12 liudijimas",
"PEM Certificate" : "PEM liudijimas",
"Certificate" : "Liudijimas",
diff --git a/l10n/lv.js b/l10n/lv.js
index 9a10b22237..347d81175e 100644
--- a/l10n/lv.js
+++ b/l10n/lv.js
@@ -174,7 +174,7 @@ OC.L10N.register(
"Inbox" : "Iesūtne",
"Junk" : "Nevēlams",
"Sent" : "Izsūtne",
- "Trash" : "Miskaste",
+ "Trash" : "Atkritne",
"Error while sharing file" : "Kļūda datnes kopīgošanā",
"{from}\n{subject}" : "{from}\n{subject}",
"There is already a message in progress. All unsaved changes will be lost if you continue!" : "Jau tiek apstrādāts ziņojums. Tiks zaudētas visas nesaglabātas izmaiņas, ja turpināsi.",
diff --git a/l10n/lv.json b/l10n/lv.json
index 6599903b1c..789672b493 100644
--- a/l10n/lv.json
+++ b/l10n/lv.json
@@ -172,7 +172,7 @@
"Inbox" : "Iesūtne",
"Junk" : "Nevēlams",
"Sent" : "Izsūtne",
- "Trash" : "Miskaste",
+ "Trash" : "Atkritne",
"Error while sharing file" : "Kļūda datnes kopīgošanā",
"{from}\n{subject}" : "{from}\n{subject}",
"There is already a message in progress. All unsaved changes will be lost if you continue!" : "Jau tiek apstrādāts ziņojums. Tiks zaudētas visas nesaglabātas izmaiņas, ja turpināsi.",
diff --git a/l10n/mk.js b/l10n/mk.js
index 940398d309..3b2142268d 100644
--- a/l10n/mk.js
+++ b/l10n/mk.js
@@ -412,6 +412,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Сертификатот е успешно увезен",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Неуспешно увезување на сертификат. Проверете дали приватниот клуч се совпаѓа со сертификатот и не е заштитен со лозинка.",
"Failed to import the certificate" : "Неуспешен увоз на сертификат",
+ "Import S/MIME certificate" : "Увези S/MIME сертификат",
"S/MIME certificates" : "S/MIME сертификати",
"Certificate name" : "Име на сертификатот",
"E-mail address" : "Е-пошта адреса",
@@ -419,7 +420,6 @@ OC.L10N.register(
"Delete certificate" : "Избриши сертификат",
"No certificate imported yet" : "Сеуште нема увезено сертификат",
"Import certificate" : "Увези сертификат",
- "Import S/MIME certificate" : "Увези S/MIME сертификат",
"PKCS #12 Certificate" : "PKCS #12 Сертификат",
"PEM Certificate" : "PEM Сертификат",
"Certificate" : "Сертификат",
diff --git a/l10n/mk.json b/l10n/mk.json
index 7fb4e93431..6b04a1edbd 100644
--- a/l10n/mk.json
+++ b/l10n/mk.json
@@ -410,6 +410,7 @@
"Certificate imported successfully" : "Сертификатот е успешно увезен",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Неуспешно увезување на сертификат. Проверете дали приватниот клуч се совпаѓа со сертификатот и не е заштитен со лозинка.",
"Failed to import the certificate" : "Неуспешен увоз на сертификат",
+ "Import S/MIME certificate" : "Увези S/MIME сертификат",
"S/MIME certificates" : "S/MIME сертификати",
"Certificate name" : "Име на сертификатот",
"E-mail address" : "Е-пошта адреса",
@@ -417,7 +418,6 @@
"Delete certificate" : "Избриши сертификат",
"No certificate imported yet" : "Сеуште нема увезено сертификат",
"Import certificate" : "Увези сертификат",
- "Import S/MIME certificate" : "Увези S/MIME сертификат",
"PKCS #12 Certificate" : "PKCS #12 Сертификат",
"PEM Certificate" : "PEM Сертификат",
"Certificate" : "Сертификат",
diff --git a/l10n/mn.js b/l10n/mn.js
index abc9f6a682..c830af9647 100644
--- a/l10n/mn.js
+++ b/l10n/mn.js
@@ -801,6 +801,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Сертификат амжилттай импортлогдлоо",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Сертификатыг импортлоход амжилтгүй боллоо. Хувийн түлхүүр сертификаттай тохирч байгаа эсэх болон нууц үгээр хамгаалагдаагүй эсэхийг шалгана уу.",
"Failed to import the certificate" : "Сертификат импортлоход алдаа гарлаа",
+ "Import S/MIME certificate" : "S/MIME сертификат импортлох",
"S/MIME certificates" : "S/MIME сертификатууд",
"Certificate name" : "Сертификатын нэр",
"E-mail address" : "И-мэйл хаяг",
@@ -808,7 +809,6 @@ OC.L10N.register(
"Delete certificate" : "Сертификат устгах",
"No certificate imported yet" : "Сертификат импортлогдоогүй байна",
"Import certificate" : "Сертификат импортлох",
- "Import S/MIME certificate" : "S/MIME сертификат импортлох",
"PKCS #12 Certificate" : "PKCS #12 сертификат",
"PEM Certificate" : "PEM сертификат",
"Certificate" : "–ì—ç—Ä—á–∏–ª–≥—ç—ç",
diff --git a/l10n/mn.json b/l10n/mn.json
index 624ff98d66..26a2c0cfa4 100644
--- a/l10n/mn.json
+++ b/l10n/mn.json
@@ -799,6 +799,7 @@
"Certificate imported successfully" : "Сертификат амжилттай импортлогдлоо",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Сертификатыг импортлоход амжилтгүй боллоо. Хувийн түлхүүр сертификаттай тохирч байгаа эсэх болон нууц үгээр хамгаалагдаагүй эсэхийг шалгана уу.",
"Failed to import the certificate" : "Сертификат импортлоход алдаа гарлаа",
+ "Import S/MIME certificate" : "S/MIME сертификат импортлох",
"S/MIME certificates" : "S/MIME сертификатууд",
"Certificate name" : "Сертификатын нэр",
"E-mail address" : "И-мэйл хаяг",
@@ -806,7 +807,6 @@
"Delete certificate" : "Сертификат устгах",
"No certificate imported yet" : "Сертификат импортлогдоогүй байна",
"Import certificate" : "Сертификат импортлох",
- "Import S/MIME certificate" : "S/MIME сертификат импортлох",
"PKCS #12 Certificate" : "PKCS #12 сертификат",
"PEM Certificate" : "PEM сертификат",
"Certificate" : "–ì—ç—Ä—á–∏–ª–≥—ç—ç",
diff --git a/l10n/nb.js b/l10n/nb.js
index 3c07a2ca7d..f32d245c57 100644
--- a/l10n/nb.js
+++ b/l10n/nb.js
@@ -644,6 +644,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Sertifikatet ble importert",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Kan ikke importere sertifikatet. Forsikre deg om at den private nøkkelen samsvarer med sertifikatet og ikke er beskyttet av en passordfrase.",
"Failed to import the certificate" : "Kunne ikke importere sertifikatet",
+ "Import S/MIME certificate" : "Importer S/MIME-sertifikat",
"S/MIME certificates" : "S/MIME-sertifikater",
"Certificate name" : "Sertifikatnavn",
"E-mail address" : "E-postadresse",
@@ -651,7 +652,6 @@ OC.L10N.register(
"Delete certificate" : "Slett sertifikat",
"No certificate imported yet" : "Ingen sertifikat importert enda",
"Import certificate" : "Importer sertifikat",
- "Import S/MIME certificate" : "Importer S/MIME-sertifikat",
"PKCS #12 Certificate" : "PKCS #12-sertifikat",
"PEM Certificate" : "PEM-sertifikat",
"Certificate" : "Sertifikat",
diff --git a/l10n/nb.json b/l10n/nb.json
index 5c145f8bef..894e25ac84 100644
--- a/l10n/nb.json
+++ b/l10n/nb.json
@@ -642,6 +642,7 @@
"Certificate imported successfully" : "Sertifikatet ble importert",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Kan ikke importere sertifikatet. Forsikre deg om at den private nøkkelen samsvarer med sertifikatet og ikke er beskyttet av en passordfrase.",
"Failed to import the certificate" : "Kunne ikke importere sertifikatet",
+ "Import S/MIME certificate" : "Importer S/MIME-sertifikat",
"S/MIME certificates" : "S/MIME-sertifikater",
"Certificate name" : "Sertifikatnavn",
"E-mail address" : "E-postadresse",
@@ -649,7 +650,6 @@
"Delete certificate" : "Slett sertifikat",
"No certificate imported yet" : "Ingen sertifikat importert enda",
"Import certificate" : "Importer sertifikat",
- "Import S/MIME certificate" : "Importer S/MIME-sertifikat",
"PKCS #12 Certificate" : "PKCS #12-sertifikat",
"PEM Certificate" : "PEM-sertifikat",
"Certificate" : "Sertifikat",
diff --git a/l10n/nl.js b/l10n/nl.js
index e83c9e282d..ef6bf0ecd8 100644
--- a/l10n/nl.js
+++ b/l10n/nl.js
@@ -635,6 +635,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificaat succesvol geïmporteerd",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Importeren van het certificaat is mislukt. Controleer of de privaatsleutel overeenkomt met het certificaat en niet beschermd is door een beveiligingszin.",
"Failed to import the certificate" : "Importeren van het certificaat mislukt",
+ "Import S/MIME certificate" : "Importeer S/MIME certificaat",
"S/MIME certificates" : "S/MIME certificaten",
"Certificate name" : "Certificaat naam",
"E-mail address" : "E-mailadres",
@@ -642,7 +643,6 @@ OC.L10N.register(
"Delete certificate" : "Verwijder certificaat",
"No certificate imported yet" : "Nog geen certificaat geïmporteerd",
"Import certificate" : "Importeer certificaat",
- "Import S/MIME certificate" : "Importeer S/MIME certificaat",
"PKCS #12 Certificate" : "PKCS #12 Certificaat",
"PEM Certificate" : "PEM certificaat",
"Certificate" : "Certificaat",
diff --git a/l10n/nl.json b/l10n/nl.json
index 38492d5475..249a997c1d 100644
--- a/l10n/nl.json
+++ b/l10n/nl.json
@@ -633,6 +633,7 @@
"Certificate imported successfully" : "Certificaat succesvol geïmporteerd",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Importeren van het certificaat is mislukt. Controleer of de privaatsleutel overeenkomt met het certificaat en niet beschermd is door een beveiligingszin.",
"Failed to import the certificate" : "Importeren van het certificaat mislukt",
+ "Import S/MIME certificate" : "Importeer S/MIME certificaat",
"S/MIME certificates" : "S/MIME certificaten",
"Certificate name" : "Certificaat naam",
"E-mail address" : "E-mailadres",
@@ -640,7 +641,6 @@
"Delete certificate" : "Verwijder certificaat",
"No certificate imported yet" : "Nog geen certificaat geïmporteerd",
"Import certificate" : "Importeer certificaat",
- "Import S/MIME certificate" : "Importeer S/MIME certificaat",
"PKCS #12 Certificate" : "PKCS #12 Certificaat",
"PEM Certificate" : "PEM certificaat",
"Certificate" : "Certificaat",
diff --git a/l10n/pl.js b/l10n/pl.js
index 619b5256ab..90ab0010ed 100644
--- a/l10n/pl.js
+++ b/l10n/pl.js
@@ -815,6 +815,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certyfikat został zaimportowany pomyślnie",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nie udało się zaimportować certyfikatu. Upewnij się, że klucz prywatny jest zgodny z certyfikatem i nie jest chroniony hasłem.",
"Failed to import the certificate" : "Nie udało się zaimportować certyfikatu",
+ "Import S/MIME certificate" : "Importuj certyfikat S/MIME",
"S/MIME certificates" : "Certyfikaty S/MIME",
"Certificate name" : "Nazwa certyfikatu",
"E-mail address" : "Adres e-mail",
@@ -822,7 +823,6 @@ OC.L10N.register(
"Delete certificate" : "Usuń certyfikat",
"No certificate imported yet" : "Nie zaimportowano jeszcze żadnego certyfikatu",
"Import certificate" : "Importuj certyfikat",
- "Import S/MIME certificate" : "Importuj certyfikat S/MIME",
"PKCS #12 Certificate" : "Certyfikat PKCS #12",
"PEM Certificate" : "Certyfikat PEM",
"Certificate" : "Certyfikat",
diff --git a/l10n/pl.json b/l10n/pl.json
index f2545f9208..b32b839000 100644
--- a/l10n/pl.json
+++ b/l10n/pl.json
@@ -813,6 +813,7 @@
"Certificate imported successfully" : "Certyfikat został zaimportowany pomyślnie",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nie udało się zaimportować certyfikatu. Upewnij się, że klucz prywatny jest zgodny z certyfikatem i nie jest chroniony hasłem.",
"Failed to import the certificate" : "Nie udało się zaimportować certyfikatu",
+ "Import S/MIME certificate" : "Importuj certyfikat S/MIME",
"S/MIME certificates" : "Certyfikaty S/MIME",
"Certificate name" : "Nazwa certyfikatu",
"E-mail address" : "Adres e-mail",
@@ -820,7 +821,6 @@
"Delete certificate" : "Usuń certyfikat",
"No certificate imported yet" : "Nie zaimportowano jeszcze żadnego certyfikatu",
"Import certificate" : "Importuj certyfikat",
- "Import S/MIME certificate" : "Importuj certyfikat S/MIME",
"PKCS #12 Certificate" : "Certyfikat PKCS #12",
"PEM Certificate" : "Certyfikat PEM",
"Certificate" : "Certyfikat",
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index 95a1cee804..fab1e12411 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -846,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certificado importado com sucesso",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Falha ao importar o certificado. Por favor, certifique-se de que a chave privada corresponda ao certificado e não esteja protegida por uma frase secreta.",
"Failed to import the certificate" : "Falha ao importar o certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nome do certificado",
"E-mail address" : "Endereço de e-mail",
@@ -853,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "Excluir certificado",
"No certificate imported yet" : "Nenhum certificado importado ainda",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index b7019d09f7..1a010947e8 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -844,6 +844,7 @@
"Certificate imported successfully" : "Certificado importado com sucesso",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Falha ao importar o certificado. Por favor, certifique-se de que a chave privada corresponda ao certificado e não esteja protegida por uma frase secreta.",
"Failed to import the certificate" : "Falha ao importar o certificado",
+ "Import S/MIME certificate" : "Importar certificado S/MIME",
"S/MIME certificates" : "Certificados S/MIME",
"Certificate name" : "Nome do certificado",
"E-mail address" : "Endereço de e-mail",
@@ -851,7 +852,6 @@
"Delete certificate" : "Excluir certificado",
"No certificate imported yet" : "Nenhum certificado importado ainda",
"Import certificate" : "Importar certificado",
- "Import S/MIME certificate" : "Importar certificado S/MIME",
"PKCS #12 Certificate" : "Certificado PKCS #12",
"PEM Certificate" : "Certificado PEM",
"Certificate" : "Certificado",
diff --git a/l10n/ru.js b/l10n/ru.js
index 6258d9abe4..ad0b0c904d 100644
--- a/l10n/ru.js
+++ b/l10n/ru.js
@@ -719,6 +719,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Сертификат успешно импортирован",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Не удалось импортировать сертификат. Убедитесь, что закрытый ключ соответствует сертификату и не защищен парольной фразой.",
"Failed to import the certificate" : "Не удалось импортировать сертификат",
+ "Import S/MIME certificate" : "Импортировать сертификат S/MIME",
"S/MIME certificates" : "Сертификаты S/MIME",
"Certificate name" : "Название сертификата",
"E-mail address" : "Адрес эл. почты",
@@ -726,7 +727,6 @@ OC.L10N.register(
"Delete certificate" : "Удалить сертификат",
"No certificate imported yet" : "Сертификат еще не импортирован",
"Import certificate" : "Импортный сертификат",
- "Import S/MIME certificate" : "Импортировать сертификат S/MIME",
"PKCS #12 Certificate" : "PKCS #12 Сертификат",
"PEM Certificate" : "PEM Сертификат",
"Certificate" : "Сертификат",
diff --git a/l10n/ru.json b/l10n/ru.json
index 7d625faf64..a88bf4228b 100644
--- a/l10n/ru.json
+++ b/l10n/ru.json
@@ -717,6 +717,7 @@
"Certificate imported successfully" : "Сертификат успешно импортирован",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Не удалось импортировать сертификат. Убедитесь, что закрытый ключ соответствует сертификату и не защищен парольной фразой.",
"Failed to import the certificate" : "Не удалось импортировать сертификат",
+ "Import S/MIME certificate" : "Импортировать сертификат S/MIME",
"S/MIME certificates" : "Сертификаты S/MIME",
"Certificate name" : "Название сертификата",
"E-mail address" : "Адрес эл. почты",
@@ -724,7 +725,6 @@
"Delete certificate" : "Удалить сертификат",
"No certificate imported yet" : "Сертификат еще не импортирован",
"Import certificate" : "Импортный сертификат",
- "Import S/MIME certificate" : "Импортировать сертификат S/MIME",
"PKCS #12 Certificate" : "PKCS #12 Сертификат",
"PEM Certificate" : "PEM Сертификат",
"Certificate" : "Сертификат",
diff --git a/l10n/sk.js b/l10n/sk.js
index 8566e50461..66af8aea2b 100644
--- a/l10n/sk.js
+++ b/l10n/sk.js
@@ -821,6 +821,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certifikát úspešne importovaný",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nepodarilo sa importovať certifikát. Uistite sa, prosím, že súkromný kľúč zodpovedá certifikátu a nie je chránený heslom.",
"Failed to import the certificate" : "Nepodarilo sa importovať certifikát.",
+ "Import S/MIME certificate" : "Importovať S/MIME certifikát",
"S/MIME certificates" : "S/MIME certifikáty",
"Certificate name" : "Meno certifikátu",
"E-mail address" : "E-mailová adresa",
@@ -828,7 +829,6 @@ OC.L10N.register(
"Delete certificate" : "Vymazať certifikát",
"No certificate imported yet" : "Žiadny certifikát zatiaľ nebol importovaný.",
"Import certificate" : "Importovať certifikát",
- "Import S/MIME certificate" : "Importovať S/MIME certifikát",
"PKCS #12 Certificate" : "PKCS #12 Certifikát",
"PEM Certificate" : "PEM Certifikát",
"Certificate" : "Certifikát",
diff --git a/l10n/sk.json b/l10n/sk.json
index d2c98febc3..c6e1353c46 100644
--- a/l10n/sk.json
+++ b/l10n/sk.json
@@ -819,6 +819,7 @@
"Certificate imported successfully" : "Certifikát úspešne importovaný",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nepodarilo sa importovať certifikát. Uistite sa, prosím, že súkromný kľúč zodpovedá certifikátu a nie je chránený heslom.",
"Failed to import the certificate" : "Nepodarilo sa importovať certifikát.",
+ "Import S/MIME certificate" : "Importovať S/MIME certifikát",
"S/MIME certificates" : "S/MIME certifikáty",
"Certificate name" : "Meno certifikátu",
"E-mail address" : "E-mailová adresa",
@@ -826,7 +827,6 @@
"Delete certificate" : "Vymazať certifikát",
"No certificate imported yet" : "Žiadny certifikát zatiaľ nebol importovaný.",
"Import certificate" : "Importovať certifikát",
- "Import S/MIME certificate" : "Importovať S/MIME certifikát",
"PKCS #12 Certificate" : "PKCS #12 Certifikát",
"PEM Certificate" : "PEM Certifikát",
"Certificate" : "Certifikát",
diff --git a/l10n/sl.js b/l10n/sl.js
index 37adecb804..edd1e7099c 100644
--- a/l10n/sl.js
+++ b/l10n/sl.js
@@ -378,7 +378,7 @@ OC.L10N.register(
"Add tag" : "Dodaj oznako",
"Task created" : "Naloga je ustvarjena",
"Could not create task" : "Naloge ni mogoče ustvariti",
- "No calendars with task list support" : "Koledar s podporo seznama nalog",
+ "No calendars with task list support" : "Ni koledarjev s podporo seznama nalog",
"Could not load your message thread" : "Ni mogoče naložiti niti sporočil",
"The thread doesn't exist or has been deleted" : "Nit ne obstaja ali pa je bila izbrisana",
"Loading thread" : "Poteka nalaganje niti",
@@ -471,12 +471,13 @@ OC.L10N.register(
"SMTP" : "SMTP",
"Sieve" : "Sieve",
"Enable sieve integration" : "Omogoči združevalnik sieve",
- "The LDAP aliases integration reads an attribute from the configured LDAP directory to provision email aliases." : "PRogram LDAP pridobi podatke atributa, nastavljenega v imeniku LDAP za povezovanje elektronskih naslovov z vzdevki.",
+ "The LDAP aliases integration reads an attribute from the configured LDAP directory to provision email aliases." : "Program LDAP pridobi podatke atributa, nastavljenega v imeniku LDAP za povezovanje elektronskih naslovov z vzdevki.",
"A multi value attribute to provision email aliases. For each value an alias is created. Aliases existing in Nextcloud which are not in the LDAP directory are deleted." : "Nastavitev določa atribut z več vrednostmi za povezovanje vzdevkov elektronskih naslovov. Za vsako vrednost je ustvarjen vzdevek, tisti vzdevki, ki so vpisani v oblaku Nextcloud, a niso tudi v imeniku LDAP, se izbrišejo.",
"Save Config" : "Shrani nastavitve",
"Unprovision & Delete Config" : "Odstrani povezavo in izbriši nastavitve",
"With the settings above, the app will create account settings in the following way:" : "Z zgornjo nastavitvijo bo ustvarjen račun s podatki:",
"Failed to import the certificate" : "Uvažanje potrdila je spodletelo",
+ "Import S/MIME certificate" : "Uvozi potrdila S/MIME",
"S/MIME certificates" : "Potrdila S/MIME",
"Certificate name" : "Ime potrdila",
"E-mail address" : "Naslov elektronske pošte",
@@ -484,7 +485,6 @@ OC.L10N.register(
"Delete certificate" : "Izbriši potrdilo",
"No certificate imported yet" : "Ni še uvoženih potrdil",
"Import certificate" : "Uvozi potrdilo",
- "Import S/MIME certificate" : "Uvozi potrdila S/MIME",
"PKCS #12 Certificate" : "Potrdilo PKCS #12",
"PEM Certificate" : "Potrdilo PEM",
"Certificate" : "Potrdilo",
diff --git a/l10n/sl.json b/l10n/sl.json
index 67b39db649..158eebc32c 100644
--- a/l10n/sl.json
+++ b/l10n/sl.json
@@ -376,7 +376,7 @@
"Add tag" : "Dodaj oznako",
"Task created" : "Naloga je ustvarjena",
"Could not create task" : "Naloge ni mogoče ustvariti",
- "No calendars with task list support" : "Koledar s podporo seznama nalog",
+ "No calendars with task list support" : "Ni koledarjev s podporo seznama nalog",
"Could not load your message thread" : "Ni mogoče naložiti niti sporočil",
"The thread doesn't exist or has been deleted" : "Nit ne obstaja ali pa je bila izbrisana",
"Loading thread" : "Poteka nalaganje niti",
@@ -469,12 +469,13 @@
"SMTP" : "SMTP",
"Sieve" : "Sieve",
"Enable sieve integration" : "Omogoči združevalnik sieve",
- "The LDAP aliases integration reads an attribute from the configured LDAP directory to provision email aliases." : "PRogram LDAP pridobi podatke atributa, nastavljenega v imeniku LDAP za povezovanje elektronskih naslovov z vzdevki.",
+ "The LDAP aliases integration reads an attribute from the configured LDAP directory to provision email aliases." : "Program LDAP pridobi podatke atributa, nastavljenega v imeniku LDAP za povezovanje elektronskih naslovov z vzdevki.",
"A multi value attribute to provision email aliases. For each value an alias is created. Aliases existing in Nextcloud which are not in the LDAP directory are deleted." : "Nastavitev določa atribut z več vrednostmi za povezovanje vzdevkov elektronskih naslovov. Za vsako vrednost je ustvarjen vzdevek, tisti vzdevki, ki so vpisani v oblaku Nextcloud, a niso tudi v imeniku LDAP, se izbrišejo.",
"Save Config" : "Shrani nastavitve",
"Unprovision & Delete Config" : "Odstrani povezavo in izbriši nastavitve",
"With the settings above, the app will create account settings in the following way:" : "Z zgornjo nastavitvijo bo ustvarjen račun s podatki:",
"Failed to import the certificate" : "Uvažanje potrdila je spodletelo",
+ "Import S/MIME certificate" : "Uvozi potrdila S/MIME",
"S/MIME certificates" : "Potrdila S/MIME",
"Certificate name" : "Ime potrdila",
"E-mail address" : "Naslov elektronske pošte",
@@ -482,7 +483,6 @@
"Delete certificate" : "Izbriši potrdilo",
"No certificate imported yet" : "Ni še uvoženih potrdil",
"Import certificate" : "Uvozi potrdilo",
- "Import S/MIME certificate" : "Uvozi potrdila S/MIME",
"PKCS #12 Certificate" : "Potrdilo PKCS #12",
"PEM Certificate" : "Potrdilo PEM",
"Certificate" : "Potrdilo",
diff --git a/l10n/sr.js b/l10n/sr.js
index a48650a556..34c5da4c44 100644
--- a/l10n/sr.js
+++ b/l10n/sr.js
@@ -788,6 +788,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Сертификат је успешно увезен",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Увоз сертификата није успео. Молимо вас да обезбедите да ваш приватни кључ одговара сертификату и да није заштићен вишеделном лозинком.",
"Failed to import the certificate" : "Није успео увоз сертификата",
+ "Import S/MIME certificate" : "Увези S/MIME сертификат",
"S/MIME certificates" : "S/MIME сертификати",
"Certificate name" : "Име сертификата",
"E-mail address" : "Адреса е-поште",
@@ -795,7 +796,6 @@ OC.L10N.register(
"Delete certificate" : "Обриши сертификат",
"No certificate imported yet" : "Још увек није увезен ниједан сертификат",
"Import certificate" : "Увези сертификат",
- "Import S/MIME certificate" : "Увези S/MIME сертификат",
"PKCS #12 Certificate" : "PKCS #12 сертификат",
"PEM Certificate" : "PEM сертификат",
"Certificate" : "Сертификат",
diff --git a/l10n/sr.json b/l10n/sr.json
index 46749abac3..f41e5ed142 100644
--- a/l10n/sr.json
+++ b/l10n/sr.json
@@ -786,6 +786,7 @@
"Certificate imported successfully" : "Сертификат је успешно увезен",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Увоз сертификата није успео. Молимо вас да обезбедите да ваш приватни кључ одговара сертификату и да није заштићен вишеделном лозинком.",
"Failed to import the certificate" : "Није успео увоз сертификата",
+ "Import S/MIME certificate" : "Увези S/MIME сертификат",
"S/MIME certificates" : "S/MIME сертификати",
"Certificate name" : "Име сертификата",
"E-mail address" : "Адреса е-поште",
@@ -793,7 +794,6 @@
"Delete certificate" : "Обриши сертификат",
"No certificate imported yet" : "Још увек није увезен ниједан сертификат",
"Import certificate" : "Увези сертификат",
- "Import S/MIME certificate" : "Увези S/MIME сертификат",
"PKCS #12 Certificate" : "PKCS #12 сертификат",
"PEM Certificate" : "PEM сертификат",
"Certificate" : "Сертификат",
diff --git a/l10n/sv.js b/l10n/sv.js
index 30a878e3d1..6461e0326e 100644
--- a/l10n/sv.js
+++ b/l10n/sv.js
@@ -772,6 +772,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Certifikatet har importerats",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Det gick inte att importera certifikatet. Kontrollera att den privata nyckeln matchar certifikatet och inte är skyddad av ett löseord.",
"Failed to import the certificate" : "Kunde inte importera certifikatet",
+ "Import S/MIME certificate" : "Importera S/MIME certifikat",
"S/MIME certificates" : "S/MIME certifikat",
"Certificate name" : "Certifikatets namn",
"E-mail address" : "E-postadress",
@@ -779,7 +780,6 @@ OC.L10N.register(
"Delete certificate" : "Ta bort certifikat",
"No certificate imported yet" : "Certifikat saknas",
"Import certificate" : "Importera certifikat",
- "Import S/MIME certificate" : "Importera S/MIME certifikat",
"PKCS #12 Certificate" : "PKCS #12 Certifikat",
"PEM Certificate" : "PEM Certifikat",
"Certificate" : "Certifikat",
diff --git a/l10n/sv.json b/l10n/sv.json
index d0235ba83b..4b4550621d 100644
--- a/l10n/sv.json
+++ b/l10n/sv.json
@@ -770,6 +770,7 @@
"Certificate imported successfully" : "Certifikatet har importerats",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Det gick inte att importera certifikatet. Kontrollera att den privata nyckeln matchar certifikatet och inte är skyddad av ett löseord.",
"Failed to import the certificate" : "Kunde inte importera certifikatet",
+ "Import S/MIME certificate" : "Importera S/MIME certifikat",
"S/MIME certificates" : "S/MIME certifikat",
"Certificate name" : "Certifikatets namn",
"E-mail address" : "E-postadress",
@@ -777,7 +778,6 @@
"Delete certificate" : "Ta bort certifikat",
"No certificate imported yet" : "Certifikat saknas",
"Import certificate" : "Importera certifikat",
- "Import S/MIME certificate" : "Importera S/MIME certifikat",
"PKCS #12 Certificate" : "PKCS #12 Certifikat",
"PEM Certificate" : "PEM Certifikat",
"Certificate" : "Certifikat",
diff --git a/l10n/tr.js b/l10n/tr.js
index 47b1741452..363ed1b5cf 100644
--- a/l10n/tr.js
+++ b/l10n/tr.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "E-posta",
"You are reaching your mailbox quota limit for {account_email}" : "{account_email} e-posta kutusunun depolama alanı sınırına yaklaşıyorsunuz",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "E-posta kutunuzun depolama alanını {percentage} kadarını kullanıyorsunuz. Lütfen gereksiz e-postaları silerek biraz yer açın.",
+ "{account_email} has been delegated to you" : "{account_email} yetkisi size devredildi",
+ "{user} delegated {account} to you" : "{user}, {account} yetkisini size devretti",
+ "{account_email} is no longer delegated to you" : "{account_email} yetkisi devri sizden geri alındı",
+ "{user} revoked delegation for {account}" : "{user}, {account} yetki devrini geri aldı",
"Mail Application" : "E-posta uygulaması",
"Mails" : "E-postalar",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Gönderici e-posta adresi: %1$s adres defterinde yok. Ancak %2$s gönderici adı şu e-posta adresiyle birlikte adres defterinde var: %3$s",
@@ -30,7 +34,7 @@ OC.L10N.register(
"The app.mail.transport setting is not set to smtp. This configuration can cause issues with modern email security measures such as SPF and DKIM because emails are sent directly from the web server, which is often not properly configured for this purpose. To address this, we have discontinued support for the mail transport. Please remove app.mail.transport from your configuration to use the SMTP transport and hide this message. A properly configured SMTP setup is required to ensure email delivery." : "app.mail.transport ayarı SMTP olarak ayarlanmamış. Bu yapılandırma, e-postalar doğrudan internet sunucusundan gönderildiği için SPF ve DKIM gibi modern e-posta güvenlik önlemleriyle ilgili sorunlara neden olabilir. Bu sunucu genellikle bu amaç için düzgün şekilde yapılandırılmamıştır. Bu sorunu çözmek için, e-posta aktarımı desteğini sonlandırdık. Lütfen SMTP aktarımını kullanmak ve bu iletiyi gizlemek için yapılandırmanızdan app.mail.transport seçeneğini kaldırın. E-posta aktarımını sağlamak için düzgün şekilde yapılandırılmış bir SMTP kurulumu gerekir.",
"Mail account parameters, aliases and preferences" : "E-posta hesabı bilgileri, takma adlar ve tercihler",
"💌 A mail app for Nextcloud" : "💌 Nextcloud e-posta uygulaması",
- "**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 Nextcloud için bir e-posta uygulaması**\n\n- **🚀 Diğer Nextcloud uygulamalarıyla bütünleşik!** Şu anda Kişiler, Takvim ve Dosyalar ile. Daha fazlası gelecek.\n- **📥 Birden çok e-posta hesabı!** Kişisel ya da şirket hesabınızı mı kullanacaksınız? Sorun değil ve güzel bir birleşik gelen kutusu. Herhangi bir IMAP hesabını bağlayabilirsiniz.\n- **🔒 Şifrelenmiş e-postalar gönderin ve alın!** Harika [Mailvelope](https://mailvelope.com) tarayıcı eklentisi ile.\n- **🙈 Tekerleği yeniden keşfetmiyoruz!** Harika [Horde](https://www.horde.org) kitaplıklarını kullanıyoruz.\n- **📬 Kendi e-posta sunucunuzu barındırmak ister misiniz?** [Mail-in-a-Box](https://mailinabox.email) kurabileceğiniz için bunu yeniden yapmak zorunda değiliz!\n\n## Etik yapay zeka değerlendirmesi\n\n### Öncelikli gelen kutusu 🟢\n\nOlumlu:\n* Bu modelin eğitim ve çıkarım yazılımı açık kaynak kodludur.\n* Model, kullanıcının kendi verilerine göre yerinde oluşturulur ve eğitilir.\n* Eğitim verilerine kullanıcı erişebilir, bu da sapmayı denetlemeyi veya düzeltmeyi ya da başarımı ve CO2 kullanımını iyileştirebilmeyi sağlar.\n\n### Yazışma özetleri (abonelik)\n\n**Değerlendirme:** 🟢/🟡/🟠/🔴\n\nDeğerlendirme, kurulu olan yazı işleme arka yüzüne bağlıdır. Ayrıntılı bilgi almak için [değerlendirme özeti](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) bölümüne bakabilirsiniz.\n\n[Blogumuzda](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/) Nextcloud etik yapay zeka değerlendirmesi hakkında ayrıntılı bilgi alabilirsiniz.",
+ "**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 Nextcloud için bir e-posta uygulaması**\n\n- **🚀 Diğer Nextcloud uygulamalarıyla bütünleşik!** Şu anda Kişiler, Takvim ve Dosyalar ile. Daha fazlası gelecek.\n- **📥 Birden çok e-posta hesabı!** Kişisel ya da şirket hesabınızı mı kullanacaksınız? Sorun değil ve güzel bir birleşik gelen kutusu. Herhangi bir IMAP hesabını bağlayabilirsiniz.\n- **🔒 Şifrelenmiş e-postalar gönderin ve alın!** Harika [Mailvelope](https://mailvelope.com) tarayıcı eklentisi ile.\n- **🙈 Tekerleği yeniden keşfetmiyoruz!** Harika [Horde](https://www.horde.org) kitaplıklarını kullanıyoruz.\n- **📬 Kendi e-posta sunucunuzu barındırmak ister misiniz?** [Mail-in-a-Box](https://mailinabox.email) kurabileceğiniz için bunu yeniden yapmak zorunda değiliz!\n\n## Etik yapay zeka değerlendirmesi\n\n### Öncelikli gelen kutusu 🟢\n\nOlumlu:\n* Bu modelin eğitim ve çıkarım yazılımı açık kaynak kodludur.\n* Model, kullanıcının kendi verilerine göre yerinde oluşturulur ve eğitilir.\n* Eğitim verilerine kullanıcı erişebilir, bu da sapmayı denetlemeyi veya düzeltmeyi ya da başarımı ve CO2 kullanımını iyileştirebilmeyi sağlar.\n\n### Yazışma özetleri (abonelik)\n\n**Değerlendirme:** 🟢/🟡/🟠/🔴\n\nDeğerlendirme, kurulu olan yazı işleme arka yüzüne bağlıdır. Ayrıntılı bilgi almak için [değerlendirme özeti](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) bölümüne bakabilirsiniz.\n\n[Blogumuzda](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/) Nextcloud etik yapay zeka değerlendirmesi ile ilgili ayrıntılı bilgi alabilirsiniz.",
"Your session has expired. The page will be reloaded." : "Oturumunuzun geçerlilik süresi dolmuş. Sayfa yeniden yüklenecek.",
"Drafts are saved in:" : "Taslakların kaydedileceği yer:",
"Sent messages are saved in:" : "Gönderilmiş iletilerin kaydedileceği yer:",
@@ -93,6 +97,8 @@ OC.L10N.register(
"SMTP Port" : "SMTP bağlantı noktası",
"SMTP User" : "SMTP kullanıcı adı",
"SMTP Password" : "SMTP parolası",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google için, OAuth kimlik doğrulaması gerekir. Nextcloud yöneticiniz Google OAuth yapılandırmasını tamamladıysa, bunun yerine bir Google uygulama parolası kullanabilirsiniz.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft için, OAuth kimlik doğrulaması gerekir. Nextcloud yöneticinizden yönetici ayarlarından Microsoft OAuth yapılandırmasını tamamlamasını isteyin.",
"Account settings" : "Hesap ayarları",
"Aliases" : "Takma adlar",
"Alias to S/MIME certificate mapping" : "S/MIME sertifika eşleştirmesinin takma adı",
@@ -124,7 +130,7 @@ OC.L10N.register(
"Change name" : "Adı değiştir",
"Email address" : "E-posta adresi",
"Add alias" : "Takma ad ekle",
- "Create alias" : "Takma ad ekle",
+ "Create alias" : "Takma ad oluştur",
"Cancel" : "İptal",
"Search the body of messages in priority Inbox" : "Öncelikli gelen kutusundaki iletilerin içeriğinde arama",
"Activate" : "Etkinleştir",
@@ -135,6 +141,7 @@ OC.L10N.register(
"Mail settings" : "E-posta ayarları",
"General" : "Genel",
"Set as default mail app" : "Varsayılan e-posta uygulaması olarak ayarla",
+ "{email} (delegated)" : "{email} (devredildi)",
"Add mail account" : "E-posta hesabı ekle",
"Appearance" : "Görünüm",
"Show all messages in thread" : "Yazışmadaki tüm iletileri görüntüle",
@@ -253,7 +260,21 @@ OC.L10N.register(
"Expand composer" : "Oluşturucuyu genişlet",
"Close composer" : "Oluşturucuyu kapat",
"Confirm" : "Onayla",
+ "Delegate access" : "Yetkiyi devret",
"Revoke" : "Geçersiz kıl",
+ "{userId} will no longer be able to act on your behalf" : "{userId} artık sizin adınıza davranamayacak",
+ "Could not fetch delegates" : "Yetki devirleri alınamadı",
+ "Delegated access to {userId}" : "{userId} kullanıcısına yetki devredildi",
+ "Could not delegate access" : "Yetki devredilemedi",
+ "Revoked access for {userId}" : "{userId} yetki devri geri alındı",
+ "Could not revoke delegation" : "Yetki devri geri alınamadı",
+ "Delegation" : "Yetki devri",
+ "Allow users to send, receive, and delete mail on your behalf" : "Kullanıcıların sizin adınıza e-posta göndermesine, almasına ve silmesine izin verin",
+ "Revoke access" : "Yetki devrini geri al",
+ "Add delegate" : "Yetki devri ekle",
+ "Select a user" : "Bir kullanıcı seçin",
+ "They will be able to send, receive, and delete mail on your behalf" : "Sizin adınıza eposta gönderebilecek, alabilecek ve silebilecek",
+ "Revoke access?" : "Yetki devri geri alınsın mı?",
"Tag: {name} deleted" : "Etiket: {name} silindi",
"An error occurred, unable to delete the tag." : "Bir sorun çıktı. Etiket silinemedi.",
"The tag will be deleted from all messages." : "Etiket tüm iletilerden silinecek.",
@@ -307,7 +328,7 @@ OC.L10N.register(
"Set custom snooze" : "Özel erteleme ayarla",
"Edit as new message" : "Yeni ileti olarak düzenle",
"Reply with meeting" : "Toplamtı ile yanıtla",
- "Create task" : "Görev ekle",
+ "Create task" : "Görev oluştur",
"Download message" : "İletiyi indir",
"Back to all actions" : "Tüm işlemlere dön",
"Manage quick actions" : "Hızlı işlem yönetimi",
@@ -329,15 +350,15 @@ OC.L10N.register(
"Mark as unimportant" : "Önemsiz olarak işaretle",
"Mark as important" : "Önemli olarak işaretle",
"Report this bug" : "Bu hatayı bildirin",
- "Event created" : "Etkinlik eklendi",
+ "Event created" : "Etkinlik oluşturuldu",
"Could not create event" : "Etkinlik oluşturulamadı",
- "Create event" : "Etkinlik ekle",
+ "Create event" : "Etkinlik oluştur",
"All day" : "Tüm gün",
"Attendees" : "Katılanlar",
"You can only invite attendees if your account has an email address set" : "Katılımcıları davet edebilmek için hesabınızın e-posta adresini ayarlamalısınız",
"Select calendar" : "Takvim seçin",
"Description" : "Açıklama",
- "Create" : "Ekle",
+ "Create" : "Oluştur",
"This event was updated" : "Bu etkinlik güncellendi",
"{attendeeName} accepted your invitation" : "{attendeeName} davetinizi kabul etti",
"{attendeeName} tentatively accepted your invitation" : "{attendeeName} davetinizi belirsiz olarak kabul etti",
@@ -410,8 +431,10 @@ OC.L10N.register(
"Print message" : "İletiyi yazdır",
"Create mail filter" : "E-posta süzgeçi oluştur",
"Download thread data for debugging" : "Hata ayıklama için yazışma verilerini indir",
+ "Suggested replies are using AI" : "Yapay zeka ile önerilen yanıtlar",
"Message body" : "İleti gövdesi",
"Warning: The S/MIME signature of this message is unverified. The sender might be impersonating someone!" : "Uyarı: Bu iletinin S/MIME imzası doğrulanmamış. Gönderici, başka birinin kimliğine bürünmüş olabilir!",
+ "AI info" : "Yapay zeka bilgileri",
"Unnamed" : "Adsız",
"Embedded message" : "Gömülü ileti",
"Attachment saved to Files" : "Ek dosya Dosyalar uygulamasına kaydedildi.",
@@ -448,8 +471,10 @@ OC.L10N.register(
"Remove account" : "Hesabı sil",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email} hesabı ve ön belleğe alınmış verileri Nextcloud üzerinden silinecek ancak e-posta hizmeti sağlayıcınız üzerinden silinmeyecek.",
"Remove {email}" : "{email} sil",
+ "could not delete account" : "hesap silinemedi",
"Provisioned account is disabled" : "Bu hesap kullanımdan kaldırılmış",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Bu hesabı kullanıma almak için lütfen bir parola ile oturum açın. Geçerli oturum, tek oturum açma ya da WebAuthn gibi parolasız kimlik doğrulama kullanıyor.",
+ "Delegate account" : "Hesap yetkisini devret",
"Show only subscribed folders" : "Yalnızca abone olunmuş klasörler görüntülensin",
"Add folder" : "Klasör ekle",
"Folder name" : "Klasör adı",
@@ -592,12 +617,12 @@ OC.L10N.register(
"Tag name is a hidden system tag" : "Etiket adı sistem tarafından kullanılan bir gizli ad",
"Tag already exists" : "Etiket zaten var",
"Tag name cannot be empty" : "Etiket adı boş olamaz",
- "An error occurred, unable to create the tag." : "Etiket eklenirken bir sorun çıktı.",
+ "An error occurred, unable to create the tag." : "Etiket oluşturulurken bir sorun çıktı.",
"Add default tags" : "Varsayılan etiketler ekle",
"Add tag" : "Etiket ekle",
"Saving tag …" : "Etiket kaydediliyor…",
- "Task created" : "Görev eklendi",
- "Could not create task" : "Görev eklenemedi",
+ "Task created" : "Görev oluşturuldu",
+ "Could not create task" : "Görev oluşturulamadı",
"No calendars with task list support" : "Görev listesi olan bir takvim yok",
"Summarizing thread failed." : "Yazışma özetlenemedi.",
"Could not load your message thread" : "İleti yazışmanız yüklenemedi",
@@ -622,7 +647,9 @@ OC.L10N.register(
"Reply to sender only" : "Yalnızca gönderene yanıtla",
"Mark as unfavorite" : "Sık kullanılanlardan kaldır",
"Mark as favorite" : "Sık kullanılanlara ekle",
- "To:" : "Bitiş:",
+ "To:" : "Kime:",
+ "Cc:" : "Kopya:",
+ "Bcc:" : "Gizli kopya:",
"Unsubscribe via link" : "Bağlantı ile abonelikten ayrıl",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Abonelikten ayrıldığınızda {sender} e-posta listesinden iletileri almayacaksınız ",
"Send unsubscribe email" : "Abonelikten ayrılma e-postası gönder",
@@ -819,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Sertifika içe aktarıldı",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Sertifika içe aktarılamadı. Lütfen kişisel anahtarın sertifika ile eşleştiğinden ve bir parola ile korunmadığından emin olun.",
"Failed to import the certificate" : "Sertifika içe aktarılamadı",
+ "Import S/MIME certificate" : "S/MIME sertifikasını içe aktar",
"S/MIME certificates" : "S/MIME sertifikaları",
"Certificate name" : "Sertifika adı",
"E-mail address" : "E-posta adresi",
@@ -826,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "Sertifikayı sil",
"No certificate imported yet" : "henüz bir sertifika içe aktarılmamış",
"Import certificate" : "Sertifikayı içe aktar",
- "Import S/MIME certificate" : "S/MIME sertifikasını içe aktar",
"PKCS #12 Certificate" : "PKCS #12 sertifikası",
"PEM Certificate" : "PEM sertifikası",
"Certificate" : "Sertifika",
@@ -873,6 +900,7 @@ OC.L10N.register(
"Discard changes" : "Değişiklikleri yok say",
"Discard unsaved changes" : "Kaydedilmemiş değişiklikleri yok say",
"Keep editing message" : "İletiyi düzenlemeyi sürdür",
+ "(All or part of this reply was generated by AI)" : "(Bu yanıtın tümü ya da bir bölümü yapay zeka ile oluşturulmuştur)",
"Attachments were not copied. Please add them manually." : "Ek dosyalar kopyalanmadı. Lütfen el ile ekleyin.",
"Could not create snooze mailbox" : "Erteleme kutusu oluşturulamadı",
"Sorry, the message could not be loaded. The draft may no longer exist. Please refresh the page and try again." : "Ne yazık ki, ileti yüklenemedi. Taslak artık var olmayabilir. Lütfen sayfayı yenileyip yeniden deneyin.",
diff --git a/l10n/tr.json b/l10n/tr.json
index b75501f7d4..3eb3e4b2c5 100644
--- a/l10n/tr.json
+++ b/l10n/tr.json
@@ -12,6 +12,10 @@
"Mail" : "E-posta",
"You are reaching your mailbox quota limit for {account_email}" : "{account_email} e-posta kutusunun depolama alanı sınırına yaklaşıyorsunuz",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "E-posta kutunuzun depolama alanını {percentage} kadarını kullanıyorsunuz. Lütfen gereksiz e-postaları silerek biraz yer açın.",
+ "{account_email} has been delegated to you" : "{account_email} yetkisi size devredildi",
+ "{user} delegated {account} to you" : "{user}, {account} yetkisini size devretti",
+ "{account_email} is no longer delegated to you" : "{account_email} yetkisi devri sizden geri alındı",
+ "{user} revoked delegation for {account}" : "{user}, {account} yetki devrini geri aldı",
"Mail Application" : "E-posta uygulaması",
"Mails" : "E-postalar",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Gönderici e-posta adresi: %1$s adres defterinde yok. Ancak %2$s gönderici adı şu e-posta adresiyle birlikte adres defterinde var: %3$s",
@@ -28,7 +32,7 @@
"The app.mail.transport setting is not set to smtp. This configuration can cause issues with modern email security measures such as SPF and DKIM because emails are sent directly from the web server, which is often not properly configured for this purpose. To address this, we have discontinued support for the mail transport. Please remove app.mail.transport from your configuration to use the SMTP transport and hide this message. A properly configured SMTP setup is required to ensure email delivery." : "app.mail.transport ayarı SMTP olarak ayarlanmamış. Bu yapılandırma, e-postalar doğrudan internet sunucusundan gönderildiği için SPF ve DKIM gibi modern e-posta güvenlik önlemleriyle ilgili sorunlara neden olabilir. Bu sunucu genellikle bu amaç için düzgün şekilde yapılandırılmamıştır. Bu sorunu çözmek için, e-posta aktarımı desteğini sonlandırdık. Lütfen SMTP aktarımını kullanmak ve bu iletiyi gizlemek için yapılandırmanızdan app.mail.transport seçeneğini kaldırın. E-posta aktarımını sağlamak için düzgün şekilde yapılandırılmış bir SMTP kurulumu gerekir.",
"Mail account parameters, aliases and preferences" : "E-posta hesabı bilgileri, takma adlar ve tercihler",
"💌 A mail app for Nextcloud" : "💌 Nextcloud e-posta uygulaması",
- "**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 Nextcloud için bir e-posta uygulaması**\n\n- **🚀 Diğer Nextcloud uygulamalarıyla bütünleşik!** Şu anda Kişiler, Takvim ve Dosyalar ile. Daha fazlası gelecek.\n- **📥 Birden çok e-posta hesabı!** Kişisel ya da şirket hesabınızı mı kullanacaksınız? Sorun değil ve güzel bir birleşik gelen kutusu. Herhangi bir IMAP hesabını bağlayabilirsiniz.\n- **🔒 Şifrelenmiş e-postalar gönderin ve alın!** Harika [Mailvelope](https://mailvelope.com) tarayıcı eklentisi ile.\n- **🙈 Tekerleği yeniden keşfetmiyoruz!** Harika [Horde](https://www.horde.org) kitaplıklarını kullanıyoruz.\n- **📬 Kendi e-posta sunucunuzu barındırmak ister misiniz?** [Mail-in-a-Box](https://mailinabox.email) kurabileceğiniz için bunu yeniden yapmak zorunda değiliz!\n\n## Etik yapay zeka değerlendirmesi\n\n### Öncelikli gelen kutusu 🟢\n\nOlumlu:\n* Bu modelin eğitim ve çıkarım yazılımı açık kaynak kodludur.\n* Model, kullanıcının kendi verilerine göre yerinde oluşturulur ve eğitilir.\n* Eğitim verilerine kullanıcı erişebilir, bu da sapmayı denetlemeyi veya düzeltmeyi ya da başarımı ve CO2 kullanımını iyileştirebilmeyi sağlar.\n\n### Yazışma özetleri (abonelik)\n\n**Değerlendirme:** 🟢/🟡/🟠/🔴\n\nDeğerlendirme, kurulu olan yazı işleme arka yüzüne bağlıdır. Ayrıntılı bilgi almak için [değerlendirme özeti](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) bölümüne bakabilirsiniz.\n\n[Blogumuzda](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/) Nextcloud etik yapay zeka değerlendirmesi hakkında ayrıntılı bilgi alabilirsiniz.",
+ "**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 Nextcloud için bir e-posta uygulaması**\n\n- **🚀 Diğer Nextcloud uygulamalarıyla bütünleşik!** Şu anda Kişiler, Takvim ve Dosyalar ile. Daha fazlası gelecek.\n- **📥 Birden çok e-posta hesabı!** Kişisel ya da şirket hesabınızı mı kullanacaksınız? Sorun değil ve güzel bir birleşik gelen kutusu. Herhangi bir IMAP hesabını bağlayabilirsiniz.\n- **🔒 Şifrelenmiş e-postalar gönderin ve alın!** Harika [Mailvelope](https://mailvelope.com) tarayıcı eklentisi ile.\n- **🙈 Tekerleği yeniden keşfetmiyoruz!** Harika [Horde](https://www.horde.org) kitaplıklarını kullanıyoruz.\n- **📬 Kendi e-posta sunucunuzu barındırmak ister misiniz?** [Mail-in-a-Box](https://mailinabox.email) kurabileceğiniz için bunu yeniden yapmak zorunda değiliz!\n\n## Etik yapay zeka değerlendirmesi\n\n### Öncelikli gelen kutusu 🟢\n\nOlumlu:\n* Bu modelin eğitim ve çıkarım yazılımı açık kaynak kodludur.\n* Model, kullanıcının kendi verilerine göre yerinde oluşturulur ve eğitilir.\n* Eğitim verilerine kullanıcı erişebilir, bu da sapmayı denetlemeyi veya düzeltmeyi ya da başarımı ve CO2 kullanımını iyileştirebilmeyi sağlar.\n\n### Yazışma özetleri (abonelik)\n\n**Değerlendirme:** 🟢/🟡/🟠/🔴\n\nDeğerlendirme, kurulu olan yazı işleme arka yüzüne bağlıdır. Ayrıntılı bilgi almak için [değerlendirme özeti](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) bölümüne bakabilirsiniz.\n\n[Blogumuzda](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/) Nextcloud etik yapay zeka değerlendirmesi ile ilgili ayrıntılı bilgi alabilirsiniz.",
"Your session has expired. The page will be reloaded." : "Oturumunuzun geçerlilik süresi dolmuş. Sayfa yeniden yüklenecek.",
"Drafts are saved in:" : "Taslakların kaydedileceği yer:",
"Sent messages are saved in:" : "Gönderilmiş iletilerin kaydedileceği yer:",
@@ -91,6 +95,8 @@
"SMTP Port" : "SMTP bağlantı noktası",
"SMTP User" : "SMTP kullanıcı adı",
"SMTP Password" : "SMTP parolası",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google için, OAuth kimlik doğrulaması gerekir. Nextcloud yöneticiniz Google OAuth yapılandırmasını tamamladıysa, bunun yerine bir Google uygulama parolası kullanabilirsiniz.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft için, OAuth kimlik doğrulaması gerekir. Nextcloud yöneticinizden yönetici ayarlarından Microsoft OAuth yapılandırmasını tamamlamasını isteyin.",
"Account settings" : "Hesap ayarları",
"Aliases" : "Takma adlar",
"Alias to S/MIME certificate mapping" : "S/MIME sertifika eşleştirmesinin takma adı",
@@ -122,7 +128,7 @@
"Change name" : "Adı değiştir",
"Email address" : "E-posta adresi",
"Add alias" : "Takma ad ekle",
- "Create alias" : "Takma ad ekle",
+ "Create alias" : "Takma ad oluştur",
"Cancel" : "İptal",
"Search the body of messages in priority Inbox" : "Öncelikli gelen kutusundaki iletilerin içeriğinde arama",
"Activate" : "Etkinleştir",
@@ -133,6 +139,7 @@
"Mail settings" : "E-posta ayarları",
"General" : "Genel",
"Set as default mail app" : "Varsayılan e-posta uygulaması olarak ayarla",
+ "{email} (delegated)" : "{email} (devredildi)",
"Add mail account" : "E-posta hesabı ekle",
"Appearance" : "Görünüm",
"Show all messages in thread" : "Yazışmadaki tüm iletileri görüntüle",
@@ -251,7 +258,21 @@
"Expand composer" : "Oluşturucuyu genişlet",
"Close composer" : "Oluşturucuyu kapat",
"Confirm" : "Onayla",
+ "Delegate access" : "Yetkiyi devret",
"Revoke" : "Geçersiz kıl",
+ "{userId} will no longer be able to act on your behalf" : "{userId} artık sizin adınıza davranamayacak",
+ "Could not fetch delegates" : "Yetki devirleri alınamadı",
+ "Delegated access to {userId}" : "{userId} kullanıcısına yetki devredildi",
+ "Could not delegate access" : "Yetki devredilemedi",
+ "Revoked access for {userId}" : "{userId} yetki devri geri alındı",
+ "Could not revoke delegation" : "Yetki devri geri alınamadı",
+ "Delegation" : "Yetki devri",
+ "Allow users to send, receive, and delete mail on your behalf" : "Kullanıcıların sizin adınıza e-posta göndermesine, almasına ve silmesine izin verin",
+ "Revoke access" : "Yetki devrini geri al",
+ "Add delegate" : "Yetki devri ekle",
+ "Select a user" : "Bir kullanıcı seçin",
+ "They will be able to send, receive, and delete mail on your behalf" : "Sizin adınıza eposta gönderebilecek, alabilecek ve silebilecek",
+ "Revoke access?" : "Yetki devri geri alınsın mı?",
"Tag: {name} deleted" : "Etiket: {name} silindi",
"An error occurred, unable to delete the tag." : "Bir sorun çıktı. Etiket silinemedi.",
"The tag will be deleted from all messages." : "Etiket tüm iletilerden silinecek.",
@@ -305,7 +326,7 @@
"Set custom snooze" : "Özel erteleme ayarla",
"Edit as new message" : "Yeni ileti olarak düzenle",
"Reply with meeting" : "Toplamtı ile yanıtla",
- "Create task" : "Görev ekle",
+ "Create task" : "Görev oluştur",
"Download message" : "İletiyi indir",
"Back to all actions" : "Tüm işlemlere dön",
"Manage quick actions" : "Hızlı işlem yönetimi",
@@ -327,15 +348,15 @@
"Mark as unimportant" : "Önemsiz olarak işaretle",
"Mark as important" : "Önemli olarak işaretle",
"Report this bug" : "Bu hatayı bildirin",
- "Event created" : "Etkinlik eklendi",
+ "Event created" : "Etkinlik oluşturuldu",
"Could not create event" : "Etkinlik oluşturulamadı",
- "Create event" : "Etkinlik ekle",
+ "Create event" : "Etkinlik oluştur",
"All day" : "Tüm gün",
"Attendees" : "Katılanlar",
"You can only invite attendees if your account has an email address set" : "Katılımcıları davet edebilmek için hesabınızın e-posta adresini ayarlamalısınız",
"Select calendar" : "Takvim seçin",
"Description" : "Açıklama",
- "Create" : "Ekle",
+ "Create" : "Oluştur",
"This event was updated" : "Bu etkinlik güncellendi",
"{attendeeName} accepted your invitation" : "{attendeeName} davetinizi kabul etti",
"{attendeeName} tentatively accepted your invitation" : "{attendeeName} davetinizi belirsiz olarak kabul etti",
@@ -408,8 +429,10 @@
"Print message" : "İletiyi yazdır",
"Create mail filter" : "E-posta süzgeçi oluştur",
"Download thread data for debugging" : "Hata ayıklama için yazışma verilerini indir",
+ "Suggested replies are using AI" : "Yapay zeka ile önerilen yanıtlar",
"Message body" : "İleti gövdesi",
"Warning: The S/MIME signature of this message is unverified. The sender might be impersonating someone!" : "Uyarı: Bu iletinin S/MIME imzası doğrulanmamış. Gönderici, başka birinin kimliğine bürünmüş olabilir!",
+ "AI info" : "Yapay zeka bilgileri",
"Unnamed" : "Adsız",
"Embedded message" : "Gömülü ileti",
"Attachment saved to Files" : "Ek dosya Dosyalar uygulamasına kaydedildi.",
@@ -446,8 +469,10 @@
"Remove account" : "Hesabı sil",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "{email} hesabı ve ön belleğe alınmış verileri Nextcloud üzerinden silinecek ancak e-posta hizmeti sağlayıcınız üzerinden silinmeyecek.",
"Remove {email}" : "{email} sil",
+ "could not delete account" : "hesap silinemedi",
"Provisioned account is disabled" : "Bu hesap kullanımdan kaldırılmış",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Bu hesabı kullanıma almak için lütfen bir parola ile oturum açın. Geçerli oturum, tek oturum açma ya da WebAuthn gibi parolasız kimlik doğrulama kullanıyor.",
+ "Delegate account" : "Hesap yetkisini devret",
"Show only subscribed folders" : "Yalnızca abone olunmuş klasörler görüntülensin",
"Add folder" : "Klasör ekle",
"Folder name" : "Klasör adı",
@@ -590,12 +615,12 @@
"Tag name is a hidden system tag" : "Etiket adı sistem tarafından kullanılan bir gizli ad",
"Tag already exists" : "Etiket zaten var",
"Tag name cannot be empty" : "Etiket adı boş olamaz",
- "An error occurred, unable to create the tag." : "Etiket eklenirken bir sorun çıktı.",
+ "An error occurred, unable to create the tag." : "Etiket oluşturulurken bir sorun çıktı.",
"Add default tags" : "Varsayılan etiketler ekle",
"Add tag" : "Etiket ekle",
"Saving tag …" : "Etiket kaydediliyor…",
- "Task created" : "Görev eklendi",
- "Could not create task" : "Görev eklenemedi",
+ "Task created" : "Görev oluşturuldu",
+ "Could not create task" : "Görev oluşturulamadı",
"No calendars with task list support" : "Görev listesi olan bir takvim yok",
"Summarizing thread failed." : "Yazışma özetlenemedi.",
"Could not load your message thread" : "İleti yazışmanız yüklenemedi",
@@ -620,7 +645,9 @@
"Reply to sender only" : "Yalnızca gönderene yanıtla",
"Mark as unfavorite" : "Sık kullanılanlardan kaldır",
"Mark as favorite" : "Sık kullanılanlara ekle",
- "To:" : "Bitiş:",
+ "To:" : "Kime:",
+ "Cc:" : "Kopya:",
+ "Bcc:" : "Gizli kopya:",
"Unsubscribe via link" : "Bağlantı ile abonelikten ayrıl",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Abonelikten ayrıldığınızda {sender} e-posta listesinden iletileri almayacaksınız ",
"Send unsubscribe email" : "Abonelikten ayrılma e-postası gönder",
@@ -817,6 +844,7 @@
"Certificate imported successfully" : "Sertifika içe aktarıldı",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Sertifika içe aktarılamadı. Lütfen kişisel anahtarın sertifika ile eşleştiğinden ve bir parola ile korunmadığından emin olun.",
"Failed to import the certificate" : "Sertifika içe aktarılamadı",
+ "Import S/MIME certificate" : "S/MIME sertifikasını içe aktar",
"S/MIME certificates" : "S/MIME sertifikaları",
"Certificate name" : "Sertifika adı",
"E-mail address" : "E-posta adresi",
@@ -824,7 +852,6 @@
"Delete certificate" : "Sertifikayı sil",
"No certificate imported yet" : "henüz bir sertifika içe aktarılmamış",
"Import certificate" : "Sertifikayı içe aktar",
- "Import S/MIME certificate" : "S/MIME sertifikasını içe aktar",
"PKCS #12 Certificate" : "PKCS #12 sertifikası",
"PEM Certificate" : "PEM sertifikası",
"Certificate" : "Sertifika",
@@ -871,6 +898,7 @@
"Discard changes" : "Değişiklikleri yok say",
"Discard unsaved changes" : "Kaydedilmemiş değişiklikleri yok say",
"Keep editing message" : "İletiyi düzenlemeyi sürdür",
+ "(All or part of this reply was generated by AI)" : "(Bu yanıtın tümü ya da bir bölümü yapay zeka ile oluşturulmuştur)",
"Attachments were not copied. Please add them manually." : "Ek dosyalar kopyalanmadı. Lütfen el ile ekleyin.",
"Could not create snooze mailbox" : "Erteleme kutusu oluşturulamadı",
"Sorry, the message could not be loaded. The draft may no longer exist. Please refresh the page and try again." : "Ne yazık ki, ileti yüklenemedi. Taslak artık var olmayabilir. Lütfen sayfayı yenileyip yeniden deneyin.",
diff --git a/l10n/ug.js b/l10n/ug.js
index 6398c1f38e..5cf25ce5c3 100644
--- a/l10n/ug.js
+++ b/l10n/ug.js
@@ -812,6 +812,7 @@ OC.L10N.register(
"Certificate imported successfully" : "مۇۋەپپەقىيەتلىك ئىمپورت قىلىنغان گۇۋاھنامە",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "گۇۋاھنامىنى ئەكىرىش مەغلۇب بولدى. شەخسىي ئاچقۇچنىڭ گۇۋاھنامىگە ماس كېلىدىغانلىقى ۋە ئىم بىلەن قوغدالمىغانلىقىغا كاپالەتلىك قىلىڭ.",
"Failed to import the certificate" : "گۇۋاھنامىنى ئەكىرىش مەغلۇب بولدى",
+ "Import S/MIME certificate" : "S/MIME گۇۋاھنامىسىنى ئەكىرىڭ",
"S/MIME certificates" : "S/MIME گۇۋاھنامىسى",
"Certificate name" : "گۇۋاھنامە ئىسمى",
"E-mail address" : "ئېلېكترونلۇق خەت ئادرېسى",
@@ -819,7 +820,6 @@ OC.L10N.register(
"Delete certificate" : "گۇۋاھنامىنى ئۆچۈرۈڭ",
"No certificate imported yet" : "تېخى ئىمپورت قىلىنغان گۇۋاھنامە يوق",
"Import certificate" : "گۇۋاھنامە ئەكىرىش",
- "Import S/MIME certificate" : "S/MIME گۇۋاھنامىسىنى ئەكىرىڭ",
"PKCS #12 Certificate" : "PKCS # 12 گۇۋاھنامىسى",
"PEM Certificate" : "PEM گۇۋاھنامىسى",
"Certificate" : "گۇۋاھنامە",
diff --git a/l10n/ug.json b/l10n/ug.json
index 60c9af716b..80b8f04ca2 100644
--- a/l10n/ug.json
+++ b/l10n/ug.json
@@ -810,6 +810,7 @@
"Certificate imported successfully" : "مۇۋەپپەقىيەتلىك ئىمپورت قىلىنغان گۇۋاھنامە",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "گۇۋاھنامىنى ئەكىرىش مەغلۇب بولدى. شەخسىي ئاچقۇچنىڭ گۇۋاھنامىگە ماس كېلىدىغانلىقى ۋە ئىم بىلەن قوغدالمىغانلىقىغا كاپالەتلىك قىلىڭ.",
"Failed to import the certificate" : "گۇۋاھنامىنى ئەكىرىش مەغلۇب بولدى",
+ "Import S/MIME certificate" : "S/MIME گۇۋاھنامىسىنى ئەكىرىڭ",
"S/MIME certificates" : "S/MIME گۇۋاھنامىسى",
"Certificate name" : "گۇۋاھنامە ئىسمى",
"E-mail address" : "ئېلېكترونلۇق خەت ئادرېسى",
@@ -817,7 +818,6 @@
"Delete certificate" : "گۇۋاھنامىنى ئۆچۈرۈڭ",
"No certificate imported yet" : "تېخى ئىمپورت قىلىنغان گۇۋاھنامە يوق",
"Import certificate" : "گۇۋاھنامە ئەكىرىش",
- "Import S/MIME certificate" : "S/MIME گۇۋاھنامىسىنى ئەكىرىڭ",
"PKCS #12 Certificate" : "PKCS # 12 گۇۋاھنامىسى",
"PEM Certificate" : "PEM گۇۋاھنامىسى",
"Certificate" : "گۇۋاھنامە",
diff --git a/l10n/uk.js b/l10n/uk.js
index 6e519b6896..7c804df7d2 100644
--- a/l10n/uk.js
+++ b/l10n/uk.js
@@ -765,6 +765,7 @@ OC.L10N.register(
"Certificate imported successfully" : "Сертифікат успішно імпортовано",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Не вдалося імпортувати сертифікат. Будь ласка, переконайтеся, що приватний ключ збігається з сертифікатом і не захищений парольною фразою.",
"Failed to import the certificate" : "Не вдалося імпортувати сертифікат",
+ "Import S/MIME certificate" : "Імпортувати S/MIME сертифікат",
"S/MIME certificates" : "S/MIME сертифікати",
"Certificate name" : "Назва сертифікату",
"E-mail address" : "Електронна адреса",
@@ -772,7 +773,6 @@ OC.L10N.register(
"Delete certificate" : "Видалити сертифікат",
"No certificate imported yet" : "Сертифікат ще не імпортовано",
"Import certificate" : "Сертифікат на імпорт",
- "Import S/MIME certificate" : "Імпортувати S/MIME сертифікат",
"PKCS #12 Certificate" : "Сертифікат PKCS #12",
"PEM Certificate" : "Сертифікат PEM",
"Certificate" : "Сертифікат",
diff --git a/l10n/uk.json b/l10n/uk.json
index 3ad8e90c7c..4c454dc939 100644
--- a/l10n/uk.json
+++ b/l10n/uk.json
@@ -763,6 +763,7 @@
"Certificate imported successfully" : "Сертифікат успішно імпортовано",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Не вдалося імпортувати сертифікат. Будь ласка, переконайтеся, що приватний ключ збігається з сертифікатом і не захищений парольною фразою.",
"Failed to import the certificate" : "Не вдалося імпортувати сертифікат",
+ "Import S/MIME certificate" : "Імпортувати S/MIME сертифікат",
"S/MIME certificates" : "S/MIME сертифікати",
"Certificate name" : "Назва сертифікату",
"E-mail address" : "Електронна адреса",
@@ -770,7 +771,6 @@
"Delete certificate" : "Видалити сертифікат",
"No certificate imported yet" : "Сертифікат ще не імпортовано",
"Import certificate" : "Сертифікат на імпорт",
- "Import S/MIME certificate" : "Імпортувати S/MIME сертифікат",
"PKCS #12 Certificate" : "Сертифікат PKCS #12",
"PEM Certificate" : "Сертифікат PEM",
"Certificate" : "Сертифікат",
diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js
index 62af5d0d07..6e5d8b8a1d 100644
--- a/l10n/zh_CN.js
+++ b/l10n/zh_CN.js
@@ -842,6 +842,7 @@ OC.L10N.register(
"Certificate imported successfully" : "导入证书成功",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "无法导入证书。请确保私钥与您的证书相符,并且不受口令保护。",
"Failed to import the certificate" : "导入证书失败",
+ "Import S/MIME certificate" : "导入 S/MIME 证书",
"S/MIME certificates" : "S/MIME 证书",
"Certificate name" : "证书名称",
"E-mail address" : "电子邮件地址",
@@ -849,7 +850,6 @@ OC.L10N.register(
"Delete certificate" : "删除证书",
"No certificate imported yet" : "尚未导入证书",
"Import certificate" : "导入证书",
- "Import S/MIME certificate" : "导入 S/MIME 证书",
"PKCS #12 Certificate" : "PKCS #12 证书",
"PEM Certificate" : "PEM 证书",
"Certificate" : "证书",
diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json
index 4f5aaad39d..383a63b453 100644
--- a/l10n/zh_CN.json
+++ b/l10n/zh_CN.json
@@ -840,6 +840,7 @@
"Certificate imported successfully" : "导入证书成功",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "无法导入证书。请确保私钥与您的证书相符,并且不受口令保护。",
"Failed to import the certificate" : "导入证书失败",
+ "Import S/MIME certificate" : "导入 S/MIME 证书",
"S/MIME certificates" : "S/MIME 证书",
"Certificate name" : "证书名称",
"E-mail address" : "电子邮件地址",
@@ -847,7 +848,6 @@
"Delete certificate" : "删除证书",
"No certificate imported yet" : "尚未导入证书",
"Import certificate" : "导入证书",
- "Import S/MIME certificate" : "导入 S/MIME 证书",
"PKCS #12 Certificate" : "PKCS #12 证书",
"PEM Certificate" : "PEM 证书",
"Certificate" : "证书",
diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js
index 60493ff6ea..837fe3d5ab 100644
--- a/l10n/zh_HK.js
+++ b/l10n/zh_HK.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "郵件",
"You are reaching your mailbox quota limit for {account_email}" : "您即將達到 {account_email} 的郵箱配額限制",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "您目前使用了郵箱存儲空間的 {percentage} ,請刪除不必要的郵件以釋放空間。",
+ "{account_email} has been delegated to you" : "{account_email} 已委託給您",
+ "{user} delegated {account} to you" : "{user} 已委託 {account} 給您",
+ "{account_email} is no longer delegated to you" : "{account_email} 不再委託給您",
+ "{user} revoked delegation for {account}" : "{user} 撤銷了 {account} 的委託",
"Mail Application" : "郵件應用程式",
"Mails" : "郵件",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "寄件人電郵地址:%1$s 不在通訊錄中,但寄件人名稱:%2$s 在通訊錄中,其電郵地址為:%3$s",
@@ -842,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "成功導入了證書",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "無法導入證書。請確保私鑰與證書匹配並且不受密碼片語保護。",
"Failed to import the certificate" : "導入證書失敗",
+ "Import S/MIME certificate" : "導入 S/MIME 證書",
"S/MIME certificates" : "S/MIME 證書",
"Certificate name" : "證書名稱",
"E-mail address" : "電郵地址",
@@ -849,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "刪除證書",
"No certificate imported yet" : "尚未導入證書",
"Import certificate" : "導入證書",
- "Import S/MIME certificate" : "導入 S/MIME 證書",
"PKCS #12 Certificate" : "PKCS #12 證書",
"PEM Certificate" : "PEM 證書",
"Certificate" : "憑證",
diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json
index b104c58c4a..5f560289f6 100644
--- a/l10n/zh_HK.json
+++ b/l10n/zh_HK.json
@@ -12,6 +12,10 @@
"Mail" : "郵件",
"You are reaching your mailbox quota limit for {account_email}" : "您即將達到 {account_email} 的郵箱配額限制",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "您目前使用了郵箱存儲空間的 {percentage} ,請刪除不必要的郵件以釋放空間。",
+ "{account_email} has been delegated to you" : "{account_email} 已委託給您",
+ "{user} delegated {account} to you" : "{user} 已委託 {account} 給您",
+ "{account_email} is no longer delegated to you" : "{account_email} 不再委託給您",
+ "{user} revoked delegation for {account}" : "{user} 撤銷了 {account} 的委託",
"Mail Application" : "郵件應用程式",
"Mails" : "郵件",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "寄件人電郵地址:%1$s 不在通訊錄中,但寄件人名稱:%2$s 在通訊錄中,其電郵地址為:%3$s",
@@ -840,6 +844,7 @@
"Certificate imported successfully" : "成功導入了證書",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "無法導入證書。請確保私鑰與證書匹配並且不受密碼片語保護。",
"Failed to import the certificate" : "導入證書失敗",
+ "Import S/MIME certificate" : "導入 S/MIME 證書",
"S/MIME certificates" : "S/MIME 證書",
"Certificate name" : "證書名稱",
"E-mail address" : "電郵地址",
@@ -847,7 +852,6 @@
"Delete certificate" : "刪除證書",
"No certificate imported yet" : "尚未導入證書",
"Import certificate" : "導入證書",
- "Import S/MIME certificate" : "導入 S/MIME 證書",
"PKCS #12 Certificate" : "PKCS #12 證書",
"PEM Certificate" : "PEM 證書",
"Certificate" : "憑證",
diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js
index e0495d6924..3e00291922 100644
--- a/l10n/zh_TW.js
+++ b/l10n/zh_TW.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "電子郵件",
"You are reaching your mailbox quota limit for {account_email}" : "您即將達到 {account_email} 的信箱配額限制",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "您目前使用了信箱儲存空間的 {percentage}。請刪除不必要的電子郵件以釋出空間。",
+ "{account_email} has been delegated to you" : "{account_email} 已委託給您",
+ "{user} delegated {account} to you" : "{user} 已委託 {account} 給您",
+ "{account_email} is no longer delegated to you" : "{account_email} 不再委託給您",
+ "{user} revoked delegation for {account}" : "{user} 撤銷了 {account} 的委託",
"Mail Application" : "郵件應用程式",
"Mails" : "郵件",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "寄件者電子郵件:%1$s 不在通訊錄中,但寄件者名稱:%2$s 在通訊錄中,但其電子郵件為:%3$s",
@@ -842,6 +846,7 @@ OC.L10N.register(
"Certificate imported successfully" : "成功匯出憑證",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "無法匯入憑證。請確保私鑰與憑證相符,且不受密語保護。",
"Failed to import the certificate" : "匯入憑證失敗",
+ "Import S/MIME certificate" : "匯入 S/MIME 憑證",
"S/MIME certificates" : "S/MIME 憑證",
"Certificate name" : "憑證名稱",
"E-mail address" : "電子郵件地址",
@@ -849,7 +854,6 @@ OC.L10N.register(
"Delete certificate" : "刪除憑證",
"No certificate imported yet" : "尚未匯入憑證",
"Import certificate" : "匯入憑證",
- "Import S/MIME certificate" : "匯入 S/MIME 憑證",
"PKCS #12 Certificate" : "PKCS #12 憑證",
"PEM Certificate" : "PEM 憑證",
"Certificate" : "憑證",
diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json
index 985eaa449d..4af740be0a 100644
--- a/l10n/zh_TW.json
+++ b/l10n/zh_TW.json
@@ -12,6 +12,10 @@
"Mail" : "電子郵件",
"You are reaching your mailbox quota limit for {account_email}" : "您即將達到 {account_email} 的信箱配額限制",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "您目前使用了信箱儲存空間的 {percentage}。請刪除不必要的電子郵件以釋出空間。",
+ "{account_email} has been delegated to you" : "{account_email} 已委託給您",
+ "{user} delegated {account} to you" : "{user} 已委託 {account} 給您",
+ "{account_email} is no longer delegated to you" : "{account_email} 不再委託給您",
+ "{user} revoked delegation for {account}" : "{user} 撤銷了 {account} 的委託",
"Mail Application" : "郵件應用程式",
"Mails" : "郵件",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "寄件者電子郵件:%1$s 不在通訊錄中,但寄件者名稱:%2$s 在通訊錄中,但其電子郵件為:%3$s",
@@ -840,6 +844,7 @@
"Certificate imported successfully" : "成功匯出憑證",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "無法匯入憑證。請確保私鑰與憑證相符,且不受密語保護。",
"Failed to import the certificate" : "匯入憑證失敗",
+ "Import S/MIME certificate" : "匯入 S/MIME 憑證",
"S/MIME certificates" : "S/MIME 憑證",
"Certificate name" : "憑證名稱",
"E-mail address" : "電子郵件地址",
@@ -847,7 +852,6 @@
"Delete certificate" : "刪除憑證",
"No certificate imported yet" : "尚未匯入憑證",
"Import certificate" : "匯入憑證",
- "Import S/MIME certificate" : "匯入 S/MIME 憑證",
"PKCS #12 Certificate" : "PKCS #12 憑證",
"PEM Certificate" : "PEM 憑證",
"Certificate" : "憑證",
From 86a46a9c09c3983db1057151bb3bb30417613a4f Mon Sep 17 00:00:00 2001
From: SoleroTG
Date: Thu, 21 May 2026 00:10:00 +0200
Subject: [PATCH 049/228] fix: disable CSRF check for message-id deeplinks
Signed-off-by: SoleroTG
---
lib/Controller/DeepLinkController.php | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/Controller/DeepLinkController.php b/lib/Controller/DeepLinkController.php
index c28385773d..c076202f85 100644
--- a/lib/Controller/DeepLinkController.php
+++ b/lib/Controller/DeepLinkController.php
@@ -14,6 +14,7 @@
use OCA\Mail\Db\MessageMapper;
use OCA\Mail\Service\AccountService;
use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\IRequest;
use OCP\IURLGenerator;
@@ -40,6 +41,7 @@ public function __construct(
* @param string $messageId
* @return RedirectResponse
*/
+ #[NoCSRFRequired]
public function open(string $messageId): RedirectResponse {
$user = $this->userSession->getUser();
if ($user === null) {
From 41bd13fca6e2acccca3e0736ef6f2d13897d19a3 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 22 May 2026 17:27:39 +0000
Subject: [PATCH 050/228] chore(deps): bump peter-evans/create-pull-request
action from v7.0.11 to v8
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/update-public-suffix-list.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/update-public-suffix-list.yml b/.github/workflows/update-public-suffix-list.yml
index d536d8c65c..7390b0ff46 100644
--- a/.github/workflows/update-public-suffix-list.yml
+++ b/.github/workflows/update-public-suffix-list.yml
@@ -31,7 +31,7 @@ jobs:
run: curl --output resources/public_suffix_list.dat https://publicsuffix.org/list/public_suffix_list.dat
- name: Create Pull Request
- uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11
+ uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'fix(dns): Update public suffix list'
From 9b6ba5871b0895c9a15e88131921d4228ee45200 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Mon, 25 May 2026 01:47:47 +0000
Subject: [PATCH 051/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/lt_LT.js | 8 ++++++--
l10n/lt_LT.json | 8 ++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index 7efd37a545..a8aa385c44 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "Paštas",
"You are reaching your mailbox quota limit for {account_email}" : "Jūs pasiekiate savo {account_email} pašto dėžutės kvotos limitą",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Šiuo metu naudojate {percentage} savo pašto dėžutės saugyklos. Atlaisvinkite vietos ištrindami nereikalingus el. laiškus.",
+ "{account_email} has been delegated to you" : "{account_email} buvo jums deleguotas",
+ "{user} delegated {account} to you" : "{user} delegavo {account} jums",
+ "{account_email} is no longer delegated to you" : "{account_email} nebėra jums deleguotas",
+ "{user} revoked delegation for {account}" : "{user} atšaukė delegavimą skirtą {account}",
"Mail Application" : "Pašto programėlė",
"Mails" : "El. laiškai",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Siuntėjo el. pašto adreso %1$s nėra adresų knygoje, bet siuntėjo vardas: %2$s yra adresų knygoje su šiuo el. pašto adresu: %3$s",
@@ -130,7 +134,7 @@ OC.L10N.register(
"Cancel" : "Atsisakyti",
"Search the body of messages in priority Inbox" : "Ieškoti prioritetinėje pašto dėžutėje pranešimų tekste",
"Activate" : "Aktyvuoti",
- "Make mails available to Context Chat" : "Padaryti laiškus pasiekiamus kontekstiniame pokalbyje",
+ "Make mails available to Context Chat" : "Padaryti laiškus pasiekiamus „Context Chat“",
"Remind about messages that require a reply but received none" : "Priminti apie pranešimus, į kuriuos reikia atsakyti, bet į kuriuos nebuvo gautas atsakymas",
"Highlight external addresses" : "Pabrėžti išorinius adresus",
"Could not update preference" : "Nepavyko atnaujinti nuostatos",
@@ -175,7 +179,7 @@ OC.L10N.register(
"Step 2" : "2 žingsnis",
"Enable for the current domain" : "Įjungti dabartiniam domenui",
"Assistance features" : "Pagalbos funkcijos",
- "Context Chat integration" : "Kontekstinis pokalbių integravimas",
+ "Context Chat integration" : "„Context Chat“ integravimas",
"Compose new message" : "Rašyti naują laišką",
"Newer message" : "Naujesni laiškai",
"Older message" : "Senesni laiškai",
diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json
index 1fb23f47b5..146c687c92 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -12,6 +12,10 @@
"Mail" : "Paštas",
"You are reaching your mailbox quota limit for {account_email}" : "Jūs pasiekiate savo {account_email} pašto dėžutės kvotos limitą",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Šiuo metu naudojate {percentage} savo pašto dėžutės saugyklos. Atlaisvinkite vietos ištrindami nereikalingus el. laiškus.",
+ "{account_email} has been delegated to you" : "{account_email} buvo jums deleguotas",
+ "{user} delegated {account} to you" : "{user} delegavo {account} jums",
+ "{account_email} is no longer delegated to you" : "{account_email} nebėra jums deleguotas",
+ "{user} revoked delegation for {account}" : "{user} atšaukė delegavimą skirtą {account}",
"Mail Application" : "Pašto programėlė",
"Mails" : "El. laiškai",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Siuntėjo el. pašto adreso %1$s nėra adresų knygoje, bet siuntėjo vardas: %2$s yra adresų knygoje su šiuo el. pašto adresu: %3$s",
@@ -128,7 +132,7 @@
"Cancel" : "Atsisakyti",
"Search the body of messages in priority Inbox" : "Ieškoti prioritetinėje pašto dėžutėje pranešimų tekste",
"Activate" : "Aktyvuoti",
- "Make mails available to Context Chat" : "Padaryti laiškus pasiekiamus kontekstiniame pokalbyje",
+ "Make mails available to Context Chat" : "Padaryti laiškus pasiekiamus „Context Chat“",
"Remind about messages that require a reply but received none" : "Priminti apie pranešimus, į kuriuos reikia atsakyti, bet į kuriuos nebuvo gautas atsakymas",
"Highlight external addresses" : "Pabrėžti išorinius adresus",
"Could not update preference" : "Nepavyko atnaujinti nuostatos",
@@ -173,7 +177,7 @@
"Step 2" : "2 žingsnis",
"Enable for the current domain" : "Įjungti dabartiniam domenui",
"Assistance features" : "Pagalbos funkcijos",
- "Context Chat integration" : "Kontekstinis pokalbių integravimas",
+ "Context Chat integration" : "„Context Chat“ integravimas",
"Compose new message" : "Rašyti naują laišką",
"Newer message" : "Naujesni laiškai",
"Older message" : "Senesni laiškai",
From c5b36c83b22909507a0140d7968f6342a1e18f38 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 25 May 2026 20:28:15 +0000
Subject: [PATCH 052/228] chore(deps): bump codecov/codecov-action action from
v5.5.4 to v6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/test.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index dde06cc527..081f5b22d2 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -53,7 +53,7 @@ jobs:
env:
XDEBUG_MODE: ${{ matrix.coverage && 'coverage' || 'off' }}
- name: Report coverage
- uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4
+ uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
if: ${{ !cancelled() && matrix.coverage }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
@@ -198,7 +198,7 @@ jobs:
if: ${{ always() }}
run: cat nextcloud/data/mail-*-*-imap.log
- name: Report coverage
- uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4
+ uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
if: ${{ !cancelled() && matrix.coverage }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
From 45b32cfb49e03a1bff58d6a08155cfacb691acef Mon Sep 17 00:00:00 2001
From: nextcloud-command
Date: Tue, 26 May 2026 03:46:00 +0000
Subject: [PATCH 053/228] fix(deps): Fix npm audit
Signed-off-by: GitHub
---
package-lock.json | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index d5ff128a33..2e788ef968 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7346,13 +7346,13 @@
}
},
"node_modules/browserify-sign": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz",
- "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.6.tgz",
+ "integrity": "sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==",
"dev": true,
"license": "ISC",
"dependencies": {
- "bn.js": "^5.2.2",
+ "bn.js": "^5.2.3",
"browserify-rsa": "^4.1.1",
"create-hash": "^1.2.0",
"create-hmac": "^1.1.7",
@@ -11779,12 +11779,13 @@
}
},
"node_modules/js-cookie": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
- "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.7.tgz",
+ "integrity": "sha512-z/wZZgDrkNV1eA0ULjM/F9/50Ya8fbzgKneSpoPsXSGd0KnpdtHfOZWK+GcwLk+EZbS4F9RBhU+K2RgzuDaItw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=14"
+ "node": ">=20"
}
},
"node_modules/js-tokens": {
@@ -14500,9 +14501,9 @@
"license": "MIT"
},
"node_modules/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
+ "version": "6.15.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
+ "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
From 9bbae7d7d55a5e22f0c1f67e1d58f987ffe80233 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Tue, 26 May 2026 12:31:45 +0200
Subject: [PATCH 054/228] fix(ui): use v-model for assistance setting switches
:checked is not a prop on NcFormBoxSwitch (it expects modelValue),
so both the follow-up reminders and context chat switches always
appeared off and unresponsive. Switch to v-model which wires the
existing computed setters correctly.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/components/AppSettingsMenu.vue | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/components/AppSettingsMenu.vue b/src/components/AppSettingsMenu.vue
index e43cd21698..50c5835315 100755
--- a/src/components/AppSettingsMenu.vue
+++ b/src/components/AppSettingsMenu.vue
@@ -203,7 +203,7 @@
{{ followUpReminderText }}
@@ -212,9 +212,8 @@
+ v-model="useContextChat"
+ :disabled="loadingContextChat">
{{ contextChatText }}
From 0f5d81cf8ae5994f36d2364088c02834e18bce4e Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Thu, 21 May 2026 11:48:06 +0200
Subject: [PATCH 055/228] fix(api): validate targetPath is an existing folder
on saveAttachment
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
lib/Controller/MessagesController.php | 6 +++
.../Controller/MessagesControllerTest.php | 47 +++++++++++++++++--
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/lib/Controller/MessagesController.php b/lib/Controller/MessagesController.php
index 7cf4e40779..1bf463c277 100755
--- a/lib/Controller/MessagesController.php
+++ b/lib/Controller/MessagesController.php
@@ -821,6 +821,12 @@ public function saveAttachment(int $id,
if ($this->userFolder === null) {
return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
}
+ if (!$this->userFolder->nodeExists($targetPath)) {
+ return new JSONResponse([], Http::STATUS_BAD_REQUEST);
+ }
+ if (!($this->userFolder->get($targetPath) instanceof Folder)) {
+ return new JSONResponse([], Http::STATUS_BAD_REQUEST);
+ }
try {
$effectiveUserId = $this->delegationService->resolveMessageUserId($id, $this->currentUserId);
$message = $this->mailManager->getMessage($effectiveUserId, $id);
diff --git a/tests/Unit/Controller/MessagesControllerTest.php b/tests/Unit/Controller/MessagesControllerTest.php
index 227a73dc90..6f57b3ca72 100644
--- a/tests/Unit/Controller/MessagesControllerTest.php
+++ b/tests/Unit/Controller/MessagesControllerTest.php
@@ -375,10 +375,15 @@ public function testSaveSingleAttachment() {
->method('getName')
->with()
->will($this->returnValue('cat.jpg'));
+ $folderNode = $this->createMock(Folder::class);
$this->userFolder->expects($this->once())
+ ->method('get')
+ ->with('Downloads')
+ ->willReturn($folderNode);
+ $this->userFolder->expects($this->exactly(2))
->method('nodeExists')
- ->with('Downloads/cat.jpg')
- ->will($this->returnValue(false));
+ ->withConsecutive(['Downloads'], ['Downloads/cat.jpg'])
+ ->willReturnOnConsecutiveCalls(true, false);
$file = $this->getMockBuilder('\OCP\Files\File')
->disableOriginalConstructor()
->getMock();
@@ -438,10 +443,15 @@ public function testSaveAllAttachments() {
->method('getName')
->with()
->will($this->returnValue('cat.jpg'));
+ $folderNode = $this->createMock(Folder::class);
$this->userFolder->expects($this->once())
+ ->method('get')
+ ->with('Downloads')
+ ->willReturn($folderNode);
+ $this->userFolder->expects($this->exactly(2))
->method('nodeExists')
- ->with('Downloads/cat.jpg')
- ->will($this->returnValue(false));
+ ->withConsecutive(['Downloads'], ['Downloads/cat.jpg'])
+ ->willReturnOnConsecutiveCalls(true, false);
$file = $this->getMockBuilder('\OCP\Files\File')
->disableOriginalConstructor()
->getMock();
@@ -466,6 +476,35 @@ public function testSaveAllAttachments() {
$this->assertEquals($expected, $response);
}
+ public function testSaveAttachmentTargetPathNotFound(): void {
+ $this->userFolder->expects($this->once())
+ ->method('nodeExists')
+ ->with('NoSuchFolder')
+ ->willReturn(false);
+
+ $response = $this->controller->saveAttachment(123, '1', 'NoSuchFolder');
+
+ $this->assertSame(Http::STATUS_BAD_REQUEST, $response->getStatus());
+ }
+
+ public function testSaveAttachmentTargetPathIsFile(): void {
+ $fileNode = $this->getMockBuilder('\OCP\Files\File')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->userFolder->expects($this->once())
+ ->method('nodeExists')
+ ->with('some/file.txt')
+ ->willReturn(true);
+ $this->userFolder->expects($this->once())
+ ->method('get')
+ ->with('some/file.txt')
+ ->willReturn($fileNode);
+
+ $response = $this->controller->saveAttachment(123, '1', 'some/file.txt');
+
+ $this->assertSame(Http::STATUS_BAD_REQUEST, $response->getStatus());
+ }
+
public function testDownloadAttachments() {
$accountId = 17;
$mailboxId = 987;
From c3bd03d591f646d1bea2038bda1b90fabbee4a29 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 27 May 2026 00:27:25 +0000
Subject: [PATCH 056/228] chore(deps): bump nextcloud/rector from ^0.5.0 to
^0.5.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
vendor-bin/rector/composer.json | 2 +-
vendor-bin/rector/composer.lock | 14 +++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json
index 2e0772173e..e312e8d561 100644
--- a/vendor-bin/rector/composer.json
+++ b/vendor-bin/rector/composer.json
@@ -1,6 +1,6 @@
{
"require-dev": {
"rector/rector": "^2.4.2",
- "nextcloud/rector": "^0.5.0"
+ "nextcloud/rector": "^0.5.1"
}
}
diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock
index 00eb52b9ee..0f8ed2d6a8 100644
--- a/vendor-bin/rector/composer.lock
+++ b/vendor-bin/rector/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "5ad5e59cd94d7383d7fc0a0e7f6ecbb6",
+ "content-hash": "3076c30db14295d382cb70e5dc50180a",
"packages": [],
"packages-dev": [
{
@@ -57,16 +57,16 @@
},
{
"name": "nextcloud/rector",
- "version": "v0.5.0",
+ "version": "v0.5.1",
"source": {
"type": "git",
"url": "https://github.com/nextcloud-libraries/rector.git",
- "reference": "27bff78af53633d9b77ed8af17b27af73e8f67e9"
+ "reference": "d9c4cf53d9bce0fa95edc87cb093307958317e28"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/27bff78af53633d9b77ed8af17b27af73e8f67e9",
- "reference": "27bff78af53633d9b77ed8af17b27af73e8f67e9",
+ "url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/d9c4cf53d9bce0fa95edc87cb093307958317e28",
+ "reference": "d9c4cf53d9bce0fa95edc87cb093307958317e28",
"shasum": ""
},
"require": {
@@ -116,9 +116,9 @@
],
"support": {
"issues": "https://github.com/nextcloud-libraries/rector/issues",
- "source": "https://github.com/nextcloud-libraries/rector/tree/v0.5.0"
+ "source": "https://github.com/nextcloud-libraries/rector/tree/v0.5.1"
},
- "time": "2026-04-28T08:20:44+00:00"
+ "time": "2026-05-08T07:32:27+00:00"
},
{
"name": "phpstan/phpstan",
From e332b3abf01dc013d2bf9adc7818095ecbbc430a Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 27 May 2026 00:27:43 +0000
Subject: [PATCH 057/228] chore(deps): bump php-cs-fixer/shim from ^3.95.1 to
^3.95.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
vendor-bin/cs-fixer/composer.json | 2 +-
vendor-bin/cs-fixer/composer.lock | 14 +++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/vendor-bin/cs-fixer/composer.json b/vendor-bin/cs-fixer/composer.json
index 159169e65c..b8b686f561 100644
--- a/vendor-bin/cs-fixer/composer.json
+++ b/vendor-bin/cs-fixer/composer.json
@@ -7,6 +7,6 @@
},
"require-dev": {
"nextcloud/coding-standard": "^1.4.0",
- "php-cs-fixer/shim": "^3.95.1"
+ "php-cs-fixer/shim": "^3.95.2"
}
}
diff --git a/vendor-bin/cs-fixer/composer.lock b/vendor-bin/cs-fixer/composer.lock
index 5befb1e091..1556e6785f 100644
--- a/vendor-bin/cs-fixer/composer.lock
+++ b/vendor-bin/cs-fixer/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "664ab76e053cea647ed646184f85bf22",
+ "content-hash": "68196a8f71fa07d1107c9d67bdef7a71",
"packages": [],
"packages-dev": [
{
@@ -106,16 +106,16 @@
},
{
"name": "php-cs-fixer/shim",
- "version": "v3.95.1",
+ "version": "v3.95.2",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/shim.git",
- "reference": "f81ccf51ca60cc9dd21358ffba0e79ebd2ebb78a"
+ "reference": "319bd80c8db64ab5f7b79a19178299045bdb9957"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/f81ccf51ca60cc9dd21358ffba0e79ebd2ebb78a",
- "reference": "f81ccf51ca60cc9dd21358ffba0e79ebd2ebb78a",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/319bd80c8db64ab5f7b79a19178299045bdb9957",
+ "reference": "319bd80c8db64ab5f7b79a19178299045bdb9957",
"shasum": ""
},
"require": {
@@ -152,9 +152,9 @@
"description": "A tool to automatically fix PHP code style",
"support": {
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
- "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.95.1"
+ "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.95.2"
},
- "time": "2026-04-12T17:00:34+00:00"
+ "time": "2026-05-15T09:21:09+00:00"
}
],
"aliases": [],
From 62444e12933f7264563abff2a132238eac2f8057 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 27 May 2026 08:22:31 +0200
Subject: [PATCH 058/228] chore(release): v5.9.0-rc.1
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
CHANGELOG.md | 13 ++++++++++++-
appinfo/info.xml | 2 +-
package-lock.json | 4 ++--
package.json | 2 +-
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9baf88b857..e9ca2066c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,11 +3,22 @@ All notable changes to this project will be documented in this file.
## 5.9.0 – unreleased
### Added
-* Account delegation
+* Nextcloud 35 support
+* Account delegation with notifications
* HTML and source editing support in composer/signature editor
* Per-message To/Cc/Bcc recipients in thread view
+* Paste or copy several email addresses into address fields at once
+* Keep inline images when forwarding messages
### Changed
* Translations
+### Performance
+* Reuse IMAP client connections during initial sync
+### Fixed
+* Attachment actions menu closes after Download or Save to Files
+* Correct favorite/unfavorite bulk action behavior
+* Detect and warn about Microsoft accounts without OAuth configured
+* Important message icon not displayed in message list
+* Load translations via filesystem path
## 5.8.0 – unreleased
### Added
diff --git a/appinfo/info.xml b/appinfo/info.xml
index fd16908695..0a6d196818 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -34,7 +34,7 @@ The rating depends on the installed text processing backend. See [the rating ove
Learn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).
]]>
- 5.9.0-alpha.1
+ 5.9.0-rc.1
agpl
Christoph Wurst
GretaD
diff --git a/package-lock.json b/package-lock.json
index 2e788ef968..dcba54128a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "nextcloud-mail",
- "version": "5.9.0-alpha.1",
+ "version": "5.9.0-rc.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nextcloud-mail",
- "version": "5.9.0-alpha.1",
+ "version": "5.9.0-rc.1",
"hasInstallScript": true,
"license": "AGPL-3.0-only",
"dependencies": {
diff --git a/package.json b/package.json
index dd20a52879..024c4e235a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "nextcloud-mail",
- "version": "5.9.0-alpha.1",
+ "version": "5.9.0-rc.1",
"private": true,
"description": "Nextcloud Mail",
"license": "AGPL-3.0-only",
From 4869677dd445bfcad490a1f8e86a3ba098827325 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 27 May 2026 08:25:38 +0200
Subject: [PATCH 059/228] ci: update maintained stable branches
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.github/workflows/npm-audit-fix.yml | 2 +-
.github/workflows/update-public-suffix-list.yml | 2 +-
.tx/backport | 2 +-
renovate.json | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/npm-audit-fix.yml b/.github/workflows/npm-audit-fix.yml
index b6b1287cbb..f8b9a7bf19 100644
--- a/.github/workflows/npm-audit-fix.yml
+++ b/.github/workflows/npm-audit-fix.yml
@@ -26,8 +26,8 @@ jobs:
matrix:
branches:
- ${{ github.event.repository.default_branch }}
+ - 'stable5.9'
- 'stable5.8'
- - 'stable5.7'
name: npm-audit-fix-${{ matrix.branches }}
diff --git a/.github/workflows/update-public-suffix-list.yml b/.github/workflows/update-public-suffix-list.yml
index 7390b0ff46..095498756d 100644
--- a/.github/workflows/update-public-suffix-list.yml
+++ b/.github/workflows/update-public-suffix-list.yml
@@ -16,8 +16,8 @@ jobs:
matrix:
branches:
- 'main'
+ - 'stable5.9'
- 'stable5.8'
- - 'stable5.7'
name: update-public-suffix-list-${{ matrix.branches }}
diff --git a/.tx/backport b/.tx/backport
index 8aa267a672..8ed496a14e 100644
--- a/.tx/backport
+++ b/.tx/backport
@@ -1,2 +1,2 @@
+stable5.9
stable5.8
-stable5.7
diff --git a/renovate.json b/renovate.json
index 28a8a5ad2f..01e20f2b9c 100644
--- a/renovate.json
+++ b/renovate.json
@@ -24,8 +24,8 @@
"ignoreUnstable": false,
"baseBranchPatterns": [
"main",
- "stable5.8",
- "stable5.7"
+ "stable5.9",
+ "stable5.8"
],
"enabledManagers": [
"composer",
From c9cbc098a0ea38db1ed2ab87b58a17e9865f3575 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 27 May 2026 10:03:58 +0200
Subject: [PATCH 060/228] fix(ui): prevent type error during shortkey usage
The shortkey event can fire multiple times. We have to ignore the ones
that are not relevant (as the debug log says) and actually return.
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/components/Mailbox.vue | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue
index 861db0a881..bbaaf8c1c6 100644
--- a/src/components/Mailbox.vue
+++ b/src/components/Mailbox.vue
@@ -374,6 +374,7 @@ export default {
logger.debug('envelope is not in the list, ignoring shortcut', {
srcKey: e.srcKey,
})
+ return
}
switch (e.srcKey) {
From 9d67a65f9ed59c6799687feab14236e917c8e9d0 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Thu, 28 May 2026 01:50:32 +0000
Subject: [PATCH 061/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/ar.js | 4 +---
l10n/ar.json | 4 +---
l10n/bg.js | 3 +--
l10n/bg.json | 3 +--
l10n/ca.js | 4 +---
l10n/ca.json | 4 +---
l10n/cs.js | 4 +---
l10n/cs.json | 4 +---
l10n/da.js | 3 +--
l10n/da.json | 3 +--
l10n/de.js | 4 +---
l10n/de.json | 4 +---
l10n/de_DE.js | 4 +---
l10n/de_DE.json | 4 +---
l10n/el.js | 4 +---
l10n/el.json | 4 +---
l10n/en_GB.js | 4 +---
l10n/en_GB.json | 4 +---
l10n/es.js | 4 +---
l10n/es.json | 4 +---
l10n/es_EC.js | 3 +--
l10n/es_EC.json | 3 +--
l10n/et_EE.js | 3 +--
l10n/et_EE.json | 3 +--
l10n/eu.js | 4 +---
l10n/eu.json | 4 +---
l10n/fa.js | 3 +--
l10n/fa.json | 3 +--
l10n/fr.js | 4 +---
l10n/fr.json | 4 +---
l10n/ga.js | 4 +---
l10n/ga.json | 4 +---
l10n/gl.js | 4 +---
l10n/gl.json | 4 +---
l10n/hr.js | 4 +---
l10n/hr.json | 4 +---
l10n/hu.js | 3 +--
l10n/hu.json | 3 +--
l10n/id.js | 4 +---
l10n/id.json | 4 +---
l10n/is.js | 3 +--
l10n/is.json | 3 +--
l10n/it.js | 4 +---
l10n/it.json | 4 +---
l10n/ja.js | 4 +---
l10n/ja.json | 4 +---
l10n/ka.js | 3 +--
l10n/ka.json | 3 +--
l10n/ko.js | 3 +--
l10n/ko.json | 3 +--
l10n/lo.js | 4 +---
l10n/lo.json | 4 +---
l10n/lt_LT.js | 4 +---
l10n/lt_LT.json | 4 +---
l10n/mk.js | 4 ++--
l10n/mk.json | 4 ++--
l10n/mn.js | 4 +---
l10n/mn.json | 4 +---
l10n/nb.js | 4 +---
l10n/nb.json | 4 +---
l10n/nl.js | 4 +---
l10n/nl.json | 4 +---
l10n/pl.js | 36 +++++++++++++++++++++++++++++++++---
l10n/pl.json | 36 +++++++++++++++++++++++++++++++++---
l10n/pt_BR.js | 4 +---
l10n/pt_BR.json | 4 +---
l10n/ro.js | 3 +--
l10n/ro.json | 3 +--
l10n/ru.js | 4 +---
l10n/ru.json | 4 +---
l10n/sc.js | 3 +--
l10n/sc.json | 3 +--
l10n/sk.js | 4 +---
l10n/sk.json | 4 +---
l10n/sl.js | 3 +--
l10n/sl.json | 3 +--
l10n/sr.js | 4 +---
l10n/sr.json | 4 +---
l10n/sv.js | 4 +---
l10n/sv.json | 4 +---
l10n/tr.js | 4 +---
l10n/tr.json | 4 +---
l10n/ug.js | 4 +---
l10n/ug.json | 4 +---
l10n/uk.js | 4 +---
l10n/uk.json | 4 +---
l10n/vi.js | 3 +--
l10n/vi.json | 3 +--
l10n/zh_CN.js | 4 +---
l10n/zh_CN.json | 4 +---
l10n/zh_HK.js | 4 +---
l10n/zh_HK.json | 4 +---
l10n/zh_TW.js | 4 +---
l10n/zh_TW.json | 4 +---
94 files changed, 160 insertions(+), 254 deletions(-)
diff --git a/l10n/ar.js b/l10n/ar.js
index 32e3af19e0..7dd4ff4063 100644
--- a/l10n/ar.js
+++ b/l10n/ar.js
@@ -715,8 +715,6 @@ OC.L10N.register(
"Could not load your message" : "تعذّر تحميل رسالتك",
"Could not load the desired message" : "تعذّر تحميل الرسالة المطلوبة",
"Could not load the message" : "تعذّر تحميل الرسالة",
- "Error loading message" : "حدث خطأ أثناء تحميل الرسالة",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "سيتم وضع علامة على الرسائل تلقائيًا على أنها مهمة بناءً على الرسائل التي تفاعلت معها أو تم وضع علامة عليها كمهمة. في البداية، قد تضطر إلى تغيير الأهمية يدويّاً من أجل تعليم النظام، لكنه سيتحسن بمرور الوقت.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "الرسائل التي أرسلتها أنت وتتطلب ردّاً لكن مرت عدة أيام و لم يتم إرساله ستظهر هنا. "
+ "Error loading message" : "حدث خطأ أثناء تحميل الرسالة"
},
"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;");
diff --git a/l10n/ar.json b/l10n/ar.json
index 64347d55e0..564960a2aa 100644
--- a/l10n/ar.json
+++ b/l10n/ar.json
@@ -713,8 +713,6 @@
"Could not load your message" : "تعذّر تحميل رسالتك",
"Could not load the desired message" : "تعذّر تحميل الرسالة المطلوبة",
"Could not load the message" : "تعذّر تحميل الرسالة",
- "Error loading message" : "حدث خطأ أثناء تحميل الرسالة",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "سيتم وضع علامة على الرسائل تلقائيًا على أنها مهمة بناءً على الرسائل التي تفاعلت معها أو تم وضع علامة عليها كمهمة. في البداية، قد تضطر إلى تغيير الأهمية يدويّاً من أجل تعليم النظام، لكنه سيتحسن بمرور الوقت.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "الرسائل التي أرسلتها أنت وتتطلب ردّاً لكن مرت عدة أيام و لم يتم إرساله ستظهر هنا. "
+ "Error loading message" : "حدث خطأ أثناء تحميل الرسالة"
},"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/l10n/bg.js b/l10n/bg.js
index c7487a63ae..c0801e3824 100644
--- a/l10n/bg.js
+++ b/l10n/bg.js
@@ -548,7 +548,6 @@ OC.L10N.register(
"Could not load your message" : "Вашето съобщение не може да бъде заредено",
"Could not load the desired message" : "Желаното съобщение не може да бъде заредено",
"Could not load the message" : "Съобщението не може да бъде заредено",
- "Error loading message" : "Грешка при зареждане съобщението",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Съобщенията автоматично ще бъдат маркирани като важни въз основа на съобщенията, с които сте взаимодействали или маркирани като важни. В началото може да се наложи ръчно да промените важността, за да обучите системата, но тя ще се подобри с течение на времето."
+ "Error loading message" : "Грешка при зареждане съобщението"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/bg.json b/l10n/bg.json
index b3a9ab5b1e..029e25a8f2 100644
--- a/l10n/bg.json
+++ b/l10n/bg.json
@@ -546,7 +546,6 @@
"Could not load your message" : "Вашето съобщение не може да бъде заредено",
"Could not load the desired message" : "Желаното съобщение не може да бъде заредено",
"Could not load the message" : "Съобщението не може да бъде заредено",
- "Error loading message" : "Грешка при зареждане съобщението",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Съобщенията автоматично ще бъдат маркирани като важни въз основа на съобщенията, с които сте взаимодействали или маркирани като важни. В началото може да се наложи ръчно да промените важността, за да обучите системата, но тя ще се подобри с течение на времето."
+ "Error loading message" : "Грешка при зареждане съобщението"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/ca.js b/l10n/ca.js
index a01514870e..14a9439df5 100644
--- a/l10n/ca.js
+++ b/l10n/ca.js
@@ -719,8 +719,6 @@ OC.L10N.register(
"Could not load your message" : "No s’ha pogut carregar el vostre missatge",
"Could not load the desired message" : "No s’ha pogut carregar el missatge desitjat",
"Could not load the message" : "No s’ha pogut carregar el missatge",
- "Error loading message" : "S'ha produït un error mentre es carregava el missatge",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Els missatges es marcaran automàticament com a importants en funció dels missatges amb els quals heu interaccionat o marcat com a importants. Al principi és possible que hageu de canviar manualment la importància per ensenyar el sistema, però millorarà amb el temps.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Aquí es mostraran els missatges enviats per tu que requereixen una resposta però que no n'hagis rebut cap al cap d'un parell de dies."
+ "Error loading message" : "S'ha produït un error mentre es carregava el missatge"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/ca.json b/l10n/ca.json
index be6d4929fd..05be2228ed 100644
--- a/l10n/ca.json
+++ b/l10n/ca.json
@@ -717,8 +717,6 @@
"Could not load your message" : "No s’ha pogut carregar el vostre missatge",
"Could not load the desired message" : "No s’ha pogut carregar el missatge desitjat",
"Could not load the message" : "No s’ha pogut carregar el missatge",
- "Error loading message" : "S'ha produït un error mentre es carregava el missatge",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Els missatges es marcaran automàticament com a importants en funció dels missatges amb els quals heu interaccionat o marcat com a importants. Al principi és possible que hageu de canviar manualment la importància per ensenyar el sistema, però millorarà amb el temps.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Aquí es mostraran els missatges enviats per tu que requereixen una resposta però que no n'hagis rebut cap al cap d'un parell de dies."
+ "Error loading message" : "S'ha produït un error mentre es carregava el missatge"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/cs.js b/l10n/cs.js
index 594f4f1f4c..f3c864ec14 100644
--- a/l10n/cs.js
+++ b/l10n/cs.js
@@ -885,8 +885,6 @@ OC.L10N.register(
"Could not load your message" : "Vaši zprávu se nedaří načíst",
"Could not load the desired message" : "Nedaří se načíst vyžádanou zprávu",
"Could not load the message" : "Zprávu se nedaří načíst",
- "Error loading message" : "Chyba při načtení zprávy",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Správy budou automaticky označené jako důležité v závislosti na tom, jakými správami jste se zabývali nebo označili jako důležité. Na začátku bude třeba měnit důležitost ručně a systém tak naučit, ale po čase se to zlepší.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Vámi zaslané zprávy, které vyžadují odpověď, ale ani po několika dnech se tak nestalo, se zobrazí zde."
+ "Error loading message" : "Chyba při načtení zprávy"
},
"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/l10n/cs.json b/l10n/cs.json
index 4849f66217..ee6a62cfc5 100644
--- a/l10n/cs.json
+++ b/l10n/cs.json
@@ -883,8 +883,6 @@
"Could not load your message" : "Vaši zprávu se nedaří načíst",
"Could not load the desired message" : "Nedaří se načíst vyžádanou zprávu",
"Could not load the message" : "Zprávu se nedaří načíst",
- "Error loading message" : "Chyba při načtení zprávy",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Správy budou automaticky označené jako důležité v závislosti na tom, jakými správami jste se zabývali nebo označili jako důležité. Na začátku bude třeba měnit důležitost ručně a systém tak naučit, ale po čase se to zlepší.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Vámi zaslané zprávy, které vyžadují odpověď, ale ani po několika dnech se tak nestalo, se zobrazí zde."
+ "Error loading message" : "Chyba při načtení zprávy"
},"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/l10n/da.js b/l10n/da.js
index 81dfb9acd3..eca6a5bb82 100644
--- a/l10n/da.js
+++ b/l10n/da.js
@@ -581,7 +581,6 @@ OC.L10N.register(
"Could not load your message" : "Din besked kunne ikke indlæses",
"Could not load the desired message" : "Den ønskede besked kunne ikke indlæses",
"Could not load the message" : "Beskeden kunne ikke indlæses",
- "Error loading message" : "Fejl under indlæsning af besked",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Beskeder vil automatisk blive markeret som vigtige baseret på, hvilke meddelelser du har interageret med eller markeret som vigtige. I begyndelsen skal du muligvis manuelt ændre vigtigheden for at lære systemet, men det vil forbedres med tiden."
+ "Error loading message" : "Fejl under indlæsning af besked"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/da.json b/l10n/da.json
index 8ed33a5003..dca9e07137 100644
--- a/l10n/da.json
+++ b/l10n/da.json
@@ -579,7 +579,6 @@
"Could not load your message" : "Din besked kunne ikke indlæses",
"Could not load the desired message" : "Den ønskede besked kunne ikke indlæses",
"Could not load the message" : "Beskeden kunne ikke indlæses",
- "Error loading message" : "Fejl under indlæsning af besked",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Beskeder vil automatisk blive markeret som vigtige baseret på, hvilke meddelelser du har interageret med eller markeret som vigtige. I begyndelsen skal du muligvis manuelt ændre vigtigheden for at lære systemet, men det vil forbedres med tiden."
+ "Error loading message" : "Fejl under indlæsning af besked"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/de.js b/l10n/de.js
index c35acf7256..b7cf103d7e 100644
--- a/l10n/de.js
+++ b/l10n/de.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "Deine Nachricht konnte nicht geladen werden",
"Could not load the desired message" : "Gewünschte Nachricht konnte nicht geladen werden",
"Could not load the message" : "Nachricht konnte nicht geladen werden",
- "Error loading message" : "Fehler beim Laden der Nachricht",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Nachrichten werden automatisch als wichtig markiert, je nachdem, mit welchen Nachrichten du interagiert, oder als wichtig markiert hast. Am Anfang musst du möglicherweise die Wichtigkeit manuell ändern, um das System anzulernen, aber es wird sich mit der Zeit verbessern.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Von dir gesendete Nachrichten, die eine Antwort erfordern, aber nach einigen Tagen noch keine erhalten haben, werden hier angezeigt."
+ "Error loading message" : "Fehler beim Laden der Nachricht"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/de.json b/l10n/de.json
index cf8d826504..ed748a04ee 100644
--- a/l10n/de.json
+++ b/l10n/de.json
@@ -912,8 +912,6 @@
"Could not load your message" : "Deine Nachricht konnte nicht geladen werden",
"Could not load the desired message" : "Gewünschte Nachricht konnte nicht geladen werden",
"Could not load the message" : "Nachricht konnte nicht geladen werden",
- "Error loading message" : "Fehler beim Laden der Nachricht",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Nachrichten werden automatisch als wichtig markiert, je nachdem, mit welchen Nachrichten du interagiert, oder als wichtig markiert hast. Am Anfang musst du möglicherweise die Wichtigkeit manuell ändern, um das System anzulernen, aber es wird sich mit der Zeit verbessern.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Von dir gesendete Nachrichten, die eine Antwort erfordern, aber nach einigen Tagen noch keine erhalten haben, werden hier angezeigt."
+ "Error loading message" : "Fehler beim Laden der Nachricht"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index 1fc3456604..c57ba4c353 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "Ihre Nachricht konnte nicht geladen werden",
"Could not load the desired message" : "Gewünschte Nachricht konnte nicht geladen werden",
"Could not load the message" : "Nachricht konnte nicht geladen werden",
- "Error loading message" : "Fehler beim Laden der Nachricht",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Nachrichten werden automatisch als wichtig markiert, je nachdem, mit welchen Nachrichten Sie interagieren, oder als wichtig markiert haben. Am Anfang müssen Sie möglicherweise die Wichtigkeit manuell ändern, um das System anzulernen, aber es wird sich mit der Zeit verbessern.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Von Ihnen gesendete Nachrichten, die eine Antwort erfordern, aber nach einigen Tagen noch keine erhalten haben, werden hier angezeigt."
+ "Error loading message" : "Fehler beim Laden der Nachricht"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index cf2dcd885f..1e87e0d77f 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -912,8 +912,6 @@
"Could not load your message" : "Ihre Nachricht konnte nicht geladen werden",
"Could not load the desired message" : "Gewünschte Nachricht konnte nicht geladen werden",
"Could not load the message" : "Nachricht konnte nicht geladen werden",
- "Error loading message" : "Fehler beim Laden der Nachricht",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Nachrichten werden automatisch als wichtig markiert, je nachdem, mit welchen Nachrichten Sie interagieren, oder als wichtig markiert haben. Am Anfang müssen Sie möglicherweise die Wichtigkeit manuell ändern, um das System anzulernen, aber es wird sich mit der Zeit verbessern.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Von Ihnen gesendete Nachrichten, die eine Antwort erfordern, aber nach einigen Tagen noch keine erhalten haben, werden hier angezeigt."
+ "Error loading message" : "Fehler beim Laden der Nachricht"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/el.js b/l10n/el.js
index edef2bae05..0ed451e3e8 100644
--- a/l10n/el.js
+++ b/l10n/el.js
@@ -830,8 +830,6 @@ OC.L10N.register(
"Could not load your message" : "Δεν ήταν δυνατή η φόρτωση του μηνύματός σας",
"Could not load the desired message" : "Αδυναμία φόρτωσης του προτιμώμενου μηνύματος",
"Could not load the message" : "Δεν ήταν δυνατή η φόρτωση του μηνύματος",
- "Error loading message" : "Σφάλμα φόρτωσης μηνύματος",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Τα μηνύματα θα επισημανθούν αυτόματα ως σημαντικά με βάση αυτά με τα οποία επισημαίνετε ως σημαντικά. Στην αρχή ίσως χρειαστεί να τα αλλάζετε χειροκίνητα, έως ότου εκπαιδευτεί το σύστημα, αλλά θα βελτιώνεται σταδιακά με την πάροδο του χρόνου.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Μηνύματα που στείλατε και απαιτούν απάντηση αλλά δεν έλαβαν καμία μετά από μερικές ημέρες θα εμφανίζονται εδώ."
+ "Error loading message" : "Σφάλμα φόρτωσης μηνύματος"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/el.json b/l10n/el.json
index 005fe1cb67..70889155a6 100644
--- a/l10n/el.json
+++ b/l10n/el.json
@@ -828,8 +828,6 @@
"Could not load your message" : "Δεν ήταν δυνατή η φόρτωση του μηνύματός σας",
"Could not load the desired message" : "Αδυναμία φόρτωσης του προτιμώμενου μηνύματος",
"Could not load the message" : "Δεν ήταν δυνατή η φόρτωση του μηνύματος",
- "Error loading message" : "Σφάλμα φόρτωσης μηνύματος",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Τα μηνύματα θα επισημανθούν αυτόματα ως σημαντικά με βάση αυτά με τα οποία επισημαίνετε ως σημαντικά. Στην αρχή ίσως χρειαστεί να τα αλλάζετε χειροκίνητα, έως ότου εκπαιδευτεί το σύστημα, αλλά θα βελτιώνεται σταδιακά με την πάροδο του χρόνου.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Μηνύματα που στείλατε και απαιτούν απάντηση αλλά δεν έλαβαν καμία μετά από μερικές ημέρες θα εμφανίζονται εδώ."
+ "Error loading message" : "Σφάλμα φόρτωσης μηνύματος"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/en_GB.js b/l10n/en_GB.js
index d09888d9cf..0ac4abd2f1 100644
--- a/l10n/en_GB.js
+++ b/l10n/en_GB.js
@@ -889,8 +889,6 @@ OC.L10N.register(
"Could not load your message" : "Could not load your message",
"Could not load the desired message" : "Could not load the desired message",
"Could not load the message" : "Could not load the message",
- "Error loading message" : "Error loading message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here."
+ "Error loading message" : "Error loading message"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/en_GB.json b/l10n/en_GB.json
index c4632fdcbe..3795036e73 100644
--- a/l10n/en_GB.json
+++ b/l10n/en_GB.json
@@ -887,8 +887,6 @@
"Could not load your message" : "Could not load your message",
"Could not load the desired message" : "Could not load the desired message",
"Could not load the message" : "Could not load the message",
- "Error loading message" : "Error loading message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here."
+ "Error loading message" : "Error loading message"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/es.js b/l10n/es.js
index afd9727b69..07d5604088 100644
--- a/l10n/es.js
+++ b/l10n/es.js
@@ -830,8 +830,6 @@ OC.L10N.register(
"Could not load your message" : "No se ha podido cargar tu mensaje",
"Could not load the desired message" : "No se ha podido cargar el mensaje deseado",
"Could not load the message" : "No se ha podido cargar el mensaje",
- "Error loading message" : "Error al cargar el mensaje",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Los mensajes se marcarán automáticamente como importantes en función de los mensajes con los que interactuó o se marcaron como importantes. Al principio puede que tengas que cambiar manualmente la importancia para enseñar el sistema, pero mejorará con el tiempo.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Los mensajes que ha enviado y requieren respuesta pero no han recibido ninguna en un par de días aparecerán aquí."
+ "Error loading message" : "Error al cargar el mensaje"
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/l10n/es.json b/l10n/es.json
index 59cc13c3ce..6931fcd545 100644
--- a/l10n/es.json
+++ b/l10n/es.json
@@ -828,8 +828,6 @@
"Could not load your message" : "No se ha podido cargar tu mensaje",
"Could not load the desired message" : "No se ha podido cargar el mensaje deseado",
"Could not load the message" : "No se ha podido cargar el mensaje",
- "Error loading message" : "Error al cargar el mensaje",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Los mensajes se marcarán automáticamente como importantes en función de los mensajes con los que interactuó o se marcaron como importantes. Al principio puede que tengas que cambiar manualmente la importancia para enseñar el sistema, pero mejorará con el tiempo.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Los mensajes que ha enviado y requieren respuesta pero no han recibido ninguna en un par de días aparecerán aquí."
+ "Error loading message" : "Error al cargar el mensaje"
},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}
\ No newline at end of file
diff --git a/l10n/es_EC.js b/l10n/es_EC.js
index 045c881c35..1e4d2dd98c 100644
--- a/l10n/es_EC.js
+++ b/l10n/es_EC.js
@@ -565,7 +565,6 @@ OC.L10N.register(
"Could not load your message" : "No fue posible cargar tu mensaje",
"Could not load the desired message" : "No fue posible cargar el mensaje deseado",
"Could not load the message" : "No fue posible cargar el mensaje",
- "Error loading message" : "Se presentó un error al cargar el mensaje",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Los mensajes se marcarán automáticamente como importantes en función de los mensajes con los que interactúes o que marques como importantes. Al principio, es posible que debas cambiar manualmente la importancia para enseñar al sistema, pero mejorará con el tiempo."
+ "Error loading message" : "Se presentó un error al cargar el mensaje"
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/l10n/es_EC.json b/l10n/es_EC.json
index b339f8cadd..cd0abbbe12 100644
--- a/l10n/es_EC.json
+++ b/l10n/es_EC.json
@@ -563,7 +563,6 @@
"Could not load your message" : "No fue posible cargar tu mensaje",
"Could not load the desired message" : "No fue posible cargar el mensaje deseado",
"Could not load the message" : "No fue posible cargar el mensaje",
- "Error loading message" : "Se presentó un error al cargar el mensaje",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Los mensajes se marcarán automáticamente como importantes en función de los mensajes con los que interactúes o que marques como importantes. Al principio, es posible que debas cambiar manualmente la importancia para enseñar al sistema, pero mejorará con el tiempo."
+ "Error loading message" : "Se presentó un error al cargar el mensaje"
},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}
\ No newline at end of file
diff --git a/l10n/et_EE.js b/l10n/et_EE.js
index dc482455ff..eef713fa4e 100644
--- a/l10n/et_EE.js
+++ b/l10n/et_EE.js
@@ -849,7 +849,6 @@ OC.L10N.register(
"Could not load your message" : "Sinu kirja laadimine ei õnnestunud",
"Could not load the desired message" : "Soovitud kirja laadimine ei õnnestunud",
"Could not load the message" : "Kirja laadimine ei õnnestunud",
- "Error loading message" : "Viga kirja laadimisel",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Kirjad märgitakse automaatselt oluliseks selle alusel, milliste kirjadega sa suhestud või milliseid sa oluliseks märgid. Alguses võib olla vaja olulisuse taset käsitsi muuta, et süsteemi õpetada, kuid aja jooksul muutub see üha paremaks"
+ "Error loading message" : "Viga kirja laadimisel"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/et_EE.json b/l10n/et_EE.json
index 7b3830602b..cdb2b72db8 100644
--- a/l10n/et_EE.json
+++ b/l10n/et_EE.json
@@ -847,7 +847,6 @@
"Could not load your message" : "Sinu kirja laadimine ei õnnestunud",
"Could not load the desired message" : "Soovitud kirja laadimine ei õnnestunud",
"Could not load the message" : "Kirja laadimine ei õnnestunud",
- "Error loading message" : "Viga kirja laadimisel",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Kirjad märgitakse automaatselt oluliseks selle alusel, milliste kirjadega sa suhestud või milliseid sa oluliseks märgid. Alguses võib olla vaja olulisuse taset käsitsi muuta, et süsteemi õpetada, kuid aja jooksul muutub see üha paremaks"
+ "Error loading message" : "Viga kirja laadimisel"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/eu.js b/l10n/eu.js
index 8d22122705..7a4f9e818a 100644
--- a/l10n/eu.js
+++ b/l10n/eu.js
@@ -704,8 +704,6 @@ OC.L10N.register(
"Could not load your message" : "Ezin izan da zure mezua kargatu",
"Could not load the desired message" : "Ezin izan da kargatu nahi zen mezu hori",
"Could not load the message" : "Ezin izan da mezua kargatu",
- "Error loading message" : "Errorea mezua kargatzerakoan",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Mezuak automatikoki markatuko dira garrantzitsu bezala kontuan izanda zein mezurekin aritu zaren interakzioan edo zein markatu dituzun garratzitsu gisa. Hasieran garrantzia eskuz aldatu beharko duzu sistemari irakasteko, baina denborarekin hobetuko du.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Erantzuteko eskatuz bidali zenituen emailak, baina egun batzuen ondoren erantzunik jasotzen ez dutenak hemen erakutsiko dira."
+ "Error loading message" : "Errorea mezua kargatzerakoan"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/eu.json b/l10n/eu.json
index 9557046c8c..89da052f44 100644
--- a/l10n/eu.json
+++ b/l10n/eu.json
@@ -702,8 +702,6 @@
"Could not load your message" : "Ezin izan da zure mezua kargatu",
"Could not load the desired message" : "Ezin izan da kargatu nahi zen mezu hori",
"Could not load the message" : "Ezin izan da mezua kargatu",
- "Error loading message" : "Errorea mezua kargatzerakoan",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Mezuak automatikoki markatuko dira garrantzitsu bezala kontuan izanda zein mezurekin aritu zaren interakzioan edo zein markatu dituzun garratzitsu gisa. Hasieran garrantzia eskuz aldatu beharko duzu sistemari irakasteko, baina denborarekin hobetuko du.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Erantzuteko eskatuz bidali zenituen emailak, baina egun batzuen ondoren erantzunik jasotzen ez dutenak hemen erakutsiko dira."
+ "Error loading message" : "Errorea mezua kargatzerakoan"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/fa.js b/l10n/fa.js
index 85630df9cf..85663cdff2 100644
--- a/l10n/fa.js
+++ b/l10n/fa.js
@@ -587,7 +587,6 @@ OC.L10N.register(
"Could not load your message" : "پیام شما بارگیری نشد",
"Could not load the desired message" : "پیام مورد نظر بارگیری نشد",
"Could not load the message" : "بارگیری پیام امکان پذیر نیست",
- "Error loading message" : "خطا در بارگزاری پیام",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time."
+ "Error loading message" : "خطا در بارگزاری پیام"
},
"nplurals=2; plural=(n > 1);");
diff --git a/l10n/fa.json b/l10n/fa.json
index 830ee2b57b..a5ba5fffb7 100644
--- a/l10n/fa.json
+++ b/l10n/fa.json
@@ -585,7 +585,6 @@
"Could not load your message" : "پیام شما بارگیری نشد",
"Could not load the desired message" : "پیام مورد نظر بارگیری نشد",
"Could not load the message" : "بارگیری پیام امکان پذیر نیست",
- "Error loading message" : "خطا در بارگزاری پیام",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time."
+ "Error loading message" : "خطا در بارگزاری پیام"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}
\ No newline at end of file
diff --git a/l10n/fr.js b/l10n/fr.js
index 03dbbb7ea8..3b8c2f3450 100644
--- a/l10n/fr.js
+++ b/l10n/fr.js
@@ -904,8 +904,6 @@ OC.L10N.register(
"Could not load your message" : "Impossible de charger votre message",
"Could not load the desired message" : "Impossible de charger le message souhaité",
"Could not load the message" : "Impossible de charger le message",
- "Error loading message" : "Erreur lors du chargement du message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Les messages seront automatiquement marqués comme importants en fonction des messages avec lesquels vous avez interagi et marqués comme importants. Au début, vous devrez manuellement modifier l'importance pour que le système apprenne, mais le marquage automatique va s'améliorer avec le temps.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Les messages que vous avez envoyés et qui n'ont pas reçu de réponse au bout de quelques jours apparaîtront ici."
+ "Error loading message" : "Erreur lors du chargement du message"
},
"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/l10n/fr.json b/l10n/fr.json
index 3c5a447cf9..df37c04bcb 100644
--- a/l10n/fr.json
+++ b/l10n/fr.json
@@ -902,8 +902,6 @@
"Could not load your message" : "Impossible de charger votre message",
"Could not load the desired message" : "Impossible de charger le message souhaité",
"Could not load the message" : "Impossible de charger le message",
- "Error loading message" : "Erreur lors du chargement du message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Les messages seront automatiquement marqués comme importants en fonction des messages avec lesquels vous avez interagi et marqués comme importants. Au début, vous devrez manuellement modifier l'importance pour que le système apprenne, mais le marquage automatique va s'améliorer avec le temps.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Les messages que vous avez envoyés et qui n'ont pas reçu de réponse au bout de quelques jours apparaîtront ici."
+ "Error loading message" : "Erreur lors du chargement du message"
},"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/l10n/ga.js b/l10n/ga.js
index 38b6b897c3..f2b21a1779 100644
--- a/l10n/ga.js
+++ b/l10n/ga.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "Níorbh fhéidir do theachtaireacht a lódáil",
"Could not load the desired message" : "Níorbh fhéidir an teachtaireacht atá uait a luchtú",
"Could not load the message" : "Níorbh fhéidir an teachtaireacht a luchtú",
- "Error loading message" : "Earráid agus an teachtaireacht á lódáil",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Déanfar teachtaireachtaí a mharcáil go huathoibríoch mar thábhachtach, bunaithe ar na teachtaireachtaí a ndearna tú idirghníomhú leo nó a mharcáil tú a bheith tábhachtach. Ar dtús b'fhéidir go mbeadh ort an tábhacht a bhaineann leis an gcóras a mhúineadh a athrú de láimh, ach feabhsóidh sé le himeacht ama.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Taispeánfar anseo teachtaireachtaí a sheol tú a dteastaíonn freagra uathu ach nach bhfuair tú tar éis cúpla lá."
+ "Error loading message" : "Earráid agus an teachtaireacht á lódáil"
},
"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);");
diff --git a/l10n/ga.json b/l10n/ga.json
index 0de0699d34..2c581d672a 100644
--- a/l10n/ga.json
+++ b/l10n/ga.json
@@ -912,8 +912,6 @@
"Could not load your message" : "Níorbh fhéidir do theachtaireacht a lódáil",
"Could not load the desired message" : "Níorbh fhéidir an teachtaireacht atá uait a luchtú",
"Could not load the message" : "Níorbh fhéidir an teachtaireacht a luchtú",
- "Error loading message" : "Earráid agus an teachtaireacht á lódáil",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Déanfar teachtaireachtaí a mharcáil go huathoibríoch mar thábhachtach, bunaithe ar na teachtaireachtaí a ndearna tú idirghníomhú leo nó a mharcáil tú a bheith tábhachtach. Ar dtús b'fhéidir go mbeadh ort an tábhacht a bhaineann leis an gcóras a mhúineadh a athrú de láimh, ach feabhsóidh sé le himeacht ama.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Taispeánfar anseo teachtaireachtaí a sheol tú a dteastaíonn freagra uathu ach nach bhfuair tú tar éis cúpla lá."
+ "Error loading message" : "Earráid agus an teachtaireacht á lódáil"
},"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/l10n/gl.js b/l10n/gl.js
index 2661e03684..b898402f53 100644
--- a/l10n/gl.js
+++ b/l10n/gl.js
@@ -886,8 +886,6 @@ OC.L10N.register(
"Could not load your message" : "Non foi posíbel cargar a súa mensaxe",
"Could not load the desired message" : "Non foi posíbel cargar a mensaxe desexada",
"Could not load the message" : "Non foi posíbel cargar a mensaxe",
- "Error loading message" : "Produciuse un erro ao cargar a mensaxe",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "As mensaxes marcaranse automaticamente como importantes en función das mensaxes coas que interactuou ou que foron marcadas como importantes. No principio, é posíbel que teña que cambiar manualmente a importancia para ensinarlle ao sistema, máis mellorará co paso do tempo",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Aquí amosaranse as mensaxes enviadas por Vde. que requiren unha resposta mais non a recibiron após dun par de días."
+ "Error loading message" : "Produciuse un erro ao cargar a mensaxe"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/gl.json b/l10n/gl.json
index 5ba826d26f..aa951fb0a5 100644
--- a/l10n/gl.json
+++ b/l10n/gl.json
@@ -884,8 +884,6 @@
"Could not load your message" : "Non foi posíbel cargar a súa mensaxe",
"Could not load the desired message" : "Non foi posíbel cargar a mensaxe desexada",
"Could not load the message" : "Non foi posíbel cargar a mensaxe",
- "Error loading message" : "Produciuse un erro ao cargar a mensaxe",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "As mensaxes marcaranse automaticamente como importantes en función das mensaxes coas que interactuou ou que foron marcadas como importantes. No principio, é posíbel que teña que cambiar manualmente a importancia para ensinarlle ao sistema, máis mellorará co paso do tempo",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Aquí amosaranse as mensaxes enviadas por Vde. que requiren unha resposta mais non a recibiron após dun par de días."
+ "Error loading message" : "Produciuse un erro ao cargar a mensaxe"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/hr.js b/l10n/hr.js
index cb287a6068..d10135d738 100644
--- a/l10n/hr.js
+++ b/l10n/hr.js
@@ -888,8 +888,6 @@ OC.L10N.register(
"Could not load your message" : "Učitavanje vaše poruke nije uspjelo",
"Could not load the desired message" : "Ne može se učitati željena poruka",
"Could not load the message" : "Poruku nije moguće učitati",
- "Error loading message" : "Pogreška pri učitavanju poruke",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Poruke se automatski označavaju kao važne na temelju poruka kojima ste rukovali ili koje ste označili kao važne. U početku ćete možda morati ručno mijenjati važnost poruka kako bi sustav zapamtio vaše želje, ali s vremenom će se poboljšati.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Poruke koje ste poslali i koje zahtijevaju odgovor, ali ga nisu dobile nakon nekoliko dana, prikazivat će se ovdje."
+ "Error loading message" : "Pogreška pri učitavanju poruke"
},
"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;");
diff --git a/l10n/hr.json b/l10n/hr.json
index a4cf46a32f..34b325ccd5 100644
--- a/l10n/hr.json
+++ b/l10n/hr.json
@@ -886,8 +886,6 @@
"Could not load your message" : "Učitavanje vaše poruke nije uspjelo",
"Could not load the desired message" : "Ne može se učitati željena poruka",
"Could not load the message" : "Poruku nije moguće učitati",
- "Error loading message" : "Pogreška pri učitavanju poruke",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Poruke se automatski označavaju kao važne na temelju poruka kojima ste rukovali ili koje ste označili kao važne. U početku ćete možda morati ručno mijenjati važnost poruka kako bi sustav zapamtio vaše želje, ali s vremenom će se poboljšati.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Poruke koje ste poslali i koje zahtijevaju odgovor, ali ga nisu dobile nakon nekoliko dana, prikazivat će se ovdje."
+ "Error loading message" : "Pogreška pri učitavanju poruke"
},"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"
}
\ No newline at end of file
diff --git a/l10n/hu.js b/l10n/hu.js
index 571d2a30d1..6c76c75a08 100644
--- a/l10n/hu.js
+++ b/l10n/hu.js
@@ -625,7 +625,6 @@ OC.L10N.register(
"Could not load your message" : "Nem sikerült betölteni az üzenetét",
"Could not load the desired message" : "Nem sikerült betölteni a kért üzenetet",
"Could not load the message" : "Nem sikerült betölteni az üzenetet",
- "Error loading message" : "Hiba történt az üzenet betöltése közben",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Az üzeneteket automatikusan fontosként jelöli meg az alapján, hogy mely üzenetekre reagált, vagy jelölt meg fontosként. Kezdetben lehet, hogy kézzel megváltoztatnia a fontosságot és ezzel kell tanítania a rendszert, de ez az idő múlásával javulni fog."
+ "Error loading message" : "Hiba történt az üzenet betöltése közben"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/hu.json b/l10n/hu.json
index 328c5ca2e1..49464c1098 100644
--- a/l10n/hu.json
+++ b/l10n/hu.json
@@ -623,7 +623,6 @@
"Could not load your message" : "Nem sikerült betölteni az üzenetét",
"Could not load the desired message" : "Nem sikerült betölteni a kért üzenetet",
"Could not load the message" : "Nem sikerült betölteni az üzenetet",
- "Error loading message" : "Hiba történt az üzenet betöltése közben",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Az üzeneteket automatikusan fontosként jelöli meg az alapján, hogy mely üzenetekre reagált, vagy jelölt meg fontosként. Kezdetben lehet, hogy kézzel megváltoztatnia a fontosságot és ezzel kell tanítania a rendszert, de ez az idő múlásával javulni fog."
+ "Error loading message" : "Hiba történt az üzenet betöltése közben"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/id.js b/l10n/id.js
index b3b7ccd709..ef1de34d51 100644
--- a/l10n/id.js
+++ b/l10n/id.js
@@ -881,8 +881,6 @@ OC.L10N.register(
"Could not load your message" : "Tidak dapat memuat pesan Anda",
"Could not load the desired message" : "Tidak dapat memuat pesan yang diinginkan",
"Could not load the message" : "Tidak dapat memuat pesan",
- "Error loading message" : "Kesalahan saat memuat pesan",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Pesan akan otomatis ditandai sebagai penting berdasarkan pesan mana yang Anda interaksikan atau tandai sebagai penting. Pada awalnya Anda mungkin perlu mengubah tingkat kepentingan secara manual untuk mengajarkan sistem, tetapi seiring waktu akan membaik.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Pesan yang Anda kirim yang memerlukan balasan tetapi tidak menerima balasan setelah beberapa hari akan ditampilkan di sini."
+ "Error loading message" : "Kesalahan saat memuat pesan"
},
"nplurals=1; plural=0;");
diff --git a/l10n/id.json b/l10n/id.json
index 9e0f7a5725..3a1ca3a5cd 100644
--- a/l10n/id.json
+++ b/l10n/id.json
@@ -879,8 +879,6 @@
"Could not load your message" : "Tidak dapat memuat pesan Anda",
"Could not load the desired message" : "Tidak dapat memuat pesan yang diinginkan",
"Could not load the message" : "Tidak dapat memuat pesan",
- "Error loading message" : "Kesalahan saat memuat pesan",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Pesan akan otomatis ditandai sebagai penting berdasarkan pesan mana yang Anda interaksikan atau tandai sebagai penting. Pada awalnya Anda mungkin perlu mengubah tingkat kepentingan secara manual untuk mengajarkan sistem, tetapi seiring waktu akan membaik.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Pesan yang Anda kirim yang memerlukan balasan tetapi tidak menerima balasan setelah beberapa hari akan ditampilkan di sini."
+ "Error loading message" : "Kesalahan saat memuat pesan"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/is.js b/l10n/is.js
index 9f841331eb..c520cf4991 100644
--- a/l10n/is.js
+++ b/l10n/is.js
@@ -695,7 +695,6 @@ OC.L10N.register(
"Could not load your message" : "Gat ekki hlaðið inn skilaboðunum þínum",
"Could not load the desired message" : "Gat ekki hlaðið inn umbeðnum skilaboðum",
"Could not load the message" : "Gat ekki hlaðið inn skilaboðunum",
- "Error loading message" : "Villa við hleðslu á skilaboðum",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Skilaboð sem þú sendir og sem þarfnast svars en hafa ekki enn fengið svar eftir nokkra daga, munu birtast hér."
+ "Error loading message" : "Villa við hleðslu á skilaboðum"
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");
diff --git a/l10n/is.json b/l10n/is.json
index 58c2c4d014..8e7f09fd9d 100644
--- a/l10n/is.json
+++ b/l10n/is.json
@@ -693,7 +693,6 @@
"Could not load your message" : "Gat ekki hlaðið inn skilaboðunum þínum",
"Could not load the desired message" : "Gat ekki hlaðið inn umbeðnum skilaboðum",
"Could not load the message" : "Gat ekki hlaðið inn skilaboðunum",
- "Error loading message" : "Villa við hleðslu á skilaboðum",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Skilaboð sem þú sendir og sem þarfnast svars en hafa ekki enn fengið svar eftir nokkra daga, munu birtast hér."
+ "Error loading message" : "Villa við hleðslu á skilaboðum"
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
}
\ No newline at end of file
diff --git a/l10n/it.js b/l10n/it.js
index 9823777e88..dd49c45f45 100644
--- a/l10n/it.js
+++ b/l10n/it.js
@@ -910,8 +910,6 @@ OC.L10N.register(
"Could not load your message" : "Impossibile caricare il tuo messaggio",
"Could not load the desired message" : "Impossibile caricare messaggio desiderato",
"Could not load the message" : "Impossibile caricare il messaggio",
- "Error loading message" : "Errore durante il caricamento del messaggio",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "I messaggi saranno automaticamente contrassegnati come importanti in base ai messaggi con cui hai interagito o contrassegnati come importanti. All'inizio potresti dover cambiare manualmente l'importanza per addestrare il sistema, ma migliorerà nel tempo.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Qui verranno mostrati i messaggi che hai inviato e che richiedono una risposta, ma che non ne hanno ricevuta una dopo alcuni giorni."
+ "Error loading message" : "Errore durante il caricamento del messaggio"
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/l10n/it.json b/l10n/it.json
index e059ffa6e9..a1e7d4787b 100644
--- a/l10n/it.json
+++ b/l10n/it.json
@@ -908,8 +908,6 @@
"Could not load your message" : "Impossibile caricare il tuo messaggio",
"Could not load the desired message" : "Impossibile caricare messaggio desiderato",
"Could not load the message" : "Impossibile caricare il messaggio",
- "Error loading message" : "Errore durante il caricamento del messaggio",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "I messaggi saranno automaticamente contrassegnati come importanti in base ai messaggi con cui hai interagito o contrassegnati come importanti. All'inizio potresti dover cambiare manualmente l'importanza per addestrare il sistema, ma migliorerà nel tempo.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Qui verranno mostrati i messaggi che hai inviato e che richiedono una risposta, ma che non ne hanno ricevuta una dopo alcuni giorni."
+ "Error loading message" : "Errore durante il caricamento del messaggio"
},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}
\ No newline at end of file
diff --git a/l10n/ja.js b/l10n/ja.js
index d2b2633cb8..ee2dca1176 100644
--- a/l10n/ja.js
+++ b/l10n/ja.js
@@ -735,8 +735,6 @@ OC.L10N.register(
"Could not load your message" : "あなたのメッセージを読み込めませんでした",
"Could not load the desired message" : "目的のメッセージを読み込めませんでした",
"Could not load the message" : "メッセージを読み込めませんでした",
- "Error loading message" : "メッセージ読み込みエラー",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "あなたの過去の操作を元にしてメールには自動的に重要マークがつけられます。最初のうちは重要マークを手動でつけたり外したりしてシステムに重要なメールを教える必要がありますが、精度は徐々に向上します。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "返信が必要なメッセージを送信したが、数日経っても返信がない場合は、ここに表示されます。"
+ "Error loading message" : "メッセージ読み込みエラー"
},
"nplurals=1; plural=0;");
diff --git a/l10n/ja.json b/l10n/ja.json
index 470825fae4..a7958ba158 100644
--- a/l10n/ja.json
+++ b/l10n/ja.json
@@ -733,8 +733,6 @@
"Could not load your message" : "あなたのメッセージを読み込めませんでした",
"Could not load the desired message" : "目的のメッセージを読み込めませんでした",
"Could not load the message" : "メッセージを読み込めませんでした",
- "Error loading message" : "メッセージ読み込みエラー",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "あなたの過去の操作を元にしてメールには自動的に重要マークがつけられます。最初のうちは重要マークを手動でつけたり外したりしてシステムに重要なメールを教える必要がありますが、精度は徐々に向上します。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "返信が必要なメッセージを送信したが、数日経っても返信がない場合は、ここに表示されます。"
+ "Error loading message" : "メッセージ読み込みエラー"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/ka.js b/l10n/ka.js
index d03c81769e..9044b4f2e7 100644
--- a/l10n/ka.js
+++ b/l10n/ka.js
@@ -612,7 +612,6 @@ OC.L10N.register(
"Could not load your message" : "Could not load your message",
"Could not load the desired message" : "Could not load the desired message",
"Could not load the message" : "Could not load the message",
- "Error loading message" : "Error loading message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time."
+ "Error loading message" : "Error loading message"
},
"nplurals=2; plural=(n!=1);");
diff --git a/l10n/ka.json b/l10n/ka.json
index 53935e7b59..73f79a812e 100644
--- a/l10n/ka.json
+++ b/l10n/ka.json
@@ -610,7 +610,6 @@
"Could not load your message" : "Could not load your message",
"Could not load the desired message" : "Could not load the desired message",
"Could not load the message" : "Could not load the message",
- "Error loading message" : "Error loading message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time."
+ "Error loading message" : "Error loading message"
},"pluralForm" :"nplurals=2; plural=(n!=1);"
}
\ No newline at end of file
diff --git a/l10n/ko.js b/l10n/ko.js
index 5fa87f803d..3a9488c487 100644
--- a/l10n/ko.js
+++ b/l10n/ko.js
@@ -632,7 +632,6 @@ OC.L10N.register(
"Could not load your message" : "메시지를 불러올 수 없음",
"Could not load the desired message" : "원하는 메시지를 불러올 수 없음",
"Could not load the message" : "메시지를 불러올 수 없음",
- "Error loading message" : "메시지 불러오기 오류",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "사용자의 메시지 상호작용, 중요 표시 정보 등을 바탕으로 특정 메시지가 자동으로 중요 표시됩니다. 초기 단계에서는 시스템의 학습을 위해 사용자가 중요 여부를 수동으로 변경하게 될 수 있으나, 이는 점차 개선될 것입니다."
+ "Error loading message" : "메시지 불러오기 오류"
},
"nplurals=1; plural=0;");
diff --git a/l10n/ko.json b/l10n/ko.json
index 602911b739..3ac615e4c3 100644
--- a/l10n/ko.json
+++ b/l10n/ko.json
@@ -630,7 +630,6 @@
"Could not load your message" : "메시지를 불러올 수 없음",
"Could not load the desired message" : "원하는 메시지를 불러올 수 없음",
"Could not load the message" : "메시지를 불러올 수 없음",
- "Error loading message" : "메시지 불러오기 오류",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "사용자의 메시지 상호작용, 중요 표시 정보 등을 바탕으로 특정 메시지가 자동으로 중요 표시됩니다. 초기 단계에서는 시스템의 학습을 위해 사용자가 중요 여부를 수동으로 변경하게 될 수 있으나, 이는 점차 개선될 것입니다."
+ "Error loading message" : "메시지 불러오기 오류"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/lo.js b/l10n/lo.js
index eddbe997f8..af152002db 100644
--- a/l10n/lo.js
+++ b/l10n/lo.js
@@ -861,8 +861,6 @@ OC.L10N.register(
"Could not load your message" : "Could not load your message",
"Could not load the desired message" : "Could not load the desired message",
"Could not load the message" : "Could not load the message",
- "Error loading message" : "Error loading message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here."
+ "Error loading message" : "Error loading message"
},
"nplurals=1; plural=0;");
diff --git a/l10n/lo.json b/l10n/lo.json
index ce4092003c..9b209de39c 100644
--- a/l10n/lo.json
+++ b/l10n/lo.json
@@ -859,8 +859,6 @@
"Could not load your message" : "Could not load your message",
"Could not load the desired message" : "Could not load the desired message",
"Could not load the message" : "Could not load the message",
- "Error loading message" : "Error loading message",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here."
+ "Error loading message" : "Error loading message"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index a8aa385c44..35065187b5 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "Nepavyko įkelti jūsų laiško",
"Could not load the desired message" : "Nepavyko įkelti pageidaujamo laiško",
"Could not load the message" : "Nepavyko įkelti laiško",
- "Error loading message" : "Klaida įkeliant laišką",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Pranešimai bus automatiškai pažymėti kaip svarbūs, atsižvelgiant į tai, su kuriais pranešimais jūs sąveikavote arba kuriuos pažymėjote kaip svarbius. Pradžioje gali tekti rankiniu būdu pakeisti svarbos lygį, kad sistema išmoktų, tačiau laikui bėgant ji tobulės.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Čia bus rodomos jūsų išsiųstos žinutės, į kurias reikia atsakyti, bet per keletą dienų atsakymo negauta."
+ "Error loading message" : "Klaida įkeliant laišką"
},
"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/l10n/lt_LT.json b/l10n/lt_LT.json
index 146c687c92..70017575c9 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -912,8 +912,6 @@
"Could not load your message" : "Nepavyko įkelti jūsų laiško",
"Could not load the desired message" : "Nepavyko įkelti pageidaujamo laiško",
"Could not load the message" : "Nepavyko įkelti laiško",
- "Error loading message" : "Klaida įkeliant laišką",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Pranešimai bus automatiškai pažymėti kaip svarbūs, atsižvelgiant į tai, su kuriais pranešimais jūs sąveikavote arba kuriuos pažymėjote kaip svarbius. Pradžioje gali tekti rankiniu būdu pakeisti svarbos lygį, kad sistema išmoktų, tačiau laikui bėgant ji tobulės.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Čia bus rodomos jūsų išsiųstos žinutės, į kurias reikia atsakyti, bet per keletą dienų atsakymo negauta."
+ "Error loading message" : "Klaida įkeliant laišką"
},"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/l10n/mk.js b/l10n/mk.js
index 3b2142268d..7cebe56c23 100644
--- a/l10n/mk.js
+++ b/l10n/mk.js
@@ -148,6 +148,7 @@ OC.L10N.register(
"Disable formatting" : "Оневозможи форматирање",
"Upload attachment" : "Прикачи прилог",
"Add attachment from Files" : "Додади прилог од датотеките",
+ "Smart picker" : "Паметен избирач",
"Request a read receipt" : "Побарај потврда за прочитана порака",
"Sign message with S/MIME" : "Потпиши ја пораката со S/MIME",
"Encrypt message with S/MIME" : "Шифрирај порака со S/MIME",
@@ -455,7 +456,6 @@ OC.L10N.register(
"Could not load your message" : "Неможе да се вчита пораката",
"Could not load the desired message" : "Неможе да се вчита посакуваната порака",
"Could not load the message" : "Неможе да се вчита пораката",
- "Error loading message" : "Грешка при вчитување на пораката",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Пораките автоматски ќе бидат означени како важни врз основа на кои пораки сте комуницирале или сте ги означиле како важни. На почетокот можеби ќе треба рачно да ја менувате важноста да го научите системот, но тоа ќе се подобрува со текот на времето."
+ "Error loading message" : "Грешка при вчитување на пораката"
},
"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;");
diff --git a/l10n/mk.json b/l10n/mk.json
index 6b04a1edbd..f9478521e9 100644
--- a/l10n/mk.json
+++ b/l10n/mk.json
@@ -146,6 +146,7 @@
"Disable formatting" : "Оневозможи форматирање",
"Upload attachment" : "Прикачи прилог",
"Add attachment from Files" : "Додади прилог од датотеките",
+ "Smart picker" : "Паметен избирач",
"Request a read receipt" : "Побарај потврда за прочитана порака",
"Sign message with S/MIME" : "Потпиши ја пораката со S/MIME",
"Encrypt message with S/MIME" : "Шифрирај порака со S/MIME",
@@ -453,7 +454,6 @@
"Could not load your message" : "Неможе да се вчита пораката",
"Could not load the desired message" : "Неможе да се вчита посакуваната порака",
"Could not load the message" : "Неможе да се вчита пораката",
- "Error loading message" : "Грешка при вчитување на пораката",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Пораките автоматски ќе бидат означени како важни врз основа на кои пораки сте комуницирале или сте ги означиле како важни. На почетокот можеби ќе треба рачно да ја менувате важноста да го научите системот, но тоа ќе се подобрува со текот на времето."
+ "Error loading message" : "Грешка при вчитување на пораката"
},"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"
}
\ No newline at end of file
diff --git a/l10n/mn.js b/l10n/mn.js
index c830af9647..8407898e74 100644
--- a/l10n/mn.js
+++ b/l10n/mn.js
@@ -867,8 +867,6 @@ OC.L10N.register(
"Could not load your message" : "Таны зурвасыг ачаалах боломжгүй",
"Could not load the desired message" : "Хүссэн зурвасыг ачаалах боломжгүй",
"Could not load the message" : "Зурвас ачаалах боломжгүй",
- "Error loading message" : "–∞–ª–¥–∞–∞—Ç–∞–π –∞—á–∞–∞–ª–ª–∞—Ö –∑—É—Ä–≤–∞—Å",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Таны ямар зурвастай харилцаж байсан эсвэл чухал гэж тэмдэглэсэн дээр суурилан зурвасууд автоматаар чухал гэж тэмдэглэгдэнэ. Эхэндээ та системд заахын тулд чухлын зэргийг гараар өөрчлөх шаардлагатай байж магадгүй, гэхдээ цаг хугацааны явцад сайжирна.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Таны илгээсэн зурвасуудаас хариу шаардлагатай боловч хэд хоногийн дараа хариу аваагүй зурвасууд энд харагдана."
+ "Error loading message" : "–∞–ª–¥–∞–∞—Ç–∞–π –∞—á–∞–∞–ª–ª–∞—Ö –∑—É—Ä–≤–∞—Å"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/mn.json b/l10n/mn.json
index 26a2c0cfa4..1408b0706d 100644
--- a/l10n/mn.json
+++ b/l10n/mn.json
@@ -865,8 +865,6 @@
"Could not load your message" : "Таны зурвасыг ачаалах боломжгүй",
"Could not load the desired message" : "Хүссэн зурвасыг ачаалах боломжгүй",
"Could not load the message" : "Зурвас ачаалах боломжгүй",
- "Error loading message" : "–∞–ª–¥–∞–∞—Ç–∞–π –∞—á–∞–∞–ª–ª–∞—Ö –∑—É—Ä–≤–∞—Å",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Таны ямар зурвастай харилцаж байсан эсвэл чухал гэж тэмдэглэсэн дээр суурилан зурвасууд автоматаар чухал гэж тэмдэглэгдэнэ. Эхэндээ та системд заахын тулд чухлын зэргийг гараар өөрчлөх шаардлагатай байж магадгүй, гэхдээ цаг хугацааны явцад сайжирна.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Таны илгээсэн зурвасуудаас хариу шаардлагатай боловч хэд хоногийн дараа хариу аваагүй зурвасууд энд харагдана."
+ "Error loading message" : "–∞–ª–¥–∞–∞—Ç–∞–π –∞—á–∞–∞–ª–ª–∞—Ö –∑—É—Ä–≤–∞—Å"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/nb.js b/l10n/nb.js
index f32d245c57..2f171b6c6d 100644
--- a/l10n/nb.js
+++ b/l10n/nb.js
@@ -693,8 +693,6 @@ OC.L10N.register(
"Could not load your message" : "Kunne ikke laste meldingene dine",
"Could not load the desired message" : "Kunne ikke laste den ønskede meldingen",
"Could not load the message" : "Kunne ikke laste meldingen",
- "Error loading message" : "Feil ved innlasting av melding",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Meldinger blir automatisk merket som viktige basert på hvilke meldinger du har interagert med eller merket som viktige. I begynnelsen må du kanskje endre viktigheten manuelt for å lære systemet, men det vil forbedres over tid.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Meldinger sendt av deg som krever svar, men ikke mottok en etter et par dager, vises her."
+ "Error loading message" : "Feil ved innlasting av melding"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/nb.json b/l10n/nb.json
index 894e25ac84..671a729248 100644
--- a/l10n/nb.json
+++ b/l10n/nb.json
@@ -691,8 +691,6 @@
"Could not load your message" : "Kunne ikke laste meldingene dine",
"Could not load the desired message" : "Kunne ikke laste den ønskede meldingen",
"Could not load the message" : "Kunne ikke laste meldingen",
- "Error loading message" : "Feil ved innlasting av melding",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Meldinger blir automatisk merket som viktige basert på hvilke meldinger du har interagert med eller merket som viktige. I begynnelsen må du kanskje endre viktigheten manuelt for å lære systemet, men det vil forbedres over tid.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Meldinger sendt av deg som krever svar, men ikke mottok en etter et par dager, vises her."
+ "Error loading message" : "Feil ved innlasting av melding"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/nl.js b/l10n/nl.js
index ef6bf0ecd8..4814d75067 100644
--- a/l10n/nl.js
+++ b/l10n/nl.js
@@ -698,8 +698,6 @@ OC.L10N.register(
"Could not load your message" : "Kon je bericht niet laden",
"Could not load the desired message" : "Kon het gewenste bericht niet laden",
"Could not load the message" : "Kon het bericht niet laden",
- "Error loading message" : "Fout bij laden bericht",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Berichten zullen automatisch als belangrijk gemarkeerd worden, gebaseerd op met welke berichten je gewerkt hebt of welke je als belangrijk hebt gemarkeerd. In het begin moet je misschien handmatig de belangrijkheid aanpassen om het systeem in te leren, maar het wordt beter met de tijd.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Door jouw verzonden berichten die een antwoord vereisen maar die na enkele dagen nog geen reactie hebben ontvangen worden hier getoond."
+ "Error loading message" : "Fout bij laden bericht"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/nl.json b/l10n/nl.json
index 249a997c1d..8b503d89bb 100644
--- a/l10n/nl.json
+++ b/l10n/nl.json
@@ -696,8 +696,6 @@
"Could not load your message" : "Kon je bericht niet laden",
"Could not load the desired message" : "Kon het gewenste bericht niet laden",
"Could not load the message" : "Kon het bericht niet laden",
- "Error loading message" : "Fout bij laden bericht",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Berichten zullen automatisch als belangrijk gemarkeerd worden, gebaseerd op met welke berichten je gewerkt hebt of welke je als belangrijk hebt gemarkeerd. In het begin moet je misschien handmatig de belangrijkheid aanpassen om het systeem in te leren, maar het wordt beter met de tijd.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Door jouw verzonden berichten die een antwoord vereisen maar die na enkele dagen nog geen reactie hebben ontvangen worden hier getoond."
+ "Error loading message" : "Fout bij laden bericht"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/pl.js b/l10n/pl.js
index 90ab0010ed..e3688a7ec3 100644
--- a/l10n/pl.js
+++ b/l10n/pl.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "Poczta",
"You are reaching your mailbox quota limit for {account_email}" : "Osiągnięto limit skrzynki pocztowej dla {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Obecnie używasz {percentage} przestrzeni dyskowej skrzynki pocztowej. Zrób trochę miejsca, usuwając niepotrzebne wiadomości e-mail.",
+ "{account_email} has been delegated to you" : "{account_email} zostało delegowane do Ciebie ",
+ "{user} delegated {account} to you" : "{user} delegował konto {account} do Ciebie",
+ "{account_email} is no longer delegated to you" : "{account_email} nie jest już delegowane do Ciebie",
+ "{user} revoked delegation for {account}" : "{user} cofnął/cofnęła delegację dla {account}",
"Mail Application" : "Aplikacja poczty",
"Mails" : "E-maile",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Adres e-mail nadawcy %1$s: nie znajduje się w książce adresowej, ale nazwa nadawcy: %2$s znajduje się w książce adresowej pod następującym adresem e-mail: %3$s",
@@ -93,6 +97,8 @@ OC.L10N.register(
"SMTP Port" : "Port SMTP",
"SMTP User" : "Użytkownik SMTP",
"SMTP Password" : "Hasło SMTP",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google wymaga uwierzytelniania OAuth. Jeśli administrator Nextcloud nie skonfigurował OAuth Google, możesz zamiast tego użyć hasła aplikacji Google.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft wymaga uwierzytelniania OAuth. Poproś administratora Nextcloud o skonfigurowanie OAuth Microsoft w ustawieniach administracyjnych.",
"Account settings" : "Ustawienia konta",
"Aliases" : "Aliasy",
"Alias to S/MIME certificate mapping" : "Mapowanie aliasu do certyfikatu S/MIME",
@@ -135,6 +141,7 @@ OC.L10N.register(
"Mail settings" : "Ustawienia Poczty",
"General" : "Ogólne",
"Set as default mail app" : "Ustaw jako domyślną aplikację poczty",
+ "{email} (delegated)" : "{email} (delegowany)",
"Add mail account" : "Dodaj konto e-mail",
"Appearance" : "Wygląd",
"Show all messages in thread" : "Pokaż wszystkie wiadomości w wątku",
@@ -253,7 +260,21 @@ OC.L10N.register(
"Expand composer" : "Rozwiń edytor wiadomości",
"Close composer" : "Zamknij edytor wiadomości",
"Confirm" : "Potwierdź",
+ "Delegate access" : "Deleguj dostęp",
"Revoke" : "Cofnij",
+ "{userId} will no longer be able to act on your behalf" : "{userId} nie będzie już mógł/mogła działać w Twoim imieniu",
+ "Could not fetch delegates" : "Nie udało się pobrać delegatów",
+ "Delegated access to {userId}" : "Dostęp został delegowany do {userId}",
+ "Could not delegate access" : "Nie udało się delegować dostępu",
+ "Revoked access for {userId}" : "Cofnięto dostęp dla {userId}",
+ "Could not revoke delegation" : "Nie udało się cofnąć delegacji",
+ "Delegation" : "Delegacja",
+ "Allow users to send, receive, and delete mail on your behalf" : "Pozwól użytkownikom wysyłać, odbierać i usuwać pocztę w Twoim imieniu",
+ "Revoke access" : "Cofnij dostęp",
+ "Add delegate" : "Dodaj delegata",
+ "Select a user" : "Wybierz użytkownika",
+ "They will be able to send, receive, and delete mail on your behalf" : "Będzie mógł/mogła wysyłać, odbierać i usuwać pocztę w Twoim imieniu",
+ "Revoke access?" : "Cofnąć dostęp?",
"Tag: {name} deleted" : "Tag: {name} usunięty",
"An error occurred, unable to delete the tag." : "Wystąpił błąd, nie udało się usunąć tagu.",
"The tag will be deleted from all messages." : "Tag zostanie usunięty ze wszystkich wiadomości.",
@@ -381,7 +402,9 @@ OC.L10N.register(
"Indexing your messages. This can take a bit longer for larger folders." : "Indeksowanie twoich wiadomości. Może to zająć trochę więcej czasu dla większych folderów",
"Choose target folder" : "Wybierz katalog docelowy",
"No more submailboxes in here" : "Nie ma więcej skrzynek podrzędnych",
+ "Messages will automatically be marked as important using AI. The system learns from which messages you interact with or mark as important. In the beginning you might have to manually change the importance to teach it, but it will improve over time" : "Wiadomości będą automatycznie oznaczane jako ważne przy użyciu AI. System uczy się na podstawie wiadomości, które oznaczasz jako ważne lub nieważne. Na początku może być konieczna ręczna zmiana ważności, aby go nauczyć, ale z czasem będzie się poprawiał",
"Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "Wiadomości oznaczone jako ulubione będą wyświetlane na górze folderów. Możesz wyłączyć to zachowanie w ustawieniach aplikacji",
+ "AI identifies messages sent by you that likely require a reply but did not receive one after a couple of days and shows them here" : "AI identyfikuje wiadomości wysłane przez Ciebie, które prawdopodobnie wymagają odpowiedzi, ale nie otrzymały jej po kilku dniach, i wyświetla je tutaj",
"Favorites" : "Ulubione",
"Favorites info" : "Informacje o ulubionych",
"Load more favorites" : "Załaduj więcej ulubionych",
@@ -408,8 +431,10 @@ OC.L10N.register(
"Print message" : "Drukuj wiadomość",
"Create mail filter" : "Utwórz filtr poczty",
"Download thread data for debugging" : "Pobierz dane wątku do debugowania",
+ "Suggested replies are using AI" : "Sugerowane odpowiedzi wykorzystują AI",
"Message body" : "Treść wiadomości",
"Warning: The S/MIME signature of this message is unverified. The sender might be impersonating someone!" : "Ostrzeżenie: Podpis S/MIME tej wiadomości jest niezweryfikowany. Nadawca może podszywać się pod kogoś!",
+ "AI info" : "Informacje o AI",
"Unnamed" : "Bez nazwy",
"Embedded message" : "Osadzona wiadomość",
"Attachment saved to Files" : "Załącznik zapisany w plikach.",
@@ -446,8 +471,10 @@ OC.L10N.register(
"Remove account" : "Usuń konto",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Konto dla {email} i zapisane w pamięci podręcznej dane e-mail zostaną usunięte z Nextcloud, ale pozostaną nadal u dostawcy poczty e-mail.",
"Remove {email}" : "Usuń {email}",
+ "could not delete account" : "nie udało się usunąć konta",
"Provisioned account is disabled" : "Zabezpieczone konto jest wyłączone",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Zaloguj się przy użyciu hasła, aby włączyć to konto. Bieżąca sesja korzysta z uwierzytelniania bez hasła, m.in. SSO lub WebAuthn.",
+ "Delegate account" : "Deleguj konto",
"Show only subscribed folders" : "Pokaż tylko subskrybowane foldery",
"Add folder" : "Dodaj katalog",
"Folder name" : "Nazwa katalogu",
@@ -620,6 +647,9 @@ OC.L10N.register(
"Reply to sender only" : "Odpowiedz tylko nadawcy",
"Mark as unfavorite" : "Oznacz jako nieulubione",
"Mark as favorite" : "Oznacz jako nieulubione",
+ "To:" : "Do:",
+ "Cc:" : "DW:",
+ "Bcc:" : "UDW:",
"Unsubscribe via link" : "Wypisz się przez link",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Wypisanie zatrzyma wszystkie wiadomości z listy mailingowej od {sender}",
"Send unsubscribe email" : "Wyślij e-mail wypisujący",
@@ -639,6 +669,7 @@ OC.L10N.register(
"Target language to translate into" : "Język docelowy, na który chcesz tłumaczyć",
"Translate to" : "Przetłumacz na",
"Translating" : "Tłumaczenie",
+ "This translation is generated using AI and may contain inaccuracies" : "To tłumaczenie zostało wygenerowane przez AI i może zawierać błędy",
"Copy translated text" : "Kopiuj przetłumaczony tekst",
"Disable trash retention by leaving the field empty or setting it to 0. Only mails deleted after enabling trash retention will be processed." : "Wyłącz przechowywanie kosza pozostawiając pole puste lub ustawiając je na 0. Przetwarzane będą tylko maile usunięte po włączeniu przechowywania kosza.",
"Could not remove trusted sender {sender}" : "Nie udało się usunąć zaufanego nadawcy {sender}",
@@ -869,6 +900,7 @@ OC.L10N.register(
"Discard changes" : "Odrzuć zmiany",
"Discard unsaved changes" : "Odrzuć niezapisane zmiany",
"Keep editing message" : "Kontynuuj edycję wiadomości",
+ "(All or part of this reply was generated by AI)" : "(Całość lub część tej odpowiedzi została wygenerowana przez AI)",
"Attachments were not copied. Please add them manually." : "Załączniki nie zostały skopiowane. Dodaj je ręcznie.",
"Could not create snooze mailbox" : "Nie udało się utworzyć skrzynki pocztowej drzemki (snooze mailbox)",
"Sorry, the message could not be loaded. The draft may no longer exist. Please refresh the page and try again." : "Przepraszamy, nie udało się wczytać wiadomości. Wersja robocza mogła już nie istnieć. Odśwież stronę i spróbuj ponownie.",
@@ -882,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "Nie można wczytać wiadomości",
"Could not load the desired message" : "Nie można wczytać żądanej wiadomości",
"Could not load the message" : "Nie można wczytać wiadomości",
- "Error loading message" : "Błąd podczas wczytywania wiadomości",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Wiadomości będą automatycznie oznaczane jako ważne na podstawie wiadomości, z którymi wchodziłeś w interakcję lub które oznaczałeś jako ważne. Na początku być może trzeba będzie ręcznie zmienić ważność dla uczenia systemu, ale z czasem będzie się poprawiać.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Wiadomości wysłane przez ciebie, które wymagają odpowiedzi, ale jej nie otrzymały po kilku dniach, będą wyświetlane tutaj"
+ "Error loading message" : "Błąd podczas wczytywania wiadomości"
},
"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/l10n/pl.json b/l10n/pl.json
index b32b839000..26c045a962 100644
--- a/l10n/pl.json
+++ b/l10n/pl.json
@@ -12,6 +12,10 @@
"Mail" : "Poczta",
"You are reaching your mailbox quota limit for {account_email}" : "Osiągnięto limit skrzynki pocztowej dla {account_email}",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Obecnie używasz {percentage} przestrzeni dyskowej skrzynki pocztowej. Zrób trochę miejsca, usuwając niepotrzebne wiadomości e-mail.",
+ "{account_email} has been delegated to you" : "{account_email} zostało delegowane do Ciebie ",
+ "{user} delegated {account} to you" : "{user} delegował konto {account} do Ciebie",
+ "{account_email} is no longer delegated to you" : "{account_email} nie jest już delegowane do Ciebie",
+ "{user} revoked delegation for {account}" : "{user} cofnął/cofnęła delegację dla {account}",
"Mail Application" : "Aplikacja poczty",
"Mails" : "E-maile",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Adres e-mail nadawcy %1$s: nie znajduje się w książce adresowej, ale nazwa nadawcy: %2$s znajduje się w książce adresowej pod następującym adresem e-mail: %3$s",
@@ -91,6 +95,8 @@
"SMTP Port" : "Port SMTP",
"SMTP User" : "Użytkownik SMTP",
"SMTP Password" : "Hasło SMTP",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google wymaga uwierzytelniania OAuth. Jeśli administrator Nextcloud nie skonfigurował OAuth Google, możesz zamiast tego użyć hasła aplikacji Google.",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft wymaga uwierzytelniania OAuth. Poproś administratora Nextcloud o skonfigurowanie OAuth Microsoft w ustawieniach administracyjnych.",
"Account settings" : "Ustawienia konta",
"Aliases" : "Aliasy",
"Alias to S/MIME certificate mapping" : "Mapowanie aliasu do certyfikatu S/MIME",
@@ -133,6 +139,7 @@
"Mail settings" : "Ustawienia Poczty",
"General" : "Ogólne",
"Set as default mail app" : "Ustaw jako domyślną aplikację poczty",
+ "{email} (delegated)" : "{email} (delegowany)",
"Add mail account" : "Dodaj konto e-mail",
"Appearance" : "Wygląd",
"Show all messages in thread" : "Pokaż wszystkie wiadomości w wątku",
@@ -251,7 +258,21 @@
"Expand composer" : "Rozwiń edytor wiadomości",
"Close composer" : "Zamknij edytor wiadomości",
"Confirm" : "Potwierdź",
+ "Delegate access" : "Deleguj dostęp",
"Revoke" : "Cofnij",
+ "{userId} will no longer be able to act on your behalf" : "{userId} nie będzie już mógł/mogła działać w Twoim imieniu",
+ "Could not fetch delegates" : "Nie udało się pobrać delegatów",
+ "Delegated access to {userId}" : "Dostęp został delegowany do {userId}",
+ "Could not delegate access" : "Nie udało się delegować dostępu",
+ "Revoked access for {userId}" : "Cofnięto dostęp dla {userId}",
+ "Could not revoke delegation" : "Nie udało się cofnąć delegacji",
+ "Delegation" : "Delegacja",
+ "Allow users to send, receive, and delete mail on your behalf" : "Pozwól użytkownikom wysyłać, odbierać i usuwać pocztę w Twoim imieniu",
+ "Revoke access" : "Cofnij dostęp",
+ "Add delegate" : "Dodaj delegata",
+ "Select a user" : "Wybierz użytkownika",
+ "They will be able to send, receive, and delete mail on your behalf" : "Będzie mógł/mogła wysyłać, odbierać i usuwać pocztę w Twoim imieniu",
+ "Revoke access?" : "Cofnąć dostęp?",
"Tag: {name} deleted" : "Tag: {name} usunięty",
"An error occurred, unable to delete the tag." : "Wystąpił błąd, nie udało się usunąć tagu.",
"The tag will be deleted from all messages." : "Tag zostanie usunięty ze wszystkich wiadomości.",
@@ -379,7 +400,9 @@
"Indexing your messages. This can take a bit longer for larger folders." : "Indeksowanie twoich wiadomości. Może to zająć trochę więcej czasu dla większych folderów",
"Choose target folder" : "Wybierz katalog docelowy",
"No more submailboxes in here" : "Nie ma więcej skrzynek podrzędnych",
+ "Messages will automatically be marked as important using AI. The system learns from which messages you interact with or mark as important. In the beginning you might have to manually change the importance to teach it, but it will improve over time" : "Wiadomości będą automatycznie oznaczane jako ważne przy użyciu AI. System uczy się na podstawie wiadomości, które oznaczasz jako ważne lub nieważne. Na początku może być konieczna ręczna zmiana ważności, aby go nauczyć, ale z czasem będzie się poprawiał",
"Messages that you marked as favorite will be shown at the top of folders. You can disable this behavior in the app settings" : "Wiadomości oznaczone jako ulubione będą wyświetlane na górze folderów. Możesz wyłączyć to zachowanie w ustawieniach aplikacji",
+ "AI identifies messages sent by you that likely require a reply but did not receive one after a couple of days and shows them here" : "AI identyfikuje wiadomości wysłane przez Ciebie, które prawdopodobnie wymagają odpowiedzi, ale nie otrzymały jej po kilku dniach, i wyświetla je tutaj",
"Favorites" : "Ulubione",
"Favorites info" : "Informacje o ulubionych",
"Load more favorites" : "Załaduj więcej ulubionych",
@@ -406,8 +429,10 @@
"Print message" : "Drukuj wiadomość",
"Create mail filter" : "Utwórz filtr poczty",
"Download thread data for debugging" : "Pobierz dane wątku do debugowania",
+ "Suggested replies are using AI" : "Sugerowane odpowiedzi wykorzystują AI",
"Message body" : "Treść wiadomości",
"Warning: The S/MIME signature of this message is unverified. The sender might be impersonating someone!" : "Ostrzeżenie: Podpis S/MIME tej wiadomości jest niezweryfikowany. Nadawca może podszywać się pod kogoś!",
+ "AI info" : "Informacje o AI",
"Unnamed" : "Bez nazwy",
"Embedded message" : "Osadzona wiadomość",
"Attachment saved to Files" : "Załącznik zapisany w plikach.",
@@ -444,8 +469,10 @@
"Remove account" : "Usuń konto",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "Konto dla {email} i zapisane w pamięci podręcznej dane e-mail zostaną usunięte z Nextcloud, ale pozostaną nadal u dostawcy poczty e-mail.",
"Remove {email}" : "Usuń {email}",
+ "could not delete account" : "nie udało się usunąć konta",
"Provisioned account is disabled" : "Zabezpieczone konto jest wyłączone",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Zaloguj się przy użyciu hasła, aby włączyć to konto. Bieżąca sesja korzysta z uwierzytelniania bez hasła, m.in. SSO lub WebAuthn.",
+ "Delegate account" : "Deleguj konto",
"Show only subscribed folders" : "Pokaż tylko subskrybowane foldery",
"Add folder" : "Dodaj katalog",
"Folder name" : "Nazwa katalogu",
@@ -618,6 +645,9 @@
"Reply to sender only" : "Odpowiedz tylko nadawcy",
"Mark as unfavorite" : "Oznacz jako nieulubione",
"Mark as favorite" : "Oznacz jako nieulubione",
+ "To:" : "Do:",
+ "Cc:" : "DW:",
+ "Bcc:" : "UDW:",
"Unsubscribe via link" : "Wypisz się przez link",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Wypisanie zatrzyma wszystkie wiadomości z listy mailingowej od {sender}",
"Send unsubscribe email" : "Wyślij e-mail wypisujący",
@@ -637,6 +667,7 @@
"Target language to translate into" : "Język docelowy, na który chcesz tłumaczyć",
"Translate to" : "Przetłumacz na",
"Translating" : "Tłumaczenie",
+ "This translation is generated using AI and may contain inaccuracies" : "To tłumaczenie zostało wygenerowane przez AI i może zawierać błędy",
"Copy translated text" : "Kopiuj przetłumaczony tekst",
"Disable trash retention by leaving the field empty or setting it to 0. Only mails deleted after enabling trash retention will be processed." : "Wyłącz przechowywanie kosza pozostawiając pole puste lub ustawiając je na 0. Przetwarzane będą tylko maile usunięte po włączeniu przechowywania kosza.",
"Could not remove trusted sender {sender}" : "Nie udało się usunąć zaufanego nadawcy {sender}",
@@ -867,6 +898,7 @@
"Discard changes" : "Odrzuć zmiany",
"Discard unsaved changes" : "Odrzuć niezapisane zmiany",
"Keep editing message" : "Kontynuuj edycję wiadomości",
+ "(All or part of this reply was generated by AI)" : "(Całość lub część tej odpowiedzi została wygenerowana przez AI)",
"Attachments were not copied. Please add them manually." : "Załączniki nie zostały skopiowane. Dodaj je ręcznie.",
"Could not create snooze mailbox" : "Nie udało się utworzyć skrzynki pocztowej drzemki (snooze mailbox)",
"Sorry, the message could not be loaded. The draft may no longer exist. Please refresh the page and try again." : "Przepraszamy, nie udało się wczytać wiadomości. Wersja robocza mogła już nie istnieć. Odśwież stronę i spróbuj ponownie.",
@@ -880,8 +912,6 @@
"Could not load your message" : "Nie można wczytać wiadomości",
"Could not load the desired message" : "Nie można wczytać żądanej wiadomości",
"Could not load the message" : "Nie można wczytać wiadomości",
- "Error loading message" : "Błąd podczas wczytywania wiadomości",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Wiadomości będą automatycznie oznaczane jako ważne na podstawie wiadomości, z którymi wchodziłeś w interakcję lub które oznaczałeś jako ważne. Na początku być może trzeba będzie ręcznie zmienić ważność dla uczenia systemu, ale z czasem będzie się poprawiać.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Wiadomości wysłane przez ciebie, które wymagają odpowiedzi, ale jej nie otrzymały po kilku dniach, będą wyświetlane tutaj"
+ "Error loading message" : "Błąd podczas wczytywania wiadomości"
},"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/l10n/pt_BR.js b/l10n/pt_BR.js
index fab1e12411..f0d416faaa 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "Não foi possível carregar sua mensagem",
"Could not load the desired message" : "Não foi possível carregar a mensagem desejada",
"Could not load the message" : "Não foi possível carregar a mensagem",
- "Error loading message" : "Erro carregando mensagem",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "As mensagens serão automaticamente marcadas como importantes com base nas mensagens com as quais você interagiu ou marcou como importantes. No início você pode ter que mudar manualmente a importância para ensinar o sistema, mas ele irá melhorar com o tempo.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "As mensagens enviadas por você que exigem uma resposta, mas não receberam uma após alguns dias, serão mostradas aqui."
+ "Error loading message" : "Erro carregando mensagem"
},
"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index 1a010947e8..c3e06c4021 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -912,8 +912,6 @@
"Could not load your message" : "Não foi possível carregar sua mensagem",
"Could not load the desired message" : "Não foi possível carregar a mensagem desejada",
"Could not load the message" : "Não foi possível carregar a mensagem",
- "Error loading message" : "Erro carregando mensagem",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "As mensagens serão automaticamente marcadas como importantes com base nas mensagens com as quais você interagiu ou marcou como importantes. No início você pode ter que mudar manualmente a importância para ensinar o sistema, mas ele irá melhorar com o tempo.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "As mensagens enviadas por você que exigem uma resposta, mas não receberam uma após alguns dias, serão mostradas aqui."
+ "Error loading message" : "Erro carregando mensagem"
},"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/l10n/ro.js b/l10n/ro.js
index b7e1fe42c6..0649bfec3e 100644
--- a/l10n/ro.js
+++ b/l10n/ro.js
@@ -489,7 +489,6 @@ OC.L10N.register(
"Could not load your message" : "Mesajul nu s-a putut încărca",
"Could not load the desired message" : "Nu s-a putut încărca mesajul dorit",
"Could not load the message" : "Nu s-a putut încărca mesajul",
- "Error loading message" : "Eroare la încărcarea mesajelor",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Mesajul va fi marcat automat ca important în funcție de mesajele cu care ați interacționat sau pe care le-ați marcat ca importante. La început ar trebui să setați manual importanța pentru antrenarea sistemului, dar aceasta se va îmbunătăți în timp."
+ "Error loading message" : "Eroare la încărcarea mesajelor"
},
"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/l10n/ro.json b/l10n/ro.json
index b44ebdb016..fa93d800ae 100644
--- a/l10n/ro.json
+++ b/l10n/ro.json
@@ -487,7 +487,6 @@
"Could not load your message" : "Mesajul nu s-a putut încărca",
"Could not load the desired message" : "Nu s-a putut încărca mesajul dorit",
"Could not load the message" : "Nu s-a putut încărca mesajul",
- "Error loading message" : "Eroare la încărcarea mesajelor",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Mesajul va fi marcat automat ca important în funcție de mesajele cu care ați interacționat sau pe care le-ați marcat ca importante. La început ar trebui să setați manual importanța pentru antrenarea sistemului, dar aceasta se va îmbunătăți în timp."
+ "Error loading message" : "Eroare la încărcarea mesajelor"
},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
}
\ No newline at end of file
diff --git a/l10n/ru.js b/l10n/ru.js
index ad0b0c904d..81d008fc99 100644
--- a/l10n/ru.js
+++ b/l10n/ru.js
@@ -785,8 +785,6 @@ OC.L10N.register(
"Could not load your message" : "Ошибка получения вашего сообщения",
"Could not load the desired message" : "Ошибка получения указанного сообщения",
"Could not load the message" : "Ошибка получения этого сообщения",
- "Error loading message" : "Ошибка загрузки сообщения",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Письма будут автоматически отмечаться важными на основе анализа ваших действий и присвоения метки «Важно». В первое время, возможно, потребуется обучить систему присвоением и удалением меток вручную.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Здесь будут отображаться отправленные вами сообщения, требующие ответа, но не полученные в течение нескольких дней."
+ "Error loading message" : "Ошибка загрузки сообщения"
},
"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/l10n/ru.json b/l10n/ru.json
index a88bf4228b..cef5d3f65a 100644
--- a/l10n/ru.json
+++ b/l10n/ru.json
@@ -783,8 +783,6 @@
"Could not load your message" : "Ошибка получения вашего сообщения",
"Could not load the desired message" : "Ошибка получения указанного сообщения",
"Could not load the message" : "Ошибка получения этого сообщения",
- "Error loading message" : "Ошибка загрузки сообщения",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Письма будут автоматически отмечаться важными на основе анализа ваших действий и присвоения метки «Важно». В первое время, возможно, потребуется обучить систему присвоением и удалением меток вручную.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Здесь будут отображаться отправленные вами сообщения, требующие ответа, но не полученные в течение нескольких дней."
+ "Error loading message" : "Ошибка загрузки сообщения"
},"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/l10n/sc.js b/l10n/sc.js
index 283e8b54fe..b5736ebe2c 100644
--- a/l10n/sc.js
+++ b/l10n/sc.js
@@ -336,7 +336,6 @@ OC.L10N.register(
"Could not load your message" : "No at fatu a carrigare su messàgiu tuo",
"Could not load the desired message" : "No at fatu a carrigare su messàgiu disigiadu",
"Could not load the message" : "No at fatu a carrigare su messàgiu",
- "Error loading message" : "Errore in su carrigamentu de su messàgiu",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Is messàgios s'ant a marcare in manera automàtica comente importantes in sa base de is messàgios cun is chi as tènnidu interatziones o chi si sunt marcados comente importantes. Fortzis a su cumintzu as a dèpere cambiare a manu s'importàntzia pro ddu imparare a su sistema, ma at a megiorare in su tempus."
+ "Error loading message" : "Errore in su carrigamentu de su messàgiu"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/sc.json b/l10n/sc.json
index b092e9731b..b2d928f312 100644
--- a/l10n/sc.json
+++ b/l10n/sc.json
@@ -334,7 +334,6 @@
"Could not load your message" : "No at fatu a carrigare su messàgiu tuo",
"Could not load the desired message" : "No at fatu a carrigare su messàgiu disigiadu",
"Could not load the message" : "No at fatu a carrigare su messàgiu",
- "Error loading message" : "Errore in su carrigamentu de su messàgiu",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Is messàgios s'ant a marcare in manera automàtica comente importantes in sa base de is messàgios cun is chi as tènnidu interatziones o chi si sunt marcados comente importantes. Fortzis a su cumintzu as a dèpere cambiare a manu s'importàntzia pro ddu imparare a su sistema, ma at a megiorare in su tempus."
+ "Error loading message" : "Errore in su carrigamentu de su messàgiu"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/sk.js b/l10n/sk.js
index 66af8aea2b..92f84fcf61 100644
--- a/l10n/sk.js
+++ b/l10n/sk.js
@@ -889,8 +889,6 @@ OC.L10N.register(
"Could not load your message" : "Nepodarilo sa načítať vašu správu",
"Could not load the desired message" : "Nepodarilo sa načítať požadovanú správu",
"Could not load the message" : "Správu sa nepodarilo sa načítať",
- "Error loading message" : "Chyba načítavania správy",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Správy sa automaticky označia ako dôležité v závislosti na tom, ktorými správami ste sa zaoberali alebo označili ako dôležité. Na začiatku bude potrebné meniť dôležitosť ručne a systém tak postupne učiť, ale časom sa to zlepší.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Tu sa zobrazia vami odoslané správy, ktoré vyžadujú odpoveď, no po niekoľkých dňoch ju nedostali."
+ "Error loading message" : "Chyba načítavania správy"
},
"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/l10n/sk.json b/l10n/sk.json
index c6e1353c46..35f0bbd0f6 100644
--- a/l10n/sk.json
+++ b/l10n/sk.json
@@ -887,8 +887,6 @@
"Could not load your message" : "Nepodarilo sa načítať vašu správu",
"Could not load the desired message" : "Nepodarilo sa načítať požadovanú správu",
"Could not load the message" : "Správu sa nepodarilo sa načítať",
- "Error loading message" : "Chyba načítavania správy",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Správy sa automaticky označia ako dôležité v závislosti na tom, ktorými správami ste sa zaoberali alebo označili ako dôležité. Na začiatku bude potrebné meniť dôležitosť ručne a systém tak postupne učiť, ale časom sa to zlepší.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Tu sa zobrazia vami odoslané správy, ktoré vyžadujú odpoveď, no po niekoľkých dňoch ju nedostali."
+ "Error loading message" : "Chyba načítavania správy"
},"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/l10n/sl.js b/l10n/sl.js
index edd1e7099c..d6027f0186 100644
--- a/l10n/sl.js
+++ b/l10n/sl.js
@@ -520,7 +520,6 @@ OC.L10N.register(
"Could not load your message" : "Sporočila ni mogoče naložiti",
"Could not load the desired message" : "Želenega sporočila ni mogoče naložiti",
"Could not load the message" : "Sporočila ni mogoče naložiti",
- "Error loading message" : "Napaka nalaganja sporočila",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Sporočila bodo samodejno označena kot pomembna na podlagi do sedaj označenih takih sporočil. V začetku bo verjetno treba kakšno označiti še ročno, a se bo sistem s časom izboljševal."
+ "Error loading message" : "Napaka nalaganja sporočila"
},
"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);");
diff --git a/l10n/sl.json b/l10n/sl.json
index 158eebc32c..3ccddfd144 100644
--- a/l10n/sl.json
+++ b/l10n/sl.json
@@ -518,7 +518,6 @@
"Could not load your message" : "Sporočila ni mogoče naložiti",
"Could not load the desired message" : "Želenega sporočila ni mogoče naložiti",
"Could not load the message" : "Sporočila ni mogoče naložiti",
- "Error loading message" : "Napaka nalaganja sporočila",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Sporočila bodo samodejno označena kot pomembna na podlagi do sedaj označenih takih sporočil. V začetku bo verjetno treba kakšno označiti še ročno, a se bo sistem s časom izboljševal."
+ "Error loading message" : "Napaka nalaganja sporočila"
},"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
}
\ No newline at end of file
diff --git a/l10n/sr.js b/l10n/sr.js
index 34c5da4c44..4a286b31e9 100644
--- a/l10n/sr.js
+++ b/l10n/sr.js
@@ -854,8 +854,6 @@ OC.L10N.register(
"Could not load your message" : "Неуспело учитавање поруке",
"Could not load the desired message" : "Неуспело учитавање жељене поруке",
"Could not load the message" : "Неуспело учитавање поруке",
- "Error loading message" : "Грешка при учитавању поруке",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Поруке ће аутоматски бити означаване као важне на основу тога које поруке одговарати или означавате као важне. У почетку ћете можда морати ручно да мењате важност да научите систем, али ће се он поправљати временом.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Овде ће се приказати поруке које сте послали и захтевали да се одговори на њих, али за које нисте примили никакав одговор након неколико дана."
+ "Error loading message" : "Грешка при учитавању поруке"
},
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);");
diff --git a/l10n/sr.json b/l10n/sr.json
index f41e5ed142..df31529886 100644
--- a/l10n/sr.json
+++ b/l10n/sr.json
@@ -852,8 +852,6 @@
"Could not load your message" : "Неуспело учитавање поруке",
"Could not load the desired message" : "Неуспело учитавање жељене поруке",
"Could not load the message" : "Неуспело учитавање поруке",
- "Error loading message" : "Грешка при учитавању поруке",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Поруке ће аутоматски бити означаване као важне на основу тога које поруке одговарати или означавате као важне. У почетку ћете можда морати ручно да мењате важност да научите систем, али ће се он поправљати временом.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Овде ће се приказати поруке које сте послали и захтевали да се одговори на њих, али за које нисте примили никакав одговор након неколико дана."
+ "Error loading message" : "Грешка при учитавању поруке"
},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
}
\ No newline at end of file
diff --git a/l10n/sv.js b/l10n/sv.js
index 6461e0326e..309fc62385 100644
--- a/l10n/sv.js
+++ b/l10n/sv.js
@@ -838,8 +838,6 @@ OC.L10N.register(
"Could not load your message" : "Kunde inte läsa in ditt meddelande",
"Could not load the desired message" : "Kunde inte läsa in önskat meddelande",
"Could not load the message" : "Kunde inte läsa in meddelandet",
- "Error loading message" : "Fel vid inläsning av meddelande",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Meddelanden kommer automatiskt att markeras som viktiga baserat på vilka meddelanden du interagerade med eller har markerat som viktiga. I början kan du behöva ändra vikten manuellt, men det kommer att förbättras med tiden.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Meddelanden som du skickat och som kräver svar men inte fått något efter ett par dagar visas här."
+ "Error loading message" : "Fel vid inläsning av meddelande"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/sv.json b/l10n/sv.json
index 4b4550621d..cbfffc6fb4 100644
--- a/l10n/sv.json
+++ b/l10n/sv.json
@@ -836,8 +836,6 @@
"Could not load your message" : "Kunde inte läsa in ditt meddelande",
"Could not load the desired message" : "Kunde inte läsa in önskat meddelande",
"Could not load the message" : "Kunde inte läsa in meddelandet",
- "Error loading message" : "Fel vid inläsning av meddelande",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Meddelanden kommer automatiskt att markeras som viktiga baserat på vilka meddelanden du interagerade med eller har markerat som viktiga. I början kan du behöva ändra vikten manuellt, men det kommer att förbättras med tiden.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Meddelanden som du skickat och som kräver svar men inte fått något efter ett par dagar visas här."
+ "Error loading message" : "Fel vid inläsning av meddelande"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/tr.js b/l10n/tr.js
index 363ed1b5cf..0ca0ad3b8a 100644
--- a/l10n/tr.js
+++ b/l10n/tr.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "İletiniz yüklenemedi",
"Could not load the desired message" : "İstenilen ileti yüklenemedi",
"Could not load the message" : "İleti yüklenemedi",
- "Error loading message" : "İleti yüklenirken sorun çıktı",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "İletiler, hangileri ile etkileşim kurduğunuza ya da hangilerini önemli olarak işaretlediğinize göre otomatik olarak önemli olarak işaretlenecek.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Gönderdiğiniz ve yanıtlanması gereken ancak birkaç gün geçmesine rağmen yanıt alamayan iletileriniz burada görüntülenir."
+ "Error loading message" : "İleti yüklenirken sorun çıktı"
},
"nplurals=2; plural=(n > 1);");
diff --git a/l10n/tr.json b/l10n/tr.json
index 3eb3e4b2c5..347038da1d 100644
--- a/l10n/tr.json
+++ b/l10n/tr.json
@@ -912,8 +912,6 @@
"Could not load your message" : "İletiniz yüklenemedi",
"Could not load the desired message" : "İstenilen ileti yüklenemedi",
"Could not load the message" : "İleti yüklenemedi",
- "Error loading message" : "İleti yüklenirken sorun çıktı",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "İletiler, hangileri ile etkileşim kurduğunuza ya da hangilerini önemli olarak işaretlediğinize göre otomatik olarak önemli olarak işaretlenecek.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Gönderdiğiniz ve yanıtlanması gereken ancak birkaç gün geçmesine rağmen yanıt alamayan iletileriniz burada görüntülenir."
+ "Error loading message" : "İleti yüklenirken sorun çıktı"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}
\ No newline at end of file
diff --git a/l10n/ug.js b/l10n/ug.js
index 5cf25ce5c3..b6abd2d603 100644
--- a/l10n/ug.js
+++ b/l10n/ug.js
@@ -878,8 +878,6 @@ OC.L10N.register(
"Could not load your message" : "ئۇچۇرىڭىزنى يۈكلىيەلمىدى",
"Could not load the desired message" : "لازىملىق ئۇچۇرنى يۈكلىيەلمىدى",
"Could not load the message" : "ئۇچۇرنى يۈكلىيەلمىدى",
- "Error loading message" : "ئۇچۇر يۈكلەشتە خاتالىق",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "سىز قايسى ئۇچۇرلار بىلەن ئالاقە قىلغان ياكى مۇھىم دەپ بەلگە قويۇلغان ئۇچۇرلار ئاپتوماتىك ھالدا مۇھىم دەپ بەلگە قىلىنىدۇ. باشتا سىز سىستېمىنى ئوقۇتۇشنىڭ مۇھىملىقىنى قولدا ئۆزگەرتىشىڭىز مۇمكىن ، ئەمما ۋاقىتنىڭ ئۆتۈشىگە ئەگىشىپ ياخشىلىنىدۇ.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "سىز ئەۋەتكەن جاۋابنى تەلەپ قىلىدىغان ، ئەمما بىر نەچچە كۈندىن كېيىن تاپشۇرۇۋالمىغان ئۇچۇرلار بۇ يەردە كۆرسىتىلىدۇ."
+ "Error loading message" : "ئۇچۇر يۈكلەشتە خاتالىق"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/ug.json b/l10n/ug.json
index 80b8f04ca2..2fe390284c 100644
--- a/l10n/ug.json
+++ b/l10n/ug.json
@@ -876,8 +876,6 @@
"Could not load your message" : "ئۇچۇرىڭىزنى يۈكلىيەلمىدى",
"Could not load the desired message" : "لازىملىق ئۇچۇرنى يۈكلىيەلمىدى",
"Could not load the message" : "ئۇچۇرنى يۈكلىيەلمىدى",
- "Error loading message" : "ئۇچۇر يۈكلەشتە خاتالىق",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "سىز قايسى ئۇچۇرلار بىلەن ئالاقە قىلغان ياكى مۇھىم دەپ بەلگە قويۇلغان ئۇچۇرلار ئاپتوماتىك ھالدا مۇھىم دەپ بەلگە قىلىنىدۇ. باشتا سىز سىستېمىنى ئوقۇتۇشنىڭ مۇھىملىقىنى قولدا ئۆزگەرتىشىڭىز مۇمكىن ، ئەمما ۋاقىتنىڭ ئۆتۈشىگە ئەگىشىپ ياخشىلىنىدۇ.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "سىز ئەۋەتكەن جاۋابنى تەلەپ قىلىدىغان ، ئەمما بىر نەچچە كۈندىن كېيىن تاپشۇرۇۋالمىغان ئۇچۇرلار بۇ يەردە كۆرسىتىلىدۇ."
+ "Error loading message" : "ئۇچۇر يۈكلەشتە خاتالىق"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
\ No newline at end of file
diff --git a/l10n/uk.js b/l10n/uk.js
index 7c804df7d2..7ac32a443c 100644
--- a/l10n/uk.js
+++ b/l10n/uk.js
@@ -831,8 +831,6 @@ OC.L10N.register(
"Could not load your message" : "Неможливо завантажити повідомлення",
"Could not load the desired message" : "Неможливо завантажити обране повідомлення",
"Could not load the message" : "Неможливо завантажити повідомлення",
- "Error loading message" : "Помилка завантаження повідомлення.",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Повідомлення автоматично будуть позначатися як важливі на основі повідомлень, з якими ви взаємодієте або позначаєте як важливі. Спочатку вам потрібно буде вручну змінювати важливість, щоб навчити систему, але з часом автоматичне визначення важливих повідомлень покращиться.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Тут будуть показані надіслані вами повідомлення, які потребують відповіді, але не були отримані протягом декількох днів."
+ "Error loading message" : "Помилка завантаження повідомлення."
},
"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/l10n/uk.json b/l10n/uk.json
index 4c454dc939..29cf5bcc8b 100644
--- a/l10n/uk.json
+++ b/l10n/uk.json
@@ -829,8 +829,6 @@
"Could not load your message" : "Неможливо завантажити повідомлення",
"Could not load the desired message" : "Неможливо завантажити обране повідомлення",
"Could not load the message" : "Неможливо завантажити повідомлення",
- "Error loading message" : "Помилка завантаження повідомлення.",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Повідомлення автоматично будуть позначатися як важливі на основі повідомлень, з якими ви взаємодієте або позначаєте як важливі. Спочатку вам потрібно буде вручну змінювати важливість, щоб навчити систему, але з часом автоматичне визначення важливих повідомлень покращиться.",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "Тут будуть показані надіслані вами повідомлення, які потребують відповіді, але не були отримані протягом декількох днів."
+ "Error loading message" : "Помилка завантаження повідомлення."
},"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/l10n/vi.js b/l10n/vi.js
index 4855155bbd..404c3f6c96 100644
--- a/l10n/vi.js
+++ b/l10n/vi.js
@@ -271,7 +271,6 @@ OC.L10N.register(
"Could not load your message" : "Không thể tải tin nhắn của bạn",
"Could not load the desired message" : "Không thể tải tin nhắn mong muốn",
"Could not load the message" : "Không thể tải tin nhắn",
- "Error loading message" : "Lỗi khi tải tin nhắn",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Tin nhắn sẽ tự động được đánh dấu là quan trọng dựa trên những tin nhắn bạn đã tương tác hoặc được đánh dấu là quan trọng. Lúc đầu, bạn có thể phải thay đổi thủ công tầm quan trọng để dạy hệ thống, nhưng nó sẽ cải thiện theo thời gian."
+ "Error loading message" : "Lỗi khi tải tin nhắn"
},
"nplurals=1; plural=0;");
diff --git a/l10n/vi.json b/l10n/vi.json
index 0a1ce06310..9d185bf3fe 100644
--- a/l10n/vi.json
+++ b/l10n/vi.json
@@ -269,7 +269,6 @@
"Could not load your message" : "Không thể tải tin nhắn của bạn",
"Could not load the desired message" : "Không thể tải tin nhắn mong muốn",
"Could not load the message" : "Không thể tải tin nhắn",
- "Error loading message" : "Lỗi khi tải tin nhắn",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "Tin nhắn sẽ tự động được đánh dấu là quan trọng dựa trên những tin nhắn bạn đã tương tác hoặc được đánh dấu là quan trọng. Lúc đầu, bạn có thể phải thay đổi thủ công tầm quan trọng để dạy hệ thống, nhưng nó sẽ cải thiện theo thời gian."
+ "Error loading message" : "Lỗi khi tải tin nhắn"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js
index 6e5d8b8a1d..18fdca5c52 100644
--- a/l10n/zh_CN.js
+++ b/l10n/zh_CN.js
@@ -910,8 +910,6 @@ OC.L10N.register(
"Could not load your message" : "无法加载您的邮件",
"Could not load the desired message" : "无法加载所需邮件",
"Could not load the message" : "无法加载邮件",
- "Error loading message" : "加载邮件时出错",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "将根据您与哪些邮件互动或手动标记为重要,自动标记邮件为重要邮件。开始时,您可能需要手动更改重要性来调教系统,但随着时间的推移,它会不断改进。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "您发送的需要回复但几天后未收到回复的邮件将显示在此处。"
+ "Error loading message" : "加载邮件时出错"
},
"nplurals=1; plural=0;");
diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json
index 383a63b453..00994cb07f 100644
--- a/l10n/zh_CN.json
+++ b/l10n/zh_CN.json
@@ -908,8 +908,6 @@
"Could not load your message" : "无法加载您的邮件",
"Could not load the desired message" : "无法加载所需邮件",
"Could not load the message" : "无法加载邮件",
- "Error loading message" : "加载邮件时出错",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "将根据您与哪些邮件互动或手动标记为重要,自动标记邮件为重要邮件。开始时,您可能需要手动更改重要性来调教系统,但随着时间的推移,它会不断改进。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "您发送的需要回复但几天后未收到回复的邮件将显示在此处。"
+ "Error loading message" : "加载邮件时出错"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js
index 837fe3d5ab..aeb90af073 100644
--- a/l10n/zh_HK.js
+++ b/l10n/zh_HK.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "無法載入您的信件",
"Could not load the desired message" : "無法載入所選的信件",
"Could not load the message" : "無法載入信件",
- "Error loading message" : "載入信件錯誤",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "郵件將會以您與其互動或標記為重要的郵件為基礎來自動標記重要郵件。ㄧ開始,您可以能必須手動教導系統哪些是重要郵件,然後它就會與時俱進。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "您發送的訊息如果在幾天內未收到回覆,將在此處顯示。"
+ "Error loading message" : "載入信件錯誤"
},
"nplurals=1; plural=0;");
diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json
index 5f560289f6..b9a2260237 100644
--- a/l10n/zh_HK.json
+++ b/l10n/zh_HK.json
@@ -912,8 +912,6 @@
"Could not load your message" : "無法載入您的信件",
"Could not load the desired message" : "無法載入所選的信件",
"Could not load the message" : "無法載入信件",
- "Error loading message" : "載入信件錯誤",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "郵件將會以您與其互動或標記為重要的郵件為基礎來自動標記重要郵件。ㄧ開始,您可以能必須手動教導系統哪些是重要郵件,然後它就會與時俱進。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "您發送的訊息如果在幾天內未收到回覆,將在此處顯示。"
+ "Error loading message" : "載入信件錯誤"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js
index 3e00291922..757f4bbe31 100644
--- a/l10n/zh_TW.js
+++ b/l10n/zh_TW.js
@@ -914,8 +914,6 @@ OC.L10N.register(
"Could not load your message" : "無法載入您的信件",
"Could not load the desired message" : "無法載入所選的信件",
"Could not load the message" : "無法載入信件",
- "Error loading message" : "載入信件錯誤",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "郵件將會以您與其互動或標記為重要的郵件為基礎來自動標記重要郵件。ㄧ開始,您可以能必須手動教導系統哪些是重要郵件,然後它就會與時俱進。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "您傳送的訊息若未在幾天內收到回覆,將在此處顯示。"
+ "Error loading message" : "載入信件錯誤"
},
"nplurals=1; plural=0;");
diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json
index 4af740be0a..3ec1375e6e 100644
--- a/l10n/zh_TW.json
+++ b/l10n/zh_TW.json
@@ -912,8 +912,6 @@
"Could not load your message" : "無法載入您的信件",
"Could not load the desired message" : "無法載入所選的信件",
"Could not load the message" : "無法載入信件",
- "Error loading message" : "載入信件錯誤",
- "Messages will automatically be marked as important based on which messages you interacted with or marked as important. In the beginning you might have to manually change the importance to teach the system, but it will improve over time." : "郵件將會以您與其互動或標記為重要的郵件為基礎來自動標記重要郵件。ㄧ開始,您可以能必須手動教導系統哪些是重要郵件,然後它就會與時俱進。",
- "Messages sent by you that require a reply but did not receive one after a couple of days will be shown here." : "您傳送的訊息若未在幾天內收到回覆,將在此處顯示。"
+ "Error loading message" : "載入信件錯誤"
},"pluralForm" :"nplurals=1; plural=0;"
}
\ No newline at end of file
From 7551ba5e8af95a1019b34386eaac814b1a48774f Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Fri, 29 May 2026 02:03:17 +0000
Subject: [PATCH 062/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/et_EE.js | 79 ++++++++++++++++++++++++++++++++++++++++++++-----
l10n/et_EE.json | 79 ++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 144 insertions(+), 14 deletions(-)
diff --git a/l10n/et_EE.js b/l10n/et_EE.js
index eef713fa4e..d95d32d65d 100644
--- a/l10n/et_EE.js
+++ b/l10n/et_EE.js
@@ -14,6 +14,10 @@ OC.L10N.register(
"Mail" : "Kirjad",
"You are reaching your mailbox quota limit for {account_email}" : "„{account_email}“ konto mahukvoot on varsti täis",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Kasutad praegu {percentage} oma postkasti andmeruumist. Palun kustuta mittevajalikud kirjad ning saada andmeruumi juurde.",
+ "{account_email} has been delegated to you" : "sul on nüüd {account_email} e-postikonto volitus",
+ "{user} delegated {account} to you" : "{user} volitas sin kasutama {account} e-posti kontot",
+ "{account_email} is no longer delegated to you" : "sul enam pole {account_email} e-posti konto volitust",
+ "{user} revoked delegation for {account}" : "{user} tühistas volituse {account} kasutajakonto jaoks",
"Mail Application" : "E-posti rakendus",
"Mails" : "E-kirjad",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Saatja aadress %1$s pole aadressiraamatus, aga %2$s nimi on ning temaga on seotud järgnev aadress: %3$s",
@@ -24,8 +28,13 @@ OC.L10N.register(
"Some addresses in this message are not matching the link text" : "Mõned selle kirja aadressid ei vasta lingi tekstile",
"Reply-To email: %1$s is different from sender email: %2$s" : "Vastamiseks mõeldud e-posti aadress: %1$s on erinev saatja aadressist %2$s",
"Mail connection performance" : "E-postiteenuse ühenduse jõudlus",
+ "Slow mail service detected (%1$s) an attempt to connect to several accounts took an average of %2$s seconds per account" : "Aeglase e-posti tuvastusteenus (%1$s) - mitme e-posti kontoga ühendamine võttis aega keskmiselt %2$s sekundit kasutajakontkonto kohta",
+ "Slow mail service detected (%1$s) an attempt to perform a mail box list operation on several accounts took an average of %2$s seconds per account" : "Aeglase e-posti tuvastusteenus (%1$s) - postkastide loendi laadimine mitme konto jaoks võttis aega keskmiselt %2$s sekundit kasutajakontkonto kohta",
+ "Mail Transport configuration" : "E-kirjade edastamise viis serverite vahel",
+ "The app.mail.transport setting is not set to smtp. This configuration can cause issues with modern email security measures such as SPF and DKIM because emails are sent directly from the web server, which is often not properly configured for this purpose. To address this, we have discontinued support for the mail transport. Please remove app.mail.transport from your configuration to use the SMTP transport and hide this message. A properly configured SMTP setup is required to ensure email delivery." : "„app.mail.transport“ seadistuse väärtus pole „smtp“. Selline seadistus võib põhjustada probleeme kaasaegsete e-posti turvameetmetega, nagu SPF ja DKIM, kuna e-kirjad saadetakse otse veebiserverist, mis ei ole selleks otstarbeks sageli nõuetekohaselt konfigureeritud. Selle probleemi lahendamiseks oleme lõpetanud „mail-transport“ meetodi toetamise. Palun eemalda serveri seadistustest „app.mail.transport“, et kasutada SMTP-põhist edastust ja peida see teade. E-kirjade kättetoimetamise tagamiseks on vaja nõuetekohaselt konfigureeritud SMTP-seadistust.",
"Mail account parameters, aliases and preferences" : "E-posti kasutajakonto parameetrid, aliased ja eelistused",
"💌 A mail app for Nextcloud" : "💌 E-postirakendus Nextcloudi jaoks",
+ "**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 E-posti rakendus Nextcloudi jaoks**\n\n- **🚀 Lõiming muude Nextcloudi rakendustega!** Hetkel kontakti-, kalendri ja failirakendused, aga õige pea lisandub neid veel.\n- **📥 Mitu e-posti kontot!** Isiklik ja töökoha konto? Pole probleemi ja kauba peale saad kena ja ühise sisendposti kausta. Võid ühendada kõiki IMAP-i kasutajakontosid.\n- **🔒 Saada krüptitud e-kirju ja võta neid vastu!** Selleks on kasutusel suurepärase veebibrauseri lisamoodul [Mailvelope](https://mailvelope.com).\n- **🙈 Me ei leiuta midagi uut!** Rakendus põhineb suurepärastel [Horde](https://www.horde.org) teekidel.\n- **📬 Tahad kasutada oma serverit?** Me ei hakanud seda ise leiutama, on ju olemas [Mail-in-a-Box](https://mailinabox.email) teenus!\n\n## Tehisaru eetiline kasutaus\n\n### Prioriteediga kirjad saabuvate kirjade postkastis\n\nPositiivne lähenemine:\n* Selle mudeli treenimiseks ja järelduste tegemiseks mõeldud tarkvara on avatud lähtekoodiga.\n* Mudel luuakse ja treenitakse kohapeal, tuginedes kasutaja enda andmetele.\n* Kasutajal on juurdepääs treeningandmetele, mis võimaldab kontrollida ja parandada võimalikke eelarvamusi ning optimeerida mudeli jõudlust ja CO2-heiteid.\n\n### Jutulõngade kokkuvõtted (kui tahad kasutada)\n\n**Hinnang:** 🟢/🟡/🟠/🔴\n\nHindamine sõltub paigaldatud tekstitöötluse taustateenusest. Üksikasju vaata dokumentatsioonist, mis kirjeldab [ülevaadet hindamisest](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html).\n\nTehisaru eetilisest kasutusest Nextcloudi raames leiad [teavet meie ajaveebist](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).",
"Your session has expired. The page will be reloaded." : "Sinu sessioon on aegunud. Leht saab olema uuesti laaditud.",
"Drafts are saved in:" : "Kirjade kavandis on salvestatud siia:",
"Sent messages are saved in:" : "Saadetud kirjad on salvestatud siia:",
@@ -88,6 +97,8 @@ OC.L10N.register(
"SMTP Port" : "SMTP port",
"SMTP User" : "SMTP kasutajanimi",
"SMTP Password" : "SMTP salasõna",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google eeldab OAuthi autentimise kasutamist. Kui sinu Nextcloudi serveri haldaja või peakasutaja pole seda teinud, siis saad selle asemel kasutada Google'i rakenduse salasõna (Google App Password).",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft eeldab OAuthi autentimise kasutamist. Palu oma Nextcloudi serveri haldajat või peakasutajat, et ta seadistaks Microsofti OAuthi.",
"Account settings" : "Konto seadistused",
"Aliases" : "Aliased",
"Alias to S/MIME certificate mapping" : "Alias S/MIME sertifikaatide vastavuse jaoks",
@@ -124,12 +135,13 @@ OC.L10N.register(
"Search the body of messages in priority Inbox" : "Otsi esmase postkasti kirjade sisust",
"Activate" : "Lülita sisse",
"Make mails available to Context Chat" : "Muuda e-kirjad loetavaks kontekstuaalses vestluses",
- "Remind about messages that require a reply but received none" : "Tuleta mulle meelde kirju, mis eeldavad vastust, kui pole seda veel saanud",
+ "Remind about messages that require a reply but received none" : "Tuleta mulle meelde kirju, mis eeldavad vastust, kuid pole seda veel saanud",
"Highlight external addresses" : "Tõsta välised aadressid esile",
"Could not update preference" : "Eelistust polnud võimalik muuta",
"Mail settings" : "E-kirjade seadistused",
"General" : "Üldine",
"Set as default mail app" : "Määra vaikimisi e-postirakenduseks",
+ "{email} (delegated)" : "{email} (volitatud)",
"Add mail account" : "Lisa e-posti konto",
"Appearance" : "Välimus",
"Show all messages in thread" : "Näita kõiki kirju jutulõngas",
@@ -139,7 +151,7 @@ OC.L10N.register(
"Layout" : "Välimus",
"Vertical split" : "Püstjoones jagamine",
"Horizontal split" : "Rõhtjoones jagamine",
- "List" : "Nimekiri",
+ "List" : "Loend",
"Use compact mode" : "Kasuta kompaktset vaadet",
"Sorting" : "Järjestus",
"Newest first" : "Uuemad eespool",
@@ -248,7 +260,21 @@ OC.L10N.register(
"Expand composer" : "Näita koostamisvaadet laiemana",
"Close composer" : "Sulge koostamisvaade",
"Confirm" : "Kinnita",
+ "Delegate access" : "Volita ligipääs",
"Revoke" : "Tühista",
+ "{userId} will no longer be able to act on your behalf" : "Kasutaja {userId} ei saa enam sinu nimel tegutseda",
+ "Could not fetch delegates" : "Volitatute laadimine ei õnnestunud",
+ "Delegated access to {userId}" : "Sa volitasid ligipääsu kasutajale {userId}",
+ "Could not delegate access" : "Ligipääsu volitamine ei õnnestunud",
+ "Revoked access for {userId}" : "Kasutaja {userId} volitus on eemaldatud",
+ "Could not revoke delegation" : "Volituse tühistamine ei õnnestunud",
+ "Delegation" : "Volitamine",
+ "Allow users to send, receive, and delete mail on your behalf" : "Luba volitatutel saata, vastu võtta ja kustutada e-kirju sinu nimel",
+ "Revoke access" : "Eemalda ligipääs",
+ "Add delegate" : "Lisa volitatav",
+ "Select a user" : "Vali kasutaja",
+ "They will be able to send, receive, and delete mail on your behalf" : "Volitatu võib saata, vastu võtta ja kustutada e-kirju sinu nimel",
+ "Revoke access?" : "Kas tühistad ligipääsu?",
"Tag: {name} deleted" : "Silt: {name} on kustutatud",
"An error occurred, unable to delete the tag." : "Tekkis viga, silti ei õnnestu kustutada",
"The tag will be deleted from all messages." : "See silt saab olema eemaldatud kõikide kirjade juurest.",
@@ -274,7 +300,7 @@ OC.L10N.register(
"No trash folder configured" : "Prügikasti kaust on määramata",
"Could not delete message" : "Kirja kustutamine ei õnnestunud",
"Could not archive message" : "Kirja arhiveerimine ei õnnestunud",
- "Thread was snoozed" : "Jutulõnga kuvamine on edasi lükatd",
+ "Thread was snoozed" : "Jutulõnga kuvamine on edasi lükatud",
"Could not snooze thread" : "Ei õnnestunud edasi lükata jutulõnga kuvamist",
"Thread was unsnoozed" : "Jutulõnga edasilükkamine on lõpetatud",
"Could not unsnooze thread" : "Jutulõnga edasilükkamise lõpetamine ei õnnestunud",
@@ -382,11 +408,14 @@ OC.L10N.register(
"Favorites" : "Lemmikud",
"Favorites info" : "Lemmikute teave",
"Load more favorites" : "Laadi veel lemmikuid",
+ "Follow up" : "Jätkukiri",
+ "Follow up info" : "Jätkukirja teave",
"Load more follow ups" : "Laadi veel jätkukirju",
"Important info" : "Oluline teave",
"Load more important messages" : "Laadi veel olulisi kirju",
"Other" : "Muu",
"Load more other messages" : "Laadi veel muid kirju",
+ "Could not send mdn" : "Olekuteate (Message Disposition Notification - MDN) edastamine ei õnnestunud",
"The sender of this message has asked to be notified when you read this message." : "Selle kirja saatja on palunud kinnitust, kui oled kirja lugenud.",
"Notify the sender" : "Teavita saatjat",
"You sent a read confirmation to the sender of this message." : "Sa saatsid selle kirja saatjale lugemisteatise.",
@@ -409,14 +438,14 @@ OC.L10N.register(
"Unnamed" : "Nimeta",
"Embedded message" : "Lõimitud kiri",
"Attachment saved to Files" : "Manus on salvestatud failirakendusse",
- "Attachment could not be saved" : "Manus polnud võimalik salvestada",
+ "Attachment could not be saved" : "Manust polnud võimalik salvestada",
"calendar imported" : "kalender on imporditud",
"Choose a folder to store the attachment in" : "Vali kaust, kuhu manus salvestada",
"Import into calendar" : "Impordi kalendrisse",
"Download attachment" : "Laadi manus alla",
"Save to Files" : "Salvesta failirakendusse",
"Attachments saved to Files" : "Manused on salvestatud failirakendusse",
- "Error while saving attachments" : "Viga manuse salvestamisel",
+ "Error while saving attachments" : "Viga manuste salvestamisel",
"View fewer attachments" : "Näita vähem manuseid",
"Choose a folder to store the attachments in" : "Vali kaust, kuhu soovid manuse salvestada",
"Save all to Files" : "Salvesta kõik failirakendusse",
@@ -442,7 +471,10 @@ OC.L10N.register(
"Remove account" : "Eemalda konto",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "E-posti konto {email} ja tema puhverdatud andmed eemaldatakse siit Nextcloudi serverist, kuid mitte sinu e-postiteenuse pakkuja juurest.",
"Remove {email}" : "Eemalda fail: „{email}“",
+ "could not delete account" : "kasutajakonto kustutamine ei õnnestunud",
+ "Provisioned account is disabled" : "Ettevalmistatud konto on eemaldatud kasutuselt",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Selle konto kasutamiseks palun logi sisse salasõnaga. Praegune sessioon kasutab salasõnata tuvastamist, milleks võib olla SSO, WebAuthn, vms.",
+ "Delegate account" : "Volita konto kasutamine",
"Show only subscribed folders" : "Näita vaid tellitud kaustu",
"Add folder" : "Lisa kaust",
"Folder name" : "Kausta nimi",
@@ -539,7 +571,7 @@ OC.L10N.register(
"Open search modal" : "Ava modaalne otsinguvaade",
"Close" : "Sulge",
"Search parameters" : "Otsinguparameetrid",
- "Search subject" : "Otsi teemat",
+ "Search subject" : "Otsi teemat/pealkirja",
"Body" : "Sisu",
"Search body" : "Otsi sisust",
"Date" : "Kuupäev",
@@ -616,6 +648,8 @@ OC.L10N.register(
"Mark as unfavorite" : "Märgi mittelemmikuks",
"Mark as favorite" : "Märgi lemmikuks",
"To:" : "Saaja:",
+ "Cc:" : "Koopia:",
+ "Bcc:" : "Pimekoopia:",
"Unsubscribe via link" : "Loobu tellimusest lingi kaudu",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Tellimusest loobudes sa enam ei saa kirju postiloendist {sender}",
"Send unsubscribe email" : "Saada loobumiskiri",
@@ -683,6 +717,7 @@ OC.L10N.register(
"contains" : "sisaldab",
"A substring match. The field matches if the provided value is contained within it. For example, \"report\" would match \"port\"." : "Stringi osaline vaste. Välja väärtus vastab, kui antud väärtus on selles sisalduv. Näiteks vastab „report“ sõnale „port“.",
"matches" : "kattub",
+ "A pattern match using wildcards. The \"*\" symbol represents any number of characters (including none), while \"?\" represents exactly one character. For example, \"*report*\" would match \"Business report 2024\"." : "Muster, milles kasutatakse metamärke. Sümbol „*“ tähistab mis tahes arvu märke (sh mitte ühtegi), samas kui „?“ tähistab täpselt ühte märki. Näiteks sobib „*report*“ kokku fraasiga „Business report 2024“.",
"Enter subject" : "Sisesta teema",
"Enter sender" : "Sisesta saatja",
"Enter recipient" : "Sisesta saaja",
@@ -714,17 +749,38 @@ OC.L10N.register(
"Successfully updated config for \"{domain}\"" : "„{domain}“ domeeni seadistuste uuendamine õnnestus",
"Error saving config" : "Viga seadistuste salvestamisel",
"Saved config for \"{domain}\"" : "„{domain}“ domeeni seadistused on salvestatud",
- "_Successfully provisioned {count} account._::_Successfully provisioned {count} accounts._" : ["{count} kasutajakonto ettevalmistamine õnnestus","{count} kasutajakonto ettevalmistamine õnnestus"],
+ "Could not save provisioning setting" : "Kasutajakonto eelseadistuse salvestamine ei õnnestunud",
+ "_Successfully provisioned {count} account._::_Successfully provisioned {count} accounts._" : ["{count} kasutajakonto eelseadistamine ja ettevalmistamine õnnestus","{count} kasutajakonto eelseadistamine ja ettevalmistamine õnnestus"],
+ "There was an error when provisioning accounts." : "Kasutajakontode eelseadistamisel ja ettevalmistamisel tekkis viga.",
+ "Successfully deleted and deprovisioned accounts for \"{domain}\"" : "„{domain}“ domeeni jaoks ettevalmistatud kontode kustutamine õnnestus",
+ "Error when deleting and deprovisioning accounts for \"{domain}\"" : "„{domain}“ domeeni jaoks ettevalmistatud kontode kustutamisel tekkis viga",
+ "Could not save default classification setting" : "Vaikimisi klassifitseerimise seadistuse salvestamine ei õnnestunud",
"Mail app" : "E-posti rakendus",
"The mail app allows users to read mails on their IMAP accounts." : "Selle rakendusega saavad kasutajad lugeda oma IMAP-i kontode kirju.",
"Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Siin on serverikohased seadistused. Kasutajakohased seadistused leiduvad rakenduses (vaata alumist vasakut nurka).",
+ "Account provisioning" : "Kasutajakontode ettevalmistus",
+ "A provisioning configuration will provision all accounts with a matching email address." : "Ettevalmistuse seadistuse alusel valmistatakse ette kõik e-posti aadressid, mis tingimustele vastavad",
+ "Using the wildcard (*) in the provisioning domain field will create a configuration that applies to all users, provided they do not match another configuration." : "Kui kasutad metamärgiga (*) määratletud eelseadistamist, siis see seadistus kehtib kõigile, välja arvatud neile, kelle puhul kehib täpselt määratletud domeeni seadistus.",
+ "The provisioning mechanism will prioritise specific domain configurations over the wildcard domain configuration." : "Ettevalmistamise (eelseadistamise) mehhanism käsitleb konkreetse domeeni seadistuse kõrgema prioriteediga, kui metamärgiga domeeni seadistusi.",
+ "Should a new matching configuration be found after the user was already provisioned with another configuration, the new configuration will take precedence and the user will be reprovisioned with the configuration." : "Kui leitakse uus sobiv seadistus pärast seda, kui kasutajale on juba eelseadistus tehtud, siis on uuel seadistusel eelisõigus ja kasutajale tehakse uus eelseadistus selle alusel uuesti.",
+ "There can only be one configuration per domain and only one wildcard domain configuration." : "Võid koostada vaid ühe domeenikohase seadistuse ja ühe metamärk+domeen seadistuse.",
+ "These settings can be used in conjunction with each other." : "Neid seadistusi saad omavahel kombineerida.",
+ "If you only want to provision one domain for all users, use the wildcard (*)." : "Kui kavatsed kõikide kasutajate jaoks eelseadistada vaid ühte domeeni, siis kasuta metamärki (*).",
+ "This setting only makes most sense if you use the same user back-end for your Nextcloud and mail server of your organization." : "See seadistus on mõttekas vaid juhul, kui kasutad oma Nextcloudi ja organisatsiooni e-postiserveri jaoks sama kasutajate haldussüsteemi.",
+ "Provisioning Configurations" : "Ettevalmistamise seadistused",
"Add new config" : "Lisa uus konfiguratsioon",
+ "Provision all accounts" : "Valmista ette kõik kasutajakontod",
"Allow additional mail accounts" : "Lisa veel e-postikontosid",
"Allow additional Mail accounts from User Settings" : "Luba kasutaja seadistustest täiendavate e-posti kontode kasutamine",
"Enable text processing through LLMs" : "Kasuta teksti töötlemist suure keelemudeliga",
"The Mail app can process user data with the help of the configured large language model and provide assistance features like thread summaries, smart replies and event agendas." : "E-postirakendus oskab töödelda kasutajaandmeid seadistatud keelemudeli abil ning selle teha abitoiminguid, nagu jutulõngade ülevaadete, nutikate vastuste ja ürituste päevakavade koostamine.",
"Enable LLM processing" : "Lülita suure keelemudeliga töötlemine sisse",
+ "Enable classification by importance by default" : "Vaikimisi luba e-kirjade klassifitseerimine olulisuse alusel",
+ "The Mail app can classify incoming emails by importance using machine learning. This feature is enabled by default but can be disabled by default here. Individual users will still be able to toggle the feature for their accounts." : "Kasutades masinõpet oskab e-postirakendus kirju klassifitseerida olulisuse alusel. Vaikimisi on see võimalus kasutusel, kuid saad määrata, et ta vaikimisi on lülitatud välja. Sel puhul saavad kasutajad niisuguse võimaluse oma konto jaoks sisse lülitada.",
+ "Enable classification of important mails by default" : "Vaikimisi luba oluliste e-kirjade klassifitseerimine",
"Anti Spam Service" : "Spämmitõrjeteenus",
+ "You can set up an anti spam service email address here." : "Siin võid seadistada spämmitõrjeteenuse e-posti aadressi.",
+ "Any email that is marked as spam will be sent to the anti spam service." : "Spämmiks ehk rämpspostiks märgitud e-kiri saadetakse sellele teenusele.",
"Gmail integration" : "Lõiming Gmailiga",
"Gmail allows users to access their email via IMAP. For security reasons this access is only possible with an OAuth 2.0 connection or Google accounts that use two-factor authentication and app passwords." : "Gmail lubab kasutajatel lugeda kirju IMAP-i abil. Turvakaalutlustel toimib see vaid OAuth 2.0 liidestusega või kui Google'i konto kasutab kaheastmelist autentimist ja rakenduse salasõna.",
"You have to register a new Client ID for a \"Web application\" in the Google Cloud console. Add the URL {url} as authorized redirect URI." : "Sa pead Google Cloudi juhtpaneelis registreerima veebirakenduse (Web application) jaoks uue klienditunnuse (Client ID). Korrektse suunamisaadressina kasuta: {url}",
@@ -736,6 +792,13 @@ OC.L10N.register(
"These settings are used to pre-configure the user interface preferences they can be overridden by the user in the mail settings" : "Need on kasutajaliidese eelseadistused, mida iga kasutaja saab oma seadistustest muuta",
"Message View Mode" : "Kirjade vaate liik",
"Show only the selected message" : "Näita vaid valitud kirja",
+ "Successfully set up anti spam email addresses" : "Spämmitõrjeteenuse e-posti aadressi seadistamine õnnestus.",
+ "Error saving anti spam email addresses" : "Spämmitõrjeteenuse e-posti aadressi salvestamine ei õnnestunud.",
+ "Successfully deleted anti spam reporting email" : "Spämmitõrjeteenuse e-posti aadressi kustutamine õnnestus.",
+ "Error deleting anti spam reporting email" : "Spämmitõrjeteenuse e-posti aadressi kustutamine ei õnnestunud.",
+ "Anti Spam" : "Spämmi ehk rämsposti tõrjumine",
+ "Add the email address of your anti spam report service here." : "Lisa oma kasutatava spämmitõrjeteenuse e-posti aadress siia.",
+ "When using this setting, a report email will be sent to the SPAM report server when a user clicks \"Mark as spam\"." : "Selle seadistuse kasutamisel saadetakse teavituskiri spämmitõrjeteenusele niipea, kui kasutaja klõpsab valikut „Märgi rämpspostiks“.",
"The original message will be attached as a \"message/rfc822\" attachment." : "Algne kiri lisatakse manusena „message/rfc822“ tüüpi failina.",
"\"Mark as Spam\" Email Address" : "„Märgitud rämpspostiks“ e-posti aadressid",
"\"Mark Not Junk\" Email Address" : "„Pole rämpspost“ e-posti aadressid",
@@ -758,6 +821,7 @@ OC.L10N.register(
"SMTP: {user} on {host}:{port} ({ssl} encryption)" : "SMTP: {user} serveris {host}:{port} ({ssl} krüptimisega)",
"Sieve: {user} on {host}:{port} ({ssl} encryption)" : "Sieve: {user} serveris {host}:{port} ({ssl} krüptimisega)",
"Configuration for \"{provisioningDomain}\"" : "Seadistus „{provisioningDomain}“ domeeni jaoks",
+ "Provisioning domain" : "Domeeni ettevalmistamine",
"Email address template" : "E-posti aadressi mall",
"IMAP" : "IMAP",
"User" : "Kasutaja",
@@ -774,6 +838,7 @@ OC.L10N.register(
"LDAP attribute for aliases" : "LDAP-i omadused aliaste jaoks",
"A multi value attribute to provision email aliases. For each value an alias is created. Aliases existing in Nextcloud which are not in the LDAP directory are deleted." : "Mitmeväärtuseline e-posti aliaste eelkoostamise lahendus. Iga väärtuse kohta luuakse alias. Nexctcloudis leiduvate aliaste puhul, millel pole LDAP-i serveris vastet, kustutakse e-posti teenusest.",
"Save Config" : "Salvesta seadistus",
+ "Unprovision & Delete Config" : "Eemalda ettevalmistatud seadistused ja kustuta nad",
"* %USERID% and %EMAIL% will be replaced with the user's UID and email" : "* %USERID% ja %EMAIL% asendatakse kasutajatunnuse (UID) ja e-posti aadressiga",
"With the settings above, the app will create account settings in the following way:" : "Ülalmääratud seadistuste alusel loob rakendus kasutajakonto seadistused alljärgneval viisil:",
"The provided PKCS #12 certificate must contain at least one certificate and exactly one private key." : "Lisatud PKCS #12 sertifikaadis peab olema vähemalt üks sertifikaat ning ainult üks privaatvõti.",
diff --git a/l10n/et_EE.json b/l10n/et_EE.json
index cdb2b72db8..303ceedd54 100644
--- a/l10n/et_EE.json
+++ b/l10n/et_EE.json
@@ -12,6 +12,10 @@
"Mail" : "Kirjad",
"You are reaching your mailbox quota limit for {account_email}" : "„{account_email}“ konto mahukvoot on varsti täis",
"You are currently using {percentage} of your mailbox storage. Please make some space by deleting unneeded emails." : "Kasutad praegu {percentage} oma postkasti andmeruumist. Palun kustuta mittevajalikud kirjad ning saada andmeruumi juurde.",
+ "{account_email} has been delegated to you" : "sul on nüüd {account_email} e-postikonto volitus",
+ "{user} delegated {account} to you" : "{user} volitas sin kasutama {account} e-posti kontot",
+ "{account_email} is no longer delegated to you" : "sul enam pole {account_email} e-posti konto volitust",
+ "{user} revoked delegation for {account}" : "{user} tühistas volituse {account} kasutajakonto jaoks",
"Mail Application" : "E-posti rakendus",
"Mails" : "E-kirjad",
"Sender email: %1$s is not in the address book, but the sender name: %2$s is in the address book with the following email: %3$s" : "Saatja aadress %1$s pole aadressiraamatus, aga %2$s nimi on ning temaga on seotud järgnev aadress: %3$s",
@@ -22,8 +26,13 @@
"Some addresses in this message are not matching the link text" : "Mõned selle kirja aadressid ei vasta lingi tekstile",
"Reply-To email: %1$s is different from sender email: %2$s" : "Vastamiseks mõeldud e-posti aadress: %1$s on erinev saatja aadressist %2$s",
"Mail connection performance" : "E-postiteenuse ühenduse jõudlus",
+ "Slow mail service detected (%1$s) an attempt to connect to several accounts took an average of %2$s seconds per account" : "Aeglase e-posti tuvastusteenus (%1$s) - mitme e-posti kontoga ühendamine võttis aega keskmiselt %2$s sekundit kasutajakontkonto kohta",
+ "Slow mail service detected (%1$s) an attempt to perform a mail box list operation on several accounts took an average of %2$s seconds per account" : "Aeglase e-posti tuvastusteenus (%1$s) - postkastide loendi laadimine mitme konto jaoks võttis aega keskmiselt %2$s sekundit kasutajakontkonto kohta",
+ "Mail Transport configuration" : "E-kirjade edastamise viis serverite vahel",
+ "The app.mail.transport setting is not set to smtp. This configuration can cause issues with modern email security measures such as SPF and DKIM because emails are sent directly from the web server, which is often not properly configured for this purpose. To address this, we have discontinued support for the mail transport. Please remove app.mail.transport from your configuration to use the SMTP transport and hide this message. A properly configured SMTP setup is required to ensure email delivery." : "„app.mail.transport“ seadistuse väärtus pole „smtp“. Selline seadistus võib põhjustada probleeme kaasaegsete e-posti turvameetmetega, nagu SPF ja DKIM, kuna e-kirjad saadetakse otse veebiserverist, mis ei ole selleks otstarbeks sageli nõuetekohaselt konfigureeritud. Selle probleemi lahendamiseks oleme lõpetanud „mail-transport“ meetodi toetamise. Palun eemalda serveri seadistustest „app.mail.transport“, et kasutada SMTP-põhist edastust ja peida see teade. E-kirjade kättetoimetamise tagamiseks on vaja nõuetekohaselt konfigureeritud SMTP-seadistust.",
"Mail account parameters, aliases and preferences" : "E-posti kasutajakonto parameetrid, aliased ja eelistused",
"💌 A mail app for Nextcloud" : "💌 E-postirakendus Nextcloudi jaoks",
+ "**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 E-posti rakendus Nextcloudi jaoks**\n\n- **🚀 Lõiming muude Nextcloudi rakendustega!** Hetkel kontakti-, kalendri ja failirakendused, aga õige pea lisandub neid veel.\n- **📥 Mitu e-posti kontot!** Isiklik ja töökoha konto? Pole probleemi ja kauba peale saad kena ja ühise sisendposti kausta. Võid ühendada kõiki IMAP-i kasutajakontosid.\n- **🔒 Saada krüptitud e-kirju ja võta neid vastu!** Selleks on kasutusel suurepärase veebibrauseri lisamoodul [Mailvelope](https://mailvelope.com).\n- **🙈 Me ei leiuta midagi uut!** Rakendus põhineb suurepärastel [Horde](https://www.horde.org) teekidel.\n- **📬 Tahad kasutada oma serverit?** Me ei hakanud seda ise leiutama, on ju olemas [Mail-in-a-Box](https://mailinabox.email) teenus!\n\n## Tehisaru eetiline kasutaus\n\n### Prioriteediga kirjad saabuvate kirjade postkastis\n\nPositiivne lähenemine:\n* Selle mudeli treenimiseks ja järelduste tegemiseks mõeldud tarkvara on avatud lähtekoodiga.\n* Mudel luuakse ja treenitakse kohapeal, tuginedes kasutaja enda andmetele.\n* Kasutajal on juurdepääs treeningandmetele, mis võimaldab kontrollida ja parandada võimalikke eelarvamusi ning optimeerida mudeli jõudlust ja CO2-heiteid.\n\n### Jutulõngade kokkuvõtted (kui tahad kasutada)\n\n**Hinnang:** 🟢/🟡/🟠/🔴\n\nHindamine sõltub paigaldatud tekstitöötluse taustateenusest. Üksikasju vaata dokumentatsioonist, mis kirjeldab [ülevaadet hindamisest](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html).\n\nTehisaru eetilisest kasutusest Nextcloudi raames leiad [teavet meie ajaveebist](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).",
"Your session has expired. The page will be reloaded." : "Sinu sessioon on aegunud. Leht saab olema uuesti laaditud.",
"Drafts are saved in:" : "Kirjade kavandis on salvestatud siia:",
"Sent messages are saved in:" : "Saadetud kirjad on salvestatud siia:",
@@ -86,6 +95,8 @@
"SMTP Port" : "SMTP port",
"SMTP User" : "SMTP kasutajanimi",
"SMTP Password" : "SMTP salasõna",
+ "Google requires OAuth authentication. If your Nextcloud admin has not configured Google OAuth, you can use a Google App Password instead." : "Google eeldab OAuthi autentimise kasutamist. Kui sinu Nextcloudi serveri haldaja või peakasutaja pole seda teinud, siis saad selle asemel kasutada Google'i rakenduse salasõna (Google App Password).",
+ "Microsoft requires OAuth authentication. Ask your Nextcloud admin to configure Microsoft OAuth in the admin settings." : "Microsoft eeldab OAuthi autentimise kasutamist. Palu oma Nextcloudi serveri haldajat või peakasutajat, et ta seadistaks Microsofti OAuthi.",
"Account settings" : "Konto seadistused",
"Aliases" : "Aliased",
"Alias to S/MIME certificate mapping" : "Alias S/MIME sertifikaatide vastavuse jaoks",
@@ -122,12 +133,13 @@
"Search the body of messages in priority Inbox" : "Otsi esmase postkasti kirjade sisust",
"Activate" : "Lülita sisse",
"Make mails available to Context Chat" : "Muuda e-kirjad loetavaks kontekstuaalses vestluses",
- "Remind about messages that require a reply but received none" : "Tuleta mulle meelde kirju, mis eeldavad vastust, kui pole seda veel saanud",
+ "Remind about messages that require a reply but received none" : "Tuleta mulle meelde kirju, mis eeldavad vastust, kuid pole seda veel saanud",
"Highlight external addresses" : "Tõsta välised aadressid esile",
"Could not update preference" : "Eelistust polnud võimalik muuta",
"Mail settings" : "E-kirjade seadistused",
"General" : "Üldine",
"Set as default mail app" : "Määra vaikimisi e-postirakenduseks",
+ "{email} (delegated)" : "{email} (volitatud)",
"Add mail account" : "Lisa e-posti konto",
"Appearance" : "Välimus",
"Show all messages in thread" : "Näita kõiki kirju jutulõngas",
@@ -137,7 +149,7 @@
"Layout" : "Välimus",
"Vertical split" : "Püstjoones jagamine",
"Horizontal split" : "Rõhtjoones jagamine",
- "List" : "Nimekiri",
+ "List" : "Loend",
"Use compact mode" : "Kasuta kompaktset vaadet",
"Sorting" : "Järjestus",
"Newest first" : "Uuemad eespool",
@@ -246,7 +258,21 @@
"Expand composer" : "Näita koostamisvaadet laiemana",
"Close composer" : "Sulge koostamisvaade",
"Confirm" : "Kinnita",
+ "Delegate access" : "Volita ligipääs",
"Revoke" : "Tühista",
+ "{userId} will no longer be able to act on your behalf" : "Kasutaja {userId} ei saa enam sinu nimel tegutseda",
+ "Could not fetch delegates" : "Volitatute laadimine ei õnnestunud",
+ "Delegated access to {userId}" : "Sa volitasid ligipääsu kasutajale {userId}",
+ "Could not delegate access" : "Ligipääsu volitamine ei õnnestunud",
+ "Revoked access for {userId}" : "Kasutaja {userId} volitus on eemaldatud",
+ "Could not revoke delegation" : "Volituse tühistamine ei õnnestunud",
+ "Delegation" : "Volitamine",
+ "Allow users to send, receive, and delete mail on your behalf" : "Luba volitatutel saata, vastu võtta ja kustutada e-kirju sinu nimel",
+ "Revoke access" : "Eemalda ligipääs",
+ "Add delegate" : "Lisa volitatav",
+ "Select a user" : "Vali kasutaja",
+ "They will be able to send, receive, and delete mail on your behalf" : "Volitatu võib saata, vastu võtta ja kustutada e-kirju sinu nimel",
+ "Revoke access?" : "Kas tühistad ligipääsu?",
"Tag: {name} deleted" : "Silt: {name} on kustutatud",
"An error occurred, unable to delete the tag." : "Tekkis viga, silti ei õnnestu kustutada",
"The tag will be deleted from all messages." : "See silt saab olema eemaldatud kõikide kirjade juurest.",
@@ -272,7 +298,7 @@
"No trash folder configured" : "Prügikasti kaust on määramata",
"Could not delete message" : "Kirja kustutamine ei õnnestunud",
"Could not archive message" : "Kirja arhiveerimine ei õnnestunud",
- "Thread was snoozed" : "Jutulõnga kuvamine on edasi lükatd",
+ "Thread was snoozed" : "Jutulõnga kuvamine on edasi lükatud",
"Could not snooze thread" : "Ei õnnestunud edasi lükata jutulõnga kuvamist",
"Thread was unsnoozed" : "Jutulõnga edasilükkamine on lõpetatud",
"Could not unsnooze thread" : "Jutulõnga edasilükkamise lõpetamine ei õnnestunud",
@@ -380,11 +406,14 @@
"Favorites" : "Lemmikud",
"Favorites info" : "Lemmikute teave",
"Load more favorites" : "Laadi veel lemmikuid",
+ "Follow up" : "Jätkukiri",
+ "Follow up info" : "Jätkukirja teave",
"Load more follow ups" : "Laadi veel jätkukirju",
"Important info" : "Oluline teave",
"Load more important messages" : "Laadi veel olulisi kirju",
"Other" : "Muu",
"Load more other messages" : "Laadi veel muid kirju",
+ "Could not send mdn" : "Olekuteate (Message Disposition Notification - MDN) edastamine ei õnnestunud",
"The sender of this message has asked to be notified when you read this message." : "Selle kirja saatja on palunud kinnitust, kui oled kirja lugenud.",
"Notify the sender" : "Teavita saatjat",
"You sent a read confirmation to the sender of this message." : "Sa saatsid selle kirja saatjale lugemisteatise.",
@@ -407,14 +436,14 @@
"Unnamed" : "Nimeta",
"Embedded message" : "Lõimitud kiri",
"Attachment saved to Files" : "Manus on salvestatud failirakendusse",
- "Attachment could not be saved" : "Manus polnud võimalik salvestada",
+ "Attachment could not be saved" : "Manust polnud võimalik salvestada",
"calendar imported" : "kalender on imporditud",
"Choose a folder to store the attachment in" : "Vali kaust, kuhu manus salvestada",
"Import into calendar" : "Impordi kalendrisse",
"Download attachment" : "Laadi manus alla",
"Save to Files" : "Salvesta failirakendusse",
"Attachments saved to Files" : "Manused on salvestatud failirakendusse",
- "Error while saving attachments" : "Viga manuse salvestamisel",
+ "Error while saving attachments" : "Viga manuste salvestamisel",
"View fewer attachments" : "Näita vähem manuseid",
"Choose a folder to store the attachments in" : "Vali kaust, kuhu soovid manuse salvestada",
"Save all to Files" : "Salvesta kõik failirakendusse",
@@ -440,7 +469,10 @@
"Remove account" : "Eemalda konto",
"The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider." : "E-posti konto {email} ja tema puhverdatud andmed eemaldatakse siit Nextcloudi serverist, kuid mitte sinu e-postiteenuse pakkuja juurest.",
"Remove {email}" : "Eemalda fail: „{email}“",
+ "could not delete account" : "kasutajakonto kustutamine ei õnnestunud",
+ "Provisioned account is disabled" : "Ettevalmistatud konto on eemaldatud kasutuselt",
"Please login using a password to enable this account. The current session is using passwordless authentication, e.g. SSO or WebAuthn." : "Selle konto kasutamiseks palun logi sisse salasõnaga. Praegune sessioon kasutab salasõnata tuvastamist, milleks võib olla SSO, WebAuthn, vms.",
+ "Delegate account" : "Volita konto kasutamine",
"Show only subscribed folders" : "Näita vaid tellitud kaustu",
"Add folder" : "Lisa kaust",
"Folder name" : "Kausta nimi",
@@ -537,7 +569,7 @@
"Open search modal" : "Ava modaalne otsinguvaade",
"Close" : "Sulge",
"Search parameters" : "Otsinguparameetrid",
- "Search subject" : "Otsi teemat",
+ "Search subject" : "Otsi teemat/pealkirja",
"Body" : "Sisu",
"Search body" : "Otsi sisust",
"Date" : "Kuupäev",
@@ -614,6 +646,8 @@
"Mark as unfavorite" : "Märgi mittelemmikuks",
"Mark as favorite" : "Märgi lemmikuks",
"To:" : "Saaja:",
+ "Cc:" : "Koopia:",
+ "Bcc:" : "Pimekoopia:",
"Unsubscribe via link" : "Loobu tellimusest lingi kaudu",
"Unsubscribing will stop all messages from the mailing list {sender}" : "Tellimusest loobudes sa enam ei saa kirju postiloendist {sender}",
"Send unsubscribe email" : "Saada loobumiskiri",
@@ -681,6 +715,7 @@
"contains" : "sisaldab",
"A substring match. The field matches if the provided value is contained within it. For example, \"report\" would match \"port\"." : "Stringi osaline vaste. Välja väärtus vastab, kui antud väärtus on selles sisalduv. Näiteks vastab „report“ sõnale „port“.",
"matches" : "kattub",
+ "A pattern match using wildcards. The \"*\" symbol represents any number of characters (including none), while \"?\" represents exactly one character. For example, \"*report*\" would match \"Business report 2024\"." : "Muster, milles kasutatakse metamärke. Sümbol „*“ tähistab mis tahes arvu märke (sh mitte ühtegi), samas kui „?“ tähistab täpselt ühte märki. Näiteks sobib „*report*“ kokku fraasiga „Business report 2024“.",
"Enter subject" : "Sisesta teema",
"Enter sender" : "Sisesta saatja",
"Enter recipient" : "Sisesta saaja",
@@ -712,17 +747,38 @@
"Successfully updated config for \"{domain}\"" : "„{domain}“ domeeni seadistuste uuendamine õnnestus",
"Error saving config" : "Viga seadistuste salvestamisel",
"Saved config for \"{domain}\"" : "„{domain}“ domeeni seadistused on salvestatud",
- "_Successfully provisioned {count} account._::_Successfully provisioned {count} accounts._" : ["{count} kasutajakonto ettevalmistamine õnnestus","{count} kasutajakonto ettevalmistamine õnnestus"],
+ "Could not save provisioning setting" : "Kasutajakonto eelseadistuse salvestamine ei õnnestunud",
+ "_Successfully provisioned {count} account._::_Successfully provisioned {count} accounts._" : ["{count} kasutajakonto eelseadistamine ja ettevalmistamine õnnestus","{count} kasutajakonto eelseadistamine ja ettevalmistamine õnnestus"],
+ "There was an error when provisioning accounts." : "Kasutajakontode eelseadistamisel ja ettevalmistamisel tekkis viga.",
+ "Successfully deleted and deprovisioned accounts for \"{domain}\"" : "„{domain}“ domeeni jaoks ettevalmistatud kontode kustutamine õnnestus",
+ "Error when deleting and deprovisioning accounts for \"{domain}\"" : "„{domain}“ domeeni jaoks ettevalmistatud kontode kustutamisel tekkis viga",
+ "Could not save default classification setting" : "Vaikimisi klassifitseerimise seadistuse salvestamine ei õnnestunud",
"Mail app" : "E-posti rakendus",
"The mail app allows users to read mails on their IMAP accounts." : "Selle rakendusega saavad kasutajad lugeda oma IMAP-i kontode kirju.",
"Here you can find instance-wide settings. User specific settings are found in the app itself (bottom-left corner)." : "Siin on serverikohased seadistused. Kasutajakohased seadistused leiduvad rakenduses (vaata alumist vasakut nurka).",
+ "Account provisioning" : "Kasutajakontode ettevalmistus",
+ "A provisioning configuration will provision all accounts with a matching email address." : "Ettevalmistuse seadistuse alusel valmistatakse ette kõik e-posti aadressid, mis tingimustele vastavad",
+ "Using the wildcard (*) in the provisioning domain field will create a configuration that applies to all users, provided they do not match another configuration." : "Kui kasutad metamärgiga (*) määratletud eelseadistamist, siis see seadistus kehtib kõigile, välja arvatud neile, kelle puhul kehib täpselt määratletud domeeni seadistus.",
+ "The provisioning mechanism will prioritise specific domain configurations over the wildcard domain configuration." : "Ettevalmistamise (eelseadistamise) mehhanism käsitleb konkreetse domeeni seadistuse kõrgema prioriteediga, kui metamärgiga domeeni seadistusi.",
+ "Should a new matching configuration be found after the user was already provisioned with another configuration, the new configuration will take precedence and the user will be reprovisioned with the configuration." : "Kui leitakse uus sobiv seadistus pärast seda, kui kasutajale on juba eelseadistus tehtud, siis on uuel seadistusel eelisõigus ja kasutajale tehakse uus eelseadistus selle alusel uuesti.",
+ "There can only be one configuration per domain and only one wildcard domain configuration." : "Võid koostada vaid ühe domeenikohase seadistuse ja ühe metamärk+domeen seadistuse.",
+ "These settings can be used in conjunction with each other." : "Neid seadistusi saad omavahel kombineerida.",
+ "If you only want to provision one domain for all users, use the wildcard (*)." : "Kui kavatsed kõikide kasutajate jaoks eelseadistada vaid ühte domeeni, siis kasuta metamärki (*).",
+ "This setting only makes most sense if you use the same user back-end for your Nextcloud and mail server of your organization." : "See seadistus on mõttekas vaid juhul, kui kasutad oma Nextcloudi ja organisatsiooni e-postiserveri jaoks sama kasutajate haldussüsteemi.",
+ "Provisioning Configurations" : "Ettevalmistamise seadistused",
"Add new config" : "Lisa uus konfiguratsioon",
+ "Provision all accounts" : "Valmista ette kõik kasutajakontod",
"Allow additional mail accounts" : "Lisa veel e-postikontosid",
"Allow additional Mail accounts from User Settings" : "Luba kasutaja seadistustest täiendavate e-posti kontode kasutamine",
"Enable text processing through LLMs" : "Kasuta teksti töötlemist suure keelemudeliga",
"The Mail app can process user data with the help of the configured large language model and provide assistance features like thread summaries, smart replies and event agendas." : "E-postirakendus oskab töödelda kasutajaandmeid seadistatud keelemudeli abil ning selle teha abitoiminguid, nagu jutulõngade ülevaadete, nutikate vastuste ja ürituste päevakavade koostamine.",
"Enable LLM processing" : "Lülita suure keelemudeliga töötlemine sisse",
+ "Enable classification by importance by default" : "Vaikimisi luba e-kirjade klassifitseerimine olulisuse alusel",
+ "The Mail app can classify incoming emails by importance using machine learning. This feature is enabled by default but can be disabled by default here. Individual users will still be able to toggle the feature for their accounts." : "Kasutades masinõpet oskab e-postirakendus kirju klassifitseerida olulisuse alusel. Vaikimisi on see võimalus kasutusel, kuid saad määrata, et ta vaikimisi on lülitatud välja. Sel puhul saavad kasutajad niisuguse võimaluse oma konto jaoks sisse lülitada.",
+ "Enable classification of important mails by default" : "Vaikimisi luba oluliste e-kirjade klassifitseerimine",
"Anti Spam Service" : "Spämmitõrjeteenus",
+ "You can set up an anti spam service email address here." : "Siin võid seadistada spämmitõrjeteenuse e-posti aadressi.",
+ "Any email that is marked as spam will be sent to the anti spam service." : "Spämmiks ehk rämpspostiks märgitud e-kiri saadetakse sellele teenusele.",
"Gmail integration" : "Lõiming Gmailiga",
"Gmail allows users to access their email via IMAP. For security reasons this access is only possible with an OAuth 2.0 connection or Google accounts that use two-factor authentication and app passwords." : "Gmail lubab kasutajatel lugeda kirju IMAP-i abil. Turvakaalutlustel toimib see vaid OAuth 2.0 liidestusega või kui Google'i konto kasutab kaheastmelist autentimist ja rakenduse salasõna.",
"You have to register a new Client ID for a \"Web application\" in the Google Cloud console. Add the URL {url} as authorized redirect URI." : "Sa pead Google Cloudi juhtpaneelis registreerima veebirakenduse (Web application) jaoks uue klienditunnuse (Client ID). Korrektse suunamisaadressina kasuta: {url}",
@@ -734,6 +790,13 @@
"These settings are used to pre-configure the user interface preferences they can be overridden by the user in the mail settings" : "Need on kasutajaliidese eelseadistused, mida iga kasutaja saab oma seadistustest muuta",
"Message View Mode" : "Kirjade vaate liik",
"Show only the selected message" : "Näita vaid valitud kirja",
+ "Successfully set up anti spam email addresses" : "Spämmitõrjeteenuse e-posti aadressi seadistamine õnnestus.",
+ "Error saving anti spam email addresses" : "Spämmitõrjeteenuse e-posti aadressi salvestamine ei õnnestunud.",
+ "Successfully deleted anti spam reporting email" : "Spämmitõrjeteenuse e-posti aadressi kustutamine õnnestus.",
+ "Error deleting anti spam reporting email" : "Spämmitõrjeteenuse e-posti aadressi kustutamine ei õnnestunud.",
+ "Anti Spam" : "Spämmi ehk rämsposti tõrjumine",
+ "Add the email address of your anti spam report service here." : "Lisa oma kasutatava spämmitõrjeteenuse e-posti aadress siia.",
+ "When using this setting, a report email will be sent to the SPAM report server when a user clicks \"Mark as spam\"." : "Selle seadistuse kasutamisel saadetakse teavituskiri spämmitõrjeteenusele niipea, kui kasutaja klõpsab valikut „Märgi rämpspostiks“.",
"The original message will be attached as a \"message/rfc822\" attachment." : "Algne kiri lisatakse manusena „message/rfc822“ tüüpi failina.",
"\"Mark as Spam\" Email Address" : "„Märgitud rämpspostiks“ e-posti aadressid",
"\"Mark Not Junk\" Email Address" : "„Pole rämpspost“ e-posti aadressid",
@@ -756,6 +819,7 @@
"SMTP: {user} on {host}:{port} ({ssl} encryption)" : "SMTP: {user} serveris {host}:{port} ({ssl} krüptimisega)",
"Sieve: {user} on {host}:{port} ({ssl} encryption)" : "Sieve: {user} serveris {host}:{port} ({ssl} krüptimisega)",
"Configuration for \"{provisioningDomain}\"" : "Seadistus „{provisioningDomain}“ domeeni jaoks",
+ "Provisioning domain" : "Domeeni ettevalmistamine",
"Email address template" : "E-posti aadressi mall",
"IMAP" : "IMAP",
"User" : "Kasutaja",
@@ -772,6 +836,7 @@
"LDAP attribute for aliases" : "LDAP-i omadused aliaste jaoks",
"A multi value attribute to provision email aliases. For each value an alias is created. Aliases existing in Nextcloud which are not in the LDAP directory are deleted." : "Mitmeväärtuseline e-posti aliaste eelkoostamise lahendus. Iga väärtuse kohta luuakse alias. Nexctcloudis leiduvate aliaste puhul, millel pole LDAP-i serveris vastet, kustutakse e-posti teenusest.",
"Save Config" : "Salvesta seadistus",
+ "Unprovision & Delete Config" : "Eemalda ettevalmistatud seadistused ja kustuta nad",
"* %USERID% and %EMAIL% will be replaced with the user's UID and email" : "* %USERID% ja %EMAIL% asendatakse kasutajatunnuse (UID) ja e-posti aadressiga",
"With the settings above, the app will create account settings in the following way:" : "Ülalmääratud seadistuste alusel loob rakendus kasutajakonto seadistused alljärgneval viisil:",
"The provided PKCS #12 certificate must contain at least one certificate and exactly one private key." : "Lisatud PKCS #12 sertifikaadis peab olema vähemalt üks sertifikaat ning ainult üks privaatvõti.",
From 809d826ae9e7b08d289c4ae519a7982459b6464f Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Sun, 31 May 2026 01:31:46 +0000
Subject: [PATCH 063/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/et_EE.js | 2 +-
l10n/et_EE.json | 2 +-
l10n/hu.js | 1 +
l10n/hu.json | 1 +
4 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/l10n/et_EE.js b/l10n/et_EE.js
index d95d32d65d..1e434f5190 100644
--- a/l10n/et_EE.js
+++ b/l10n/et_EE.js
@@ -339,7 +339,7 @@ OC.L10N.register(
"_Mark {number} as unimportant_::_Mark {number} as unimportant_" : ["Märgi {number} mitteoluliseks","Märgi {number} mitteoluliseks"],
"_Unfavorite {number}_::_Unfavorite {number}_" : ["Eemalda {number} lemmikute seast","Eemalda {number} lemmikute seast"],
"_Favorite {number}_::_Favorite {number}_" : ["Lisa {number} kiri lemmikuks","Lisa {number} kirja lemmikuks"],
- "_Unselect {number}_::_Unselect {number}_" : ["Eemalda {number} kiri lemmikute seast","Eemalda {number} kirja lemmikute seast"],
+ "_Unselect {number}_::_Unselect {number}_" : ["Eemalda {number} kiri valikust","Eemalda {number} kirja valikust"],
"_Mark {number} as spam_::_Mark {number} as spam_" : ["Märgi {number} kiri rämpspostiks","Märgi {number} kirja rämpspostiks"],
"_Mark {number} as not spam_::_Mark {number} as not spam_" : ["Eemalda {number}-lt kirjalt rämpsposti märge","Eemalda {number}-lt kirjalt rämpsposti märge"],
"_Edit tags for {number}_::_Edit tags for {number}_" : ["Muuda {number} kirja silte","Muuda {number} kirja silte"],
diff --git a/l10n/et_EE.json b/l10n/et_EE.json
index 303ceedd54..6254e580d8 100644
--- a/l10n/et_EE.json
+++ b/l10n/et_EE.json
@@ -337,7 +337,7 @@
"_Mark {number} as unimportant_::_Mark {number} as unimportant_" : ["Märgi {number} mitteoluliseks","Märgi {number} mitteoluliseks"],
"_Unfavorite {number}_::_Unfavorite {number}_" : ["Eemalda {number} lemmikute seast","Eemalda {number} lemmikute seast"],
"_Favorite {number}_::_Favorite {number}_" : ["Lisa {number} kiri lemmikuks","Lisa {number} kirja lemmikuks"],
- "_Unselect {number}_::_Unselect {number}_" : ["Eemalda {number} kiri lemmikute seast","Eemalda {number} kirja lemmikute seast"],
+ "_Unselect {number}_::_Unselect {number}_" : ["Eemalda {number} kiri valikust","Eemalda {number} kirja valikust"],
"_Mark {number} as spam_::_Mark {number} as spam_" : ["Märgi {number} kiri rämpspostiks","Märgi {number} kirja rämpspostiks"],
"_Mark {number} as not spam_::_Mark {number} as not spam_" : ["Eemalda {number}-lt kirjalt rämpsposti märge","Eemalda {number}-lt kirjalt rämpsposti märge"],
"_Edit tags for {number}_::_Edit tags for {number}_" : ["Muuda {number} kirja silte","Muuda {number} kirja silte"],
diff --git a/l10n/hu.js b/l10n/hu.js
index 6c76c75a08..e2d765ae4a 100644
--- a/l10n/hu.js
+++ b/l10n/hu.js
@@ -275,6 +275,7 @@ OC.L10N.register(
"You are not allowed to move this message to the archive folder and/or delete this message from the current folder" : "Nem helyezheti át ezt az üzenetet az archiválási mappába vagy törölheti a jelenlegi mappából",
"Last hour" : "Elmúlt óra",
"Today" : "Ma",
+ "Yesterday" : "Tegnap",
"Last week" : "Előző hét",
"Last month" : "Előző hónap",
"Choose target folder" : "Válasszon célmappát",
diff --git a/l10n/hu.json b/l10n/hu.json
index 49464c1098..0e7720bfdc 100644
--- a/l10n/hu.json
+++ b/l10n/hu.json
@@ -273,6 +273,7 @@
"You are not allowed to move this message to the archive folder and/or delete this message from the current folder" : "Nem helyezheti át ezt az üzenetet az archiválási mappába vagy törölheti a jelenlegi mappából",
"Last hour" : "Elmúlt óra",
"Today" : "Ma",
+ "Yesterday" : "Tegnap",
"Last week" : "Előző hét",
"Last month" : "Előző hónap",
"Choose target folder" : "Válasszon célmappát",
From 768ff4c64bdfa277aef9775c1c51171de4ad60cc Mon Sep 17 00:00:00 2001
From: Grigory Vodyanov
Date: Mon, 1 Jun 2026 00:16:11 +0200
Subject: [PATCH 064/228] fix(AccountSettings): overflow bug when using
autoresponder checkbox
Signed-off-by: Grigory Vodyanov
---
css/mail.scss | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/css/mail.scss b/css/mail.scss
index 8bdf76b29e..de334d5eef 100755
--- a/css/mail.scss
+++ b/css/mail.scss
@@ -309,6 +309,13 @@
opacity: .6;
}
+.app-settings .modal-wrapper .modal-container {
+ overflow: visible !important;
+
+ .modal-container__content {
+ border-radius: var(--border-radius-container, var(--border-radius-rounded));
+ }
+}
/* compose (handling mailto links) */
From 7e4eab620aa9931d6141b1febab6d512653e5bf9 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Mon, 1 Jun 2026 01:30:42 +0000
Subject: [PATCH 065/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/nn_NO.js | 4 ++++
l10n/nn_NO.json | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/l10n/nn_NO.js b/l10n/nn_NO.js
index 75129e736b..fbacc06cac 100644
--- a/l10n/nn_NO.js
+++ b/l10n/nn_NO.js
@@ -11,6 +11,7 @@ OC.L10N.register(
"Password" : "Passord",
"None" : "Ingen",
"Signature" : "Signatur",
+ "Filters" : "Filter",
"Cancel" : "Avbryt",
"General" : "Generelt",
"Appearance" : "Utsjånad",
@@ -24,12 +25,14 @@ OC.L10N.register(
"Ok" : "Greitt",
"Choose" : "Vel",
"Favorite" : "Favoritt",
+ "More actions" : "Fleire handlingar",
"Back" : "Tilbake",
"Attendees" : "Deltakarar",
"Description" : "Skildring",
"Create" : "Lag",
"Select" : "Vel",
"Comment" : "Kommentér",
+ "Accept" : "Godta",
"Remove" : "Fjern",
"Today" : "I dag",
"Yesterday" : "I går",
@@ -45,6 +48,7 @@ OC.L10N.register(
"Close" : "Lat att",
"Date" : "Dato",
"Tags" : "Emneord",
+ "Not found" : "Ikkje funne",
"Deleted" : "Sletta",
"Recipient" : "Mottakar",
"Help" : "Hjelp",
diff --git a/l10n/nn_NO.json b/l10n/nn_NO.json
index 9416c2a304..7894265ceb 100644
--- a/l10n/nn_NO.json
+++ b/l10n/nn_NO.json
@@ -9,6 +9,7 @@
"Password" : "Passord",
"None" : "Ingen",
"Signature" : "Signatur",
+ "Filters" : "Filter",
"Cancel" : "Avbryt",
"General" : "Generelt",
"Appearance" : "Utsjånad",
@@ -22,12 +23,14 @@
"Ok" : "Greitt",
"Choose" : "Vel",
"Favorite" : "Favoritt",
+ "More actions" : "Fleire handlingar",
"Back" : "Tilbake",
"Attendees" : "Deltakarar",
"Description" : "Skildring",
"Create" : "Lag",
"Select" : "Vel",
"Comment" : "Kommentér",
+ "Accept" : "Godta",
"Remove" : "Fjern",
"Today" : "I dag",
"Yesterday" : "I går",
@@ -43,6 +46,7 @@
"Close" : "Lat att",
"Date" : "Dato",
"Tags" : "Emneord",
+ "Not found" : "Ikkje funne",
"Deleted" : "Sletta",
"Recipient" : "Mottakar",
"Help" : "Hjelp",
From f9803f9fbd043de726b08f1bdc04a7795a8a7f00 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Fri, 29 May 2026 15:33:58 +0200
Subject: [PATCH 066/228] fix(smtp): handle non ascii sender names
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.../horde-mail-rfc822-isAtext-empty-zero.patch | 11 +++++++++++
REUSE.toml | 6 ++++++
patches.json | 7 +++++++
patches.lock.json | 14 +++++++++++++-
4 files changed, 37 insertions(+), 1 deletion(-)
create mode 100644 .patches/horde-mail-rfc822-isAtext-empty-zero.patch
diff --git a/.patches/horde-mail-rfc822-isAtext-empty-zero.patch b/.patches/horde-mail-rfc822-isAtext-empty-zero.patch
new file mode 100644
index 0000000000..3b6b2f5c50
--- /dev/null
+++ b/.patches/horde-mail-rfc822-isAtext-empty-zero.patch
@@ -0,0 +1,11 @@
+--- a/lib/Horde/Mail/Rfc822.php
++++ b/lib/Horde/Mail/Rfc822.php
+@@ -802,7 +802,7 @@
+ return strcspn($chr, $validate);
+ }
+
+- $ord = empty($chr) ? 0 : ord($chr);
++ $ord = ($chr === '' || $chr === false) ? 0 : ord($chr);
+
+ /* UTF-8 characters check. */
+ if ($ord > 127) {
diff --git a/REUSE.toml b/REUSE.toml
index e9e447c556..a54195f80c 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -179,6 +179,12 @@ precedence = "aggregate"
SPDX-FileCopyrightText = "angrychimp, Teon d.o.o. - Bostjan Skufca, Marcus Bointon"
SPDX-License-Identifier = "MIT"
+[[annotations]]
+path = [".patches/horde-mail-rfc822-isAtext-empty-zero.patch"]
+precedence = "aggregate"
+SPDX-FileCopyrightText = "2026 Nextcloud GmbH and Nextcloud contributors"
+SPDX-License-Identifier = "AGPL-3.0-or-later"
+
[[annotations]]
path = [".patches/url-normalizer-fix-deprecation-warning-on-PHP-8.5.patch"]
precedence = "aggregate"
diff --git a/patches.json b/patches.json
index 1562ee2148..099ce2a6a7 100644
--- a/patches.json
+++ b/patches.json
@@ -19,6 +19,13 @@
"upstream-fix-url": "https://github.com/PHPMailer/DKIMValidator/pull/21"
}
}
+ ],
+ "bytestream/horde-mail": [
+ {
+ "description": "Fix _rfc822IsAtext treating digit 0 as empty due to PHP empty() quirk",
+ "url": ".patches/horde-mail-rfc822-isAtext-empty-zero.patch",
+ "sha256": "b864ec2b2ba71b37a44c05e69934ec9f95269b8f1cc1ef8352a294e02ae3eb71"
+ }
]
}
}
diff --git a/patches.lock.json b/patches.lock.json
index 1c7d42e8aa..86a0f495d5 100644
--- a/patches.lock.json
+++ b/patches.lock.json
@@ -1,5 +1,5 @@
{
- "_hash": "e3297c923adcdbd735cc8da9765e21e3f6bcb9f669ed228d8954814d910fc127",
+ "_hash": "6053b3121d6c1645269ff3498cce80b35864f85ff75b039cc6c5889e28706293",
"patches": {
"glenscott/url-normalizer": [
{
@@ -26,6 +26,18 @@
"provenance": "patches-file:patches.json"
}
}
+ ],
+ "bytestream/horde-mail": [
+ {
+ "package": "bytestream/horde-mail",
+ "description": "Fix _rfc822IsAtext treating digit 0 as empty due to PHP empty() quirk",
+ "url": ".patches/horde-mail-rfc822-isAtext-empty-zero.patch",
+ "sha256": "b864ec2b2ba71b37a44c05e69934ec9f95269b8f1cc1ef8352a294e02ae3eb71",
+ "depth": 1,
+ "extra": {
+ "provenance": "patches-file:patches.json"
+ }
+ }
]
}
}
From b45cf9b63fe21ea152c85e253a2441de6d900759 Mon Sep 17 00:00:00 2001
From: nextcloud-command
Date: Mon, 1 Jun 2026 07:47:28 +0000
Subject: [PATCH 067/228] fix(dns): Update public suffix list
Signed-off-by: GitHub
---
resources/public_suffix_list.dat | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/resources/public_suffix_list.dat b/resources/public_suffix_list.dat
index 37e4479c48..bccfc0ac96 100644
--- a/resources/public_suffix_list.dat
+++ b/resources/public_suffix_list.dat
@@ -5,8 +5,8 @@
// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat,
// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported.
-// VERSION: 2026-05-14_08-35-31_UTC
-// COMMIT: e452c7058d6946bd76952b128c12f5ce87a5acb8
+// VERSION: 2026-05-28_06-25-58_UTC
+// COMMIT: e596036bde712ffb073b948eb8b884c72c94c6e1
// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/.
@@ -1403,6 +1403,7 @@ video.hu
// id : https://www.iana.org/domains/root/db/id.html
id
ac.id
+ai.id
biz.id
co.id
desa.id
@@ -12574,10 +12575,12 @@ cafjs.com
// Submitted by Joel Aquilina
canva-apps.cn
my.canvasite.cn
+khsj.cn
canva-apps.com
canva-hosted-embed.com
canvacode.com
rice-labs.com
+canva.link
canva.run
my.canva.site
@@ -16203,11 +16206,10 @@ webflowtest.io
*.webhare.dev
// WebHotelier Technologies Ltd : https://www.webhotelier.net/
-// Submitted by Apostolos Tsakpinis
-bookonline.app
+// Submitted by Apostolos Tsakpinis
hotelwithflight.com
-reserve-online.com
reserve-online.net
+book.online
// WebPros International, LLC : https://webpros.com/
// Submitted by Nicolas Rochelemagne
From be44178b10f1862643d9e74b13efb1e3e97a8952 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 1 Jun 2026 14:09:36 +0000
Subject: [PATCH 068/228] chore(deps): bump webpack-merge from ^5.10.0 to v6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
package-lock.json | 18 ++----------------
package.json | 2 +-
2 files changed, 3 insertions(+), 17 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index dcba54128a..0e0791a8f1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -97,7 +97,7 @@
"vue-template-compiler": "^2.7.16",
"webpack": "^5.106.2",
"webpack-cli": "^6.0.1",
- "webpack-merge": "^5.10.0"
+ "webpack-merge": "^6.0.1"
},
"engines": {
"node": "^24.0.0",
@@ -18437,7 +18437,7 @@
"node": ">= 10.13.0"
}
},
- "node_modules/webpack-cli/node_modules/webpack-merge": {
+ "node_modules/webpack-merge": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz",
"integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==",
@@ -18452,20 +18452,6 @@
"node": ">=18.0.0"
}
},
- "node_modules/webpack-merge": {
- "version": "5.10.0",
- "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
- "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
- "dev": true,
- "dependencies": {
- "clone-deep": "^4.0.1",
- "flat": "^5.0.2",
- "wildcard": "^2.0.0"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
"node_modules/webpack-sources": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.0.tgz",
diff --git a/package.json b/package.json
index 024c4e235a..2c78a39eb6 100644
--- a/package.json
+++ b/package.json
@@ -110,7 +110,7 @@
"vue-template-compiler": "^2.7.16",
"webpack": "^5.106.2",
"webpack-cli": "^6.0.1",
- "webpack-merge": "^5.10.0"
+ "webpack-merge": "^6.0.1"
},
"engines": {
"node": "^24.0.0",
From 5e3100021605ff4ba4c47a7e699b09673e6a9c58 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 2 Jun 2026 00:09:30 +0000
Subject: [PATCH 069/228] fix(deps): bump vitest from ^3.2.4 to v4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
package-lock.json | 425 ++++++++++++++++++----------------------------
package.json | 2 +-
2 files changed, 168 insertions(+), 259 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index dcba54128a..240b7038e5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -92,7 +92,7 @@
"ts-loader": "^9.5.7",
"typescript": "^5.9.3",
"url-loader": "^4.1.1",
- "vitest": "^3.2.4",
+ "vitest": "^4.0.0",
"vue-loader": "^15.11.1",
"vue-template-compiler": "^2.7.16",
"webpack": "^5.106.2",
@@ -3980,9 +3980,10 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.29",
@@ -5606,6 +5607,13 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@stylistic/eslint-plugin": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.7.1.tgz",
@@ -6085,59 +6093,87 @@
}
},
"node_modules/@vitest/expect": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz",
- "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz",
+ "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "@standard-schema/spec": "^1.1.0",
"@types/chai": "^5.2.2",
- "@vitest/spy": "3.2.4",
- "@vitest/utils": "3.2.4",
- "chai": "^5.2.0",
- "tinyrainbow": "^2.0.0"
+ "@vitest/spy": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "chai": "^6.2.2",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
+ "node_modules/@vitest/mocker": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz",
+ "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "4.1.8",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.21"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@vitest/pretty-format": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz",
- "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz",
+ "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tinyrainbow": "^2.0.0"
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/runner": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz",
- "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz",
+ "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "3.2.4",
- "pathe": "^2.0.3",
- "strip-literal": "^3.0.0"
+ "@vitest/utils": "4.1.8",
+ "pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/snapshot": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz",
- "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz",
+ "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "3.2.4",
- "magic-string": "^0.30.17",
+ "@vitest/pretty-format": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "magic-string": "^0.30.21",
"pathe": "^2.0.3"
},
"funding": {
@@ -6145,28 +6181,25 @@
}
},
"node_modules/@vitest/spy": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz",
- "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz",
+ "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "tinyspy": "^4.0.3"
- },
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/utils": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz",
- "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz",
+ "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "3.2.4",
- "loupe": "^3.1.4",
- "tinyrainbow": "^2.0.0"
+ "@vitest/pretty-format": "4.1.8",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -6891,16 +6924,6 @@
"util": "^0.12.5"
}
},
- "node_modules/assertion-error": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
- "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/astral-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
@@ -7496,16 +7519,6 @@
"resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz",
"integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q=="
},
- "node_modules/cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/cacheable": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.4.tgz",
@@ -7620,18 +7633,11 @@
}
},
"node_modules/chai": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
- "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "assertion-error": "^2.0.1",
- "check-error": "^2.1.1",
- "deep-eql": "^5.0.1",
- "loupe": "^3.1.0",
- "pathval": "^2.0.0"
- },
"engines": {
"node": ">=18"
}
@@ -7698,16 +7704,6 @@
"node": "*"
}
},
- "node_modules/check-error": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
- "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 16"
- }
- },
"node_modules/chokidar": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
@@ -8020,8 +8016,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/core-js": {
"version": "3.49.0",
@@ -8404,16 +8399,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/deep-eql": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
- "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -8893,13 +8878,6 @@
"node": ">= 0.4"
}
},
- "node_modules/es-module-lexer": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
- "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
@@ -9652,6 +9630,16 @@
"node": ">=4.0"
}
},
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -9694,9 +9682,9 @@
}
},
"node_modules/expect-type": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz",
- "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -12151,13 +12139,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/loupe": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
- "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/lowlight": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.2.0.tgz",
@@ -12183,13 +12164,13 @@
}
},
"node_modules/magic-string": {
- "version": "0.30.17",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
- "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0"
+ "@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/markdown-table": {
@@ -13517,6 +13498,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/obug": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz",
+ "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT"
+ },
"node_modules/open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
@@ -13907,16 +13899,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/pathval": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
- "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14.16"
- }
- },
"node_modules/pbkdf2": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz",
@@ -15835,9 +15817,9 @@
"license": "MIT"
},
"node_modules/std-env": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz",
- "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz",
+ "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==",
"dev": true,
"license": "MIT"
},
@@ -16090,26 +16072,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/strip-literal": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
- "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^9.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
- "node_modules/strip-literal/node_modules/js-tokens": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
- "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/striptags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/striptags/-/striptags-3.2.0.tgz",
@@ -16804,11 +16766,14 @@
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
},
"node_modules/tinyexec": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
- "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
+ "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
},
"node_modules/tinyglobby": {
"version": "0.2.15",
@@ -16858,30 +16823,10 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/tinypool": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
- "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- }
- },
"node_modules/tinyrainbow": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
- "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/tinyspy": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
- "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
+ "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -17721,29 +17666,6 @@
}
}
},
- "node_modules/vite-node": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
- "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cac": "^6.7.14",
- "debug": "^4.4.1",
- "es-module-lexer": "^1.7.0",
- "pathe": "^2.0.3",
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
- },
- "bin": {
- "vite-node": "vite-node.mjs"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
"node_modules/vite/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@@ -17776,65 +17698,79 @@
}
},
"node_modules/vitest": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz",
- "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz",
+ "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/chai": "^5.2.2",
- "@vitest/expect": "3.2.4",
- "@vitest/mocker": "3.2.4",
- "@vitest/pretty-format": "^3.2.4",
- "@vitest/runner": "3.2.4",
- "@vitest/snapshot": "3.2.4",
- "@vitest/spy": "3.2.4",
- "@vitest/utils": "3.2.4",
- "chai": "^5.2.0",
- "debug": "^4.4.1",
- "expect-type": "^1.2.1",
- "magic-string": "^0.30.17",
+ "@vitest/expect": "4.1.8",
+ "@vitest/mocker": "4.1.8",
+ "@vitest/pretty-format": "4.1.8",
+ "@vitest/runner": "4.1.8",
+ "@vitest/snapshot": "4.1.8",
+ "@vitest/spy": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "es-module-lexer": "^2.0.0",
+ "expect-type": "^1.3.0",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.1",
"pathe": "^2.0.3",
- "picomatch": "^4.0.2",
- "std-env": "^3.9.0",
+ "picomatch": "^4.0.3",
+ "std-env": "^4.0.0-rc.1",
"tinybench": "^2.9.0",
- "tinyexec": "^0.3.2",
- "tinyglobby": "^0.2.14",
- "tinypool": "^1.1.1",
- "tinyrainbow": "^2.0.0",
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
- "vite-node": "3.2.4",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tinyrainbow": "^3.1.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
"why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
- "@types/debug": "^4.1.12",
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "@vitest/browser": "3.2.4",
- "@vitest/ui": "3.2.4",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "4.1.8",
+ "@vitest/browser-preview": "4.1.8",
+ "@vitest/browser-webdriverio": "4.1.8",
+ "@vitest/coverage-istanbul": "4.1.8",
+ "@vitest/coverage-v8": "4.1.8",
+ "@vitest/ui": "4.1.8",
"happy-dom": "*",
- "jsdom": "*"
+ "jsdom": "*",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
- "@types/debug": {
+ "@opentelemetry/api": {
"optional": true
},
"@types/node": {
"optional": true
},
- "@vitest/browser": {
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
"optional": true
},
"@vitest/ui": {
@@ -17845,45 +17781,18 @@
},
"jsdom": {
"optional": true
- }
- }
- },
- "node_modules/vitest/node_modules/@vitest/mocker": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz",
- "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/spy": "3.2.4",
- "estree-walker": "^3.0.3",
- "magic-string": "^0.30.17"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "msw": "^2.4.9",
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
- },
- "peerDependenciesMeta": {
- "msw": {
- "optional": true
},
"vite": {
- "optional": true
+ "optional": false
}
}
},
- "node_modules/vitest/node_modules/estree-walker": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "node_modules/vitest/node_modules/es-module-lexer": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.0"
- }
+ "license": "MIT"
},
"node_modules/vitest/node_modules/picomatch": {
"version": "4.0.4",
diff --git a/package.json b/package.json
index 024c4e235a..2120405d69 100644
--- a/package.json
+++ b/package.json
@@ -105,7 +105,7 @@
"ts-loader": "^9.5.7",
"typescript": "^5.9.3",
"url-loader": "^4.1.1",
- "vitest": "^3.2.4",
+ "vitest": "^4.0.0",
"vue-loader": "^15.11.1",
"vue-template-compiler": "^2.7.16",
"webpack": "^5.106.2",
From 2fae929b1b75ba02ce502638e70247848c7ae5e4 Mon Sep 17 00:00:00 2001
From: Hamza
Date: Thu, 28 May 2026 15:48:37 +0200
Subject: [PATCH 070/228] chore: add audit logs to delegated actions
Signed-off-by: Hamza
---
lib/Controller/AccountsController.php | 13 +-
lib/Controller/AliasesController.php | 29 ++-
lib/Controller/DraftsController.php | 5 +-
lib/Controller/FilterController.php | 1 +
lib/Controller/ListController.php | 1 +
lib/Controller/MailboxesController.php | 19 +-
lib/Controller/MessageApiController.php | 12 +-
lib/Controller/MessagesController.php | 12 ++
lib/Controller/OutboxController.php | 11 +-
lib/Controller/SieveController.php | 3 +
lib/Controller/ThreadController.php | 4 +
lib/Service/DelegationService.php | 11 +
.../Controller/AccountsControllerTest.php | 56 ++++++
.../Unit/Controller/AliasesControllerTest.php | 12 ++
.../Unit/Controller/DraftsControllerTest.php | 9 +
.../Unit/Controller/FilterControllerTest.php | 89 +++++++++
tests/Unit/Controller/ListControllerTest.php | 5 +
.../Controller/MailboxesControllerTest.php | 188 ++++++++++++++++++
.../Controller/MessageApiControllerTest.php | 17 +-
.../Controller/MessagesControllerTest.php | 15 ++
.../Unit/Controller/OutboxControllerTest.php | 43 ++++
tests/Unit/Controller/SieveControllerTest.php | 26 ++-
.../Unit/Controller/ThreadControllerTest.php | 6 +
tests/Unit/Service/DelegationServiceTest.php | 21 ++
24 files changed, 575 insertions(+), 33 deletions(-)
create mode 100644 tests/Unit/Controller/FilterControllerTest.php
diff --git a/lib/Controller/AccountsController.php b/lib/Controller/AccountsController.php
index a87d6c07ac..bc1d6b3567 100644
--- a/lib/Controller/AccountsController.php
+++ b/lib/Controller/AccountsController.php
@@ -152,6 +152,7 @@ public function update(int $id,
?string $smtpPassword = null,
string $authMethod = 'password'): JSONResponse {
try {
+ $effectiveUserId = $this->delegationService->resolveAccountUserId($id, $this->currentUserId);
// Make sure the account actually exists
$this->accountService->find($this->currentUserId, $id);
} catch (ClientException $e) {
@@ -179,9 +180,11 @@ public function update(int $id,
}
try {
- return MailJsonResponse::success(
+ $result = MailJsonResponse::success(
$this->setup->createNewAccount($accountName, $emailAddress, $imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword, $this->currentUserId, $authMethod, $id)
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated account <$id> on behalf of $effectiveUserId");
+ return $result;
} catch (CouldNotConnectException $e) {
$data = [
'error' => $e->getReason(),
@@ -293,6 +296,7 @@ public function patchAccount(int $id,
$result = new JSONResponse(
new Account($this->accountService->save($dbAccount))
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId patched account <$id> on behalf of $effectiveUserId");
return $result;
}
@@ -311,6 +315,7 @@ public function patchAccount(int $id,
public function updateSignature(int $id, ?string $signature = null): JSONResponse {
$effectiveUserId = $this->delegationService->resolveAccountUserId($id, $this->currentUserId);
$this->accountService->updateSignature($id, $effectiveUserId, $signature);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated signature for account <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -325,7 +330,9 @@ public function updateSignature(int $id, ?string $signature = null): JSONRespons
*/
#[TrapError]
public function destroy(int $id): JSONResponse {
- $this->accountService->delete($this->currentUserId, $id);
+ $effectiveUserId = $this->delegationService->resolveAccountUserId($id, $this->currentUserId);
+ $this->accountService->delete($effectiveUserId, $id);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId deleted account <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -461,6 +468,7 @@ public function draft(int $id,
null,
[]
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId saved draft in account <$id> on behalf of $effectiveUserId");
return new JSONResponse([
'id' => $this->mailManager->getMessageIdForUid($draftsMailbox, $newUID)
]);
@@ -503,6 +511,7 @@ public function updateSmimeCertificate(int $id, ?int $smimeCertificateId = null)
$account = $this->accountService->find($effectiveUserId, $id)->getMailAccount();
$account->setSmimeCertificateId($smimeCertificateId);
$this->accountService->update($account);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated S/MIME certificate for account <$id> on behalf of $effectiveUserId");
return MailJsonResponse::success();
}
diff --git a/lib/Controller/AliasesController.php b/lib/Controller/AliasesController.php
index 3e28b2220c..344017aa27 100644
--- a/lib/Controller/AliasesController.php
+++ b/lib/Controller/AliasesController.php
@@ -71,15 +71,15 @@ public function update(int $id,
string $aliasName,
?int $smimeCertificateId = null): JSONResponse {
$effectiveUserId = $this->delegationService->resolveAliasUserId($id, $this->currentUserId);
- return new JSONResponse(
- $this->aliasService->update(
- $effectiveUserId,
- $id,
- $alias,
- $aliasName,
- $smimeCertificateId,
- )
+ $alias = $this->aliasService->update(
+ $effectiveUserId,
+ $id,
+ $alias,
+ $aliasName,
+ $smimeCertificateId,
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated alias: $id on behalf of $effectiveUserId");
+ return new JSONResponse($alias);
}
/**
@@ -91,7 +91,9 @@ public function update(int $id,
#[TrapError]
public function destroy(int $id): JSONResponse {
$effectiveUserId = $this->delegationService->resolveAliasUserId($id, $this->currentUserId);
- return new JSONResponse($this->aliasService->delete($effectiveUserId, $id));
+ $alias = $this->aliasService->delete($effectiveUserId, $id);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId deleted alias: $id on behalf of $effectiveUserId");
+ return new JSONResponse($alias);
}
/**
@@ -108,8 +110,11 @@ public function destroy(int $id): JSONResponse {
#[TrapError]
public function create(int $accountId, string $alias, string $aliasName): JSONResponse {
$effectiveUserId = $this->delegationService->resolveAccountUserId($accountId, $this->currentUserId);
+ $alias = $this->aliasService->create($effectiveUserId, $accountId, $alias, $aliasName);
+ $id = $alias->getId();
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId created alias: $id on behalf of $effectiveUserId");
return new JSONResponse(
- $this->aliasService->create($effectiveUserId, $accountId, $alias, $aliasName),
+ $alias,
Http::STATUS_CREATED
);
}
@@ -127,6 +132,8 @@ public function create(int $accountId, string $alias, string $aliasName): JSONRe
#[TrapError]
public function updateSignature(int $id, ?string $signature = null): JSONResponse {
$effectiveUserId = $this->delegationService->resolveAliasUserId($id, $this->currentUserId);
- return new JSONResponse($this->aliasService->updateSignature($effectiveUserId, $id, $signature));
+ $alias = $this->aliasService->updateSignature($effectiveUserId, $id, $signature);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated alias: $id 's signature on behalf of $effectiveUserId");
+ return new JSONResponse($alias);
}
}
diff --git a/lib/Controller/DraftsController.php b/lib/Controller/DraftsController.php
index 841f69ccf0..eb3917cf9d 100644
--- a/lib/Controller/DraftsController.php
+++ b/lib/Controller/DraftsController.php
@@ -125,7 +125,8 @@ public function create(
}
$this->service->saveMessage($account, $message, $to, $cc, $bcc, $attachments);
-
+ $id = $message->getId();
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId created draft: $id on behalf of $effectiveUserId");
return JsonResponse::success($message, Http::STATUS_CREATED);
}
@@ -213,6 +214,7 @@ public function destroy(int $id): JsonResponse {
$this->accountService->find($effectiveUserId, $message->getAccountId());
$this->service->deleteMessage($effectiveUserId, $message);
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId deleted draft: $id on behalf of $effectiveUserId");
return JsonResponse::success('Message deleted', Http::STATUS_ACCEPTED);
}
@@ -229,6 +231,7 @@ public function move(int $id): JsonResponse {
$account = $this->accountService->find($effectiveUserId, $message->getAccountId());
$this->service->sendMessage($message, $account);
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId moved draft: $id to the IMAP server on behalf of $effectiveUserId");
return JsonResponse::success(
'Message moved to IMAP', Http::STATUS_ACCEPTED
);
diff --git a/lib/Controller/FilterController.php b/lib/Controller/FilterController.php
index 8dc99b1c4c..5a2bb5f882 100644
--- a/lib/Controller/FilterController.php
+++ b/lib/Controller/FilterController.php
@@ -66,6 +66,7 @@ public function updateFilters(int $accountId, array $filters): JSONResponse {
}
$this->mailFilterService->update($account->getMailAccount(), $filters);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated account: $accountId 's filters on behalf of $effectiveUserId");
return new JSONResponse([]);
}
diff --git a/lib/Controller/ListController.php b/lib/Controller/ListController.php
index f804ad3e34..5ba0c6991d 100644
--- a/lib/Controller/ListController.php
+++ b/lib/Controller/ListController.php
@@ -99,6 +99,7 @@ public function unsubscribe(int $id): JsonResponse {
} finally {
$client->logout();
}
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId unsubscribed from mailing list: $id on behalf of $effectiveUserId");
return JsonResponse::success();
}
diff --git a/lib/Controller/MailboxesController.php b/lib/Controller/MailboxesController.php
index 0368a9bc46..06962b07a0 100644
--- a/lib/Controller/MailboxesController.php
+++ b/lib/Controller/MailboxesController.php
@@ -126,6 +126,7 @@ public function patch(int $id,
$mailbox,
$name
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId changed mailbox: id 's name to $name on behalf of $effectiveUserId");
}
if ($subscribed !== null) {
$mailbox = $this->mailManager->updateSubscription(
@@ -133,14 +134,18 @@ public function patch(int $id,
$mailbox,
$subscribed
);
+ $subscribedVerb = $subscribed ? 'subscribed' : 'unsubscribed';
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId $subscribedVerb to mailbox: $id on behalf of $effectiveUserId");
+
}
if ($syncInBackground !== null) {
$mailbox = $this->mailManager->enableMailboxBackgroundSync(
$mailbox,
$syncInBackground
);
+ $syncVerb = $syncInBackground ? 'enabled' : 'disabled';
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId $syncVerb background sync for mailbox: $id on behalf of $effectiveUserId");
}
-
return new JSONResponse($mailbox);
}
@@ -251,6 +256,8 @@ public function markAllAsRead(int $id): JSONResponse {
$this->mailManager->markFolderAsRead($account, $mailbox);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId marked all messages as read in mailbox: $id on behalf of $effectiveUserId");
+
return new JSONResponse([]);
}
@@ -321,8 +328,11 @@ public function create(int $accountId, string $name): JSONResponse {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
$account = $this->accountService->find($effectiveUserId, $accountId);
+ $mailbox = $this->mailManager->createMailbox($account, $name);
+ $id = $mailbox->getId();
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId created mailbox: $id on behalf of $effectiveUserId");
- return new JSONResponse($this->mailManager->createMailbox($account, $name));
+ return new JSONResponse($mailbox);
}
/**
@@ -349,6 +359,8 @@ public function destroy(int $id): JSONResponse {
$account = $this->accountService->find($effectiveUserId, $mailbox->getAccountId());
$this->mailManager->deleteMailbox($account, $mailbox);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId deleted mailbox: $id on behalf of $effectiveUserId");
+
return new JSONResponse();
}
@@ -377,6 +389,7 @@ public function clearMailbox(int $id): JSONResponse {
$account = $this->accountService->find($effectiveUserId, $mailbox->getAccountId());
$this->mailManager->clearMailbox($account, $mailbox);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId cleared mailbox: $id on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -400,6 +413,8 @@ public function repair(int $id): JSONResponse {
$account = $this->accountService->find($effectiveUserId, $mailbox->getAccountId());
$this->syncService->repairSync($account, $mailbox);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId repaired mailbox: $id on behalf of $effectiveUserId");
+
return new JsonResponse();
}
}
diff --git a/lib/Controller/MessageApiController.php b/lib/Controller/MessageApiController.php
index 1e313e43cb..52882b81a4 100644
--- a/lib/Controller/MessageApiController.php
+++ b/lib/Controller/MessageApiController.php
@@ -206,8 +206,16 @@ public function send(
$this->logger->error('SMTP error: could not send message', ['exception' => $e]);
return new DataResponse('Fatal SMTP error: could not send message, and no resending is possible. Please check the mail server logs.', Http::STATUS_INTERNAL_SERVER_ERROR);
}
-
- return match ($localMessage->getStatus()) {
+ $status = $localMessage->getStatus();
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, match ($status) {
+ LocalMessage::STATUS_PROCESSED => "$this->userId sent a message on behalf of $effectiveUserId",
+ LocalMessage::STATUS_NO_SENT_MAILBOX => "$this->userId attempted sending a message on behalf of $effectiveUserId but no sent mailbox is configured",
+ LocalMessage::STATUS_SMPT_SEND_FAIL => "$this->userId attempted sending a message on behalf of $effectiveUserId but SMTP sending failed",
+ LocalMessage::STATUS_IMAP_SENT_MAILBOX_FAIL => "$this->userId sent a message on behalf of $effectiveUserId but copying to sent mailbox failed",
+ default => "$this->userId attempted sending a message on behalf of $effectiveUserId but an unknown error occurred",
+ });
+
+ return match ($status) {
LocalMessage::STATUS_PROCESSED => new DataResponse('', Http::STATUS_OK),
LocalMessage::STATUS_NO_SENT_MAILBOX => new DataResponse('Configuration error: Cannot send message without sent mailbox.', Http::STATUS_FORBIDDEN),
LocalMessage::STATUS_SMPT_SEND_FAIL => new DataResponse('SMTP error: could not send message. Message sending will be retried. Please check the logs.', Http::STATUS_INTERNAL_SERVER_ERROR),
diff --git a/lib/Controller/MessagesController.php b/lib/Controller/MessagesController.php
index 1bf463c277..2e9c0a0648 100755
--- a/lib/Controller/MessagesController.php
+++ b/lib/Controller/MessagesController.php
@@ -428,6 +428,9 @@ public function move(int $id, int $destFolderId): JSONResponse {
$dstAccount,
$dstMailbox->getName()
);
+
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId moved message <$id> to mailbox <$destFolderId> on behalf of $effectiveUserId");
+
return new JSONResponse();
}
@@ -459,6 +462,7 @@ public function snooze(int $id, int $unixTimestamp, int $destMailboxId): JSONRes
}
$this->snoozeService->snoozeMessage($message, $unixTimestamp, $srcAccount, $srcMailbox, $dstAccount, $dstMailbox);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId snoozed message <$id> to <$unixTimestamp> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -485,6 +489,7 @@ public function unSnooze(int $id): JSONResponse {
}
$this->snoozeService->unSnoozeMessage($message, $effectiveUserId);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId unsnoozed message <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -898,10 +903,14 @@ public function setFlags(int $id, array $flags): JSONResponse {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
+ $flagChanges = [];
foreach ($flags as $flag => $value) {
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
$this->mailManager->flagMessage($account, $mailbox->getName(), $message->getUid(), $flag, $value);
+ $flagChanges[] = "$flag=" . ($value ? 'true' : 'false');
}
+ $flagsSummary = implode(', ', $flagChanges);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated flags on message <$id> with [$flagsSummary] on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -937,6 +946,7 @@ public function setTag(int $id, string $imapLabel): JSONResponse {
}
$this->mailManager->tagMessage($account, $mailbox->getName(), $message, $tag, true);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId added tag <$imapLabel> on message <$id> on behalf of $effectiveUserId");
return new JSONResponse($tag);
}
@@ -972,6 +982,7 @@ public function removeTag(int $id, string $imapLabel): JSONResponse {
}
$this->mailManager->tagMessage($account, $mailbox->getName(), $message, $tag, false);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId removed tag <$imapLabel> on message <$id> on behalf of $effectiveUserId");
return new JSONResponse($tag);
}
@@ -1004,6 +1015,7 @@ public function destroy(int $id): JSONResponse {
$mailbox->getName(),
$message->getUid()
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId deleted message <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
diff --git a/lib/Controller/OutboxController.php b/lib/Controller/OutboxController.php
index c58cca4b32..86c84d4b8d 100644
--- a/lib/Controller/OutboxController.php
+++ b/lib/Controller/OutboxController.php
@@ -142,6 +142,7 @@ public function create(
}
$this->service->saveMessage($account, $message, $to, $cc, $bcc, $attachments);
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId created an outbox message for account <$accountId> on behalf of $effectiveUserId");
return JsonResponse::success($message, Http::STATUS_CREATED);
}
@@ -159,6 +160,7 @@ public function createFromDraft(DraftsService $draftsService, int $id, int $send
$this->accountService->find($effectiveUserId, $draftMessage->getAccountId());
$outboxMessage = $this->service->convertDraft($draftMessage, $sendAt);
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId created an outbox message from draft <$id> on behalf of $effectiveUserId");
return JsonResponse::success(
$outboxMessage,
@@ -235,6 +237,7 @@ public function update(
}
$message = $this->service->updateMessage($account, $message, $to, $cc, $bcc, $attachments);
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId updated outbox message <$id> for account <$accountId> on behalf of $effectiveUserId");
return JsonResponse::success($message, Http::STATUS_ACCEPTED);
}
@@ -252,8 +255,13 @@ public function send(int $id): JsonResponse {
$account = $this->accountService->find($effectiveUserId, $message->getAccountId());
$message = $this->service->sendMessage($message, $account);
+ $status = $message->getStatus();
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, match ($status) {
+ LocalMessage::STATUS_PROCESSED => "$this->userId sent outbox message <$id> on behalf of $effectiveUserId",
+ default => "$this->userId attempted sending outbox message <$id> on behalf of $effectiveUserId but sending failed",
+ });
- if ($message->getStatus() !== LocalMessage::STATUS_PROCESSED) {
+ if ($status !== LocalMessage::STATUS_PROCESSED) {
return JsonResponse::error('Could not send message', Http::STATUS_INTERNAL_SERVER_ERROR, [$message]);
}
return JsonResponse::success(
@@ -272,6 +280,7 @@ public function destroy(int $id): JsonResponse {
$effectiveUserId = $this->delegationService->resolveLocalMessageUserId($id, $this->userId);
$message = $this->service->getMessage($id, $effectiveUserId);
$this->service->deleteMessage($effectiveUserId, $message);
+ $this->delegationService->logDelegatedAction($this->userId, $effectiveUserId, "$this->userId deleted outbox message <$id> on behalf of $effectiveUserId");
return JsonResponse::success('Message deleted', Http::STATUS_ACCEPTED);
}
}
diff --git a/lib/Controller/SieveController.php b/lib/Controller/SieveController.php
index 83675f063b..ddfbc315e6 100644
--- a/lib/Controller/SieveController.php
+++ b/lib/Controller/SieveController.php
@@ -99,6 +99,7 @@ public function updateActiveScript(int $id, string $script): JSONResponse {
$this->logger->error('Installing sieve script failed: ' . $e->getMessage(), ['app' => 'mail', 'exception' => $e]);
return new JSONResponse(data: ['message' => $e->getMessage()], statusCode: Http::STATUS_UNPROCESSABLE_ENTITY);
}
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated the active sieve script for account <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -152,6 +153,7 @@ public function updateAccount(int $id,
$mailAccount->setSievePassword(null);
$this->mailAccountMapper->save($mailAccount);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated sieve settings for account <$id> on behalf of $effectiveUserId");
return new JSONResponse(['sieveEnabled' => $mailAccount->isSieveEnabled()]);
}
@@ -183,6 +185,7 @@ public function updateAccount(int $id,
}
$this->mailAccountMapper->save($mailAccount);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId updated sieve settings for account <$id> on behalf of $effectiveUserId");
return new JSONResponse(['sieveEnabled' => $mailAccount->isSieveEnabled()]);
}
}
diff --git a/lib/Controller/ThreadController.php b/lib/Controller/ThreadController.php
index de53adf6f8..7ed2afb6ce 100755
--- a/lib/Controller/ThreadController.php
+++ b/lib/Controller/ThreadController.php
@@ -89,6 +89,7 @@ public function move(int $id, int $destMailboxId): JSONResponse {
$dstMailbox,
$threadRootId
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId moved thread <$id> to mailbox <$destMailboxId> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -118,6 +119,7 @@ public function snooze(int $id, int $unixTimestamp, int $destMailboxId): JSONRes
}
$this->snoozeService->snoozeThread($selectedMessage, $unixTimestamp, $srcAccount, $srcMailbox, $dstAccount, $dstMailbox);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId snoozed thread <$id> until <$unixTimestamp> in mailbox <$destMailboxId> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -141,6 +143,7 @@ public function unSnooze(int $id): JSONResponse {
}
$this->snoozeService->unSnoozeThread($selectedMessage, $effectiveUserId);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId unsnoozed thread <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
@@ -239,6 +242,7 @@ public function delete(int $id): JSONResponse {
$mailbox,
$threadRootId
);
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId deleted thread <$id> on behalf of $effectiveUserId");
return new JSONResponse();
}
diff --git a/lib/Service/DelegationService.php b/lib/Service/DelegationService.php
index 588ca42731..d21bc833a3 100644
--- a/lib/Service/DelegationService.php
+++ b/lib/Service/DelegationService.php
@@ -20,7 +20,9 @@
use OCA\Mail\Exception\DelegationExistsException;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUserManager;
+use OCP\Log\Audit\CriticalActionPerformedEvent;
use OCP\Notification\IManager;
use OCP\Notification\IncompleteNotificationException;
use Psr\Log\LoggerInterface;
@@ -37,6 +39,7 @@ public function __construct(
private IUserManager $userManager,
private IManager $notificationManager,
private ITimeFactory $time,
+ private IEventDispatcher $eventDispatcher,
private LoggerInterface $logger,
) {
}
@@ -128,6 +131,14 @@ public function resolveLocalMessageUserId(int $localMessageId, string $currentUs
return $this->resolveAccountUserId($accountId, $currentUserId);
}
+
+ public function logDelegatedAction(string $currentUserId, string $effectiveUserId, string $logMessage): void {
+ if ($currentUserId === $effectiveUserId) {
+ return;
+ }
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent($logMessage));
+ }
+
/**
* Send a notification on delegation
* @param string $userId The user the account is being delegated to
diff --git a/tests/Unit/Controller/AccountsControllerTest.php b/tests/Unit/Controller/AccountsControllerTest.php
index 234ca139a6..d11ebe2603 100644
--- a/tests/Unit/Controller/AccountsControllerTest.php
+++ b/tests/Unit/Controller/AccountsControllerTest.php
@@ -15,6 +15,7 @@
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Contracts\IMailTransmission;
use OCA\Mail\Controller\AccountsController;
+use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\IMAP\MailboxSync;
@@ -197,6 +198,9 @@ public function testUpdateSignature(): void {
$this->accountService->expects(self::once())
->method('updateSignature')
->with(self::equalTo($this->accountId), self::equalTo($this->userId), 'sig');
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated signature for account <$this->accountId> on behalf of $this->userId");
$response = $this->controller->updateSignature($this->accountId, 'sig');
@@ -219,6 +223,9 @@ public function testDestroy(): void {
$this->accountService->expects(self::once())
->method('delete')
->with(self::equalTo($this->userId), self::equalTo($this->accountId));
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted account <$this->accountId> on behalf of $this->userId");
$response = $this->controller->destroy($this->accountId);
@@ -334,6 +341,9 @@ public function testUpdateManualSuccess(): void {
->method('createNewAccount')
->with($accountName, $email, $imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword, $this->userId, 'password', $id)
->willReturn($account);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated account <$id> on behalf of $this->userId");
$response = $this->controller->update($id, $accountName, $email, $imapHost, $imapPort, $imapSslMode, $imapUser, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $imapPassword, $smtpPassword);
@@ -398,6 +408,9 @@ public function testDraft(): void {
$this->syncService->expects(self::once())
->method('syncMailbox')
->willReturn(new Response([], [], []));
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId saved draft in account <$this->accountId> on behalf of $this->userId");
$actual = $this->controller->draft($this->accountId, $subject, $body, $to, $cc, $bcc, true, $id);
@@ -406,4 +419,47 @@ public function testDraft(): void {
]);
self::assertEquals($expected, $actual);
}
+
+ public function testPatchAccountLogsDelegatedAction(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId($this->accountId);
+ $mailAccount->setUserId($this->userId);
+ $account = new Account($mailAccount);
+ $this->accountService->expects(self::once())
+ ->method('find')
+ ->with($this->userId, $this->accountId)
+ ->willReturn($account);
+ $this->accountService->expects(self::once())
+ ->method('save')
+ ->willReturn($mailAccount);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId patched account <$this->accountId> on behalf of $this->userId");
+
+ $response = $this->controller->patchAccount($this->accountId, 'plaintext');
+
+ self::assertEquals(new JSONResponse(new Account($mailAccount)), $response);
+ }
+
+ public function testUpdateSmimeCertificateLogsDelegatedAction(): void {
+ $mailAccount = new MailAccount();
+ $mailAccount->setId($this->accountId);
+ $mailAccount->setUserId($this->userId);
+ $account = new Account($mailAccount);
+ $this->accountService->expects(self::once())
+ ->method('find')
+ ->with($this->userId, $this->accountId)
+ ->willReturn($account);
+ $this->accountService->expects(self::once())
+ ->method('update')
+ ->with($mailAccount);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated S/MIME certificate for account <$this->accountId> on behalf of $this->userId");
+
+ $response = $this->controller->updateSmimeCertificate($this->accountId, 42);
+
+ self::assertEquals(42, $mailAccount->getSmimeCertificateId());
+ self::assertInstanceOf(JSONResponse::class, $response);
+ }
}
diff --git a/tests/Unit/Controller/AliasesControllerTest.php b/tests/Unit/Controller/AliasesControllerTest.php
index 067cecda14..024ce35641 100644
--- a/tests/Unit/Controller/AliasesControllerTest.php
+++ b/tests/Unit/Controller/AliasesControllerTest.php
@@ -98,6 +98,9 @@ public function testUpdate(): void {
$this->aliasMapper->expects($this->once())
->method('update')
->willReturnArgument(0);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated alias: {$alias->getId()} on behalf of $this->userId");
$response = $this->controller->update($alias->getId(), 'john@doe.com', 'John Doe');
/** @var Alias $data */
@@ -149,6 +152,9 @@ public function testDestroy(): void {
$this->aliasMapper->expects($this->once())
->method('delete')
->willReturnArgument(0);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted alias: {$alias->getId()} on behalf of $this->userId");
$expectedResponse = new JSONResponse($alias);
$response = $this->controller->destroy($alias->getId());
@@ -188,6 +194,9 @@ public function testCreate(): void {
$this->aliasMapper->expects($this->once())
->method('insert')
->willReturn($alias);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId created alias: {$alias->getId()} on behalf of $this->userId");
$expectedResponse = new JSONResponse(
$alias,
@@ -235,6 +244,9 @@ public function testUpdateSignature(): void {
$this->aliasMapper->expects($this->once())
->method('update')
->willReturnArgument(0);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated alias: {$alias->getId()} 's signature on behalf of $this->userId");
$expectedResponse = new JSONResponse(
$alias,
diff --git a/tests/Unit/Controller/DraftsControllerTest.php b/tests/Unit/Controller/DraftsControllerTest.php
index d9651ff6fa..fe34b71b81 100644
--- a/tests/Unit/Controller/DraftsControllerTest.php
+++ b/tests/Unit/Controller/DraftsControllerTest.php
@@ -83,6 +83,9 @@ public function testMove(): void {
$this->service->expects(self::once())
->method('sendMessage')
->with($message, $account);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId moved draft: {$message->getId()} to the IMAP server on behalf of $this->userId");
$expected = JsonResponse::success('Message moved to IMAP', Http::STATUS_ACCEPTED);
$actual = $this->controller->move($message->getId());
@@ -169,6 +172,9 @@ public function testDestroy(): void {
$this->service->expects(self::once())
->method('deleteMessage')
->with($this->userId, $message);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted draft: {$message->getId()} on behalf of $this->userId");
$expected = JsonResponse::success('Message deleted', Http::STATUS_ACCEPTED);
$actual = $this->controller->destroy($message->getId());
@@ -226,6 +232,9 @@ public function testCreate(): void {
$this->service->expects(self::once())
->method('saveMessage')
->with($account, $message, $to, $cc, [], []);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId created draft: on behalf of $this->userId");
$expected = JsonResponse::success($message, Http::STATUS_CREATED);
$actual = $this->controller->create(
diff --git a/tests/Unit/Controller/FilterControllerTest.php b/tests/Unit/Controller/FilterControllerTest.php
new file mode 100644
index 0000000000..880dcd1b9a
--- /dev/null
+++ b/tests/Unit/Controller/FilterControllerTest.php
@@ -0,0 +1,89 @@
+request = $this->createMock(IRequest::class);
+ $this->filterService = $this->createMock(FilterService::class);
+ $this->accountService = $this->createMock(AccountService::class);
+ $this->delegationService = $this->createMock(DelegationService::class);
+ $this->delegationService->method('resolveAccountUserId')
+ ->willReturn($this->userId);
+
+ $this->controller = new FilterController(
+ $this->request,
+ $this->userId,
+ $this->filterService,
+ $this->accountService,
+ $this->delegationService,
+ );
+ }
+
+ public function testUpdateFiltersLogsDelegatedAction(): void {
+ $accountId = 42;
+ $mailAccount = new MailAccount();
+ $mailAccount->setUserId($this->userId);
+ $account = new Account($mailAccount);
+ $this->accountService->expects(self::once())
+ ->method('findById')
+ ->with($accountId)
+ ->willReturn($account);
+ $this->filterService->expects(self::once())
+ ->method('update')
+ ->with($mailAccount, ['filter1']);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated account: $accountId 's filters on behalf of $this->userId");
+
+ $response = $this->controller->updateFilters($accountId, ['filter1']);
+
+ self::assertEquals(Http::STATUS_OK, $response->getStatus());
+ }
+
+ public function testUpdateFiltersNotFoundDoesNotLog(): void {
+ $accountId = 42;
+ $mailAccount = new MailAccount();
+ $mailAccount->setUserId('someone-else');
+ $account = new Account($mailAccount);
+ $this->accountService->expects(self::once())
+ ->method('findById')
+ ->with($accountId)
+ ->willReturn($account);
+ $this->filterService->expects(self::never())
+ ->method('update');
+ $this->delegationService->expects(self::never())
+ ->method('logDelegatedAction');
+
+ $response = $this->controller->updateFilters($accountId, []);
+
+ self::assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
+ }
+}
diff --git a/tests/Unit/Controller/ListControllerTest.php b/tests/Unit/Controller/ListControllerTest.php
index b97b9dd482..5dc66ccbe9 100644
--- a/tests/Unit/Controller/ListControllerTest.php
+++ b/tests/Unit/Controller/ListControllerTest.php
@@ -27,6 +27,7 @@
class ListControllerTest extends TestCase {
private ServiceMockObject $serviceMock;
private ListController $controller;
+ private string $userId = 'user123';
protected function setUp(): void {
parent::setUp();
@@ -235,6 +236,10 @@ public function testUnsubscribe(): void {
$httpClient->expects(self::once())
->method('post')
->with('https://un.sub.scribe/me');
+ $this->serviceMock->getParameter('delegationService')
+ ->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, 'user123 unsubscribed from mailing list: 123 on behalf of user123');
$response = $this->controller->unsubscribe(123);
diff --git a/tests/Unit/Controller/MailboxesControllerTest.php b/tests/Unit/Controller/MailboxesControllerTest.php
index 51ffc5d3ef..e25b3d7e30 100644
--- a/tests/Unit/Controller/MailboxesControllerTest.php
+++ b/tests/Unit/Controller/MailboxesControllerTest.php
@@ -121,6 +121,7 @@ public function testShow() {
public function testCreate() {
$account = $this->createStub(Account::class);
$mailbox = new Mailbox();
+ $mailbox->setId(99);
$accountId = 28;
$this->accountService->expects($this->once())
->method('find')
@@ -130,6 +131,9 @@ public function testCreate() {
->method('createMailbox')
->with($this->equalTo($account), $this->equalTo('new'))
->willReturn($mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId created mailbox: {$mailbox->getId()} on behalf of $this->userId");
$response = $this->controller->create($accountId, 'new');
@@ -137,6 +141,190 @@ public function testCreate() {
$this->assertEquals($expected, $response);
}
+ public function testPatchRenameLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->with($this->userId, 28)
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('renameMailbox')
+ ->with($account, $mailbox, 'renamed')
+ ->willReturn($mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId changed mailbox: id 's name to renamed on behalf of $this->userId");
+
+ $response = $this->controller->patch($mailboxId, 'renamed');
+
+ $this->assertEquals(new JSONResponse($mailbox), $response);
+ }
+
+ public function testPatchSubscribeLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('updateSubscription')
+ ->with($account, $mailbox, true)
+ ->willReturn($mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId subscribed to mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->patch($mailboxId, null, true);
+ }
+
+ public function testPatchUnsubscribeLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('updateSubscription')
+ ->with($account, $mailbox, false)
+ ->willReturn($mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId unsubscribed to mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->patch($mailboxId, null, false);
+ }
+
+ public function testPatchEnableSyncLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('enableMailboxBackgroundSync')
+ ->with($mailbox, true)
+ ->willReturn($mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId enabled background sync for mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->patch($mailboxId, null, null, true);
+ }
+
+ public function testMarkAllAsReadLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('markFolderAsRead')
+ ->with($account, $mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId marked all messages as read in mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->markAllAsRead($mailboxId);
+ }
+
+ public function testDestroyLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('deleteMailbox')
+ ->with($account, $mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->destroy($mailboxId);
+ }
+
+ public function testClearMailboxLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->mailManager->expects($this->once())
+ ->method('clearMailbox')
+ ->with($account, $mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId cleared mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->clearMailbox($mailboxId);
+ }
+
+ public function testRepairLogsDelegatedAction(): void {
+ $mailboxId = 13;
+ $mailbox = new Mailbox();
+ $mailbox->setId($mailboxId);
+ $mailbox->setAccountId(28);
+ $account = $this->createStub(Account::class);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->once())
+ ->method('find')
+ ->willReturn($account);
+ $this->syncService->expects($this->once())
+ ->method('repairSync')
+ ->with($account, $mailbox);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId repaired mailbox: $mailboxId on behalf of $this->userId");
+
+ $this->controller->repair($mailboxId);
+ }
+
public function testStats(): void {
$mailbox = new Mailbox();
$mailbox->setUnseen(10);
diff --git a/tests/Unit/Controller/MessageApiControllerTest.php b/tests/Unit/Controller/MessageApiControllerTest.php
index 6ab43d2dea..62e9f4ece5 100644
--- a/tests/Unit/Controller/MessageApiControllerTest.php
+++ b/tests/Unit/Controller/MessageApiControllerTest.php
@@ -405,7 +405,7 @@ public function testMailboxNotFound(): void {
/**
* @dataProvider mailData
*/
- public function testSend($messageStatus, $expected): void {
+ public function testSend($messageStatus, $expected, ?string $expectedLogMessage = null): void {
$this->message->setStatus($messageStatus);
$this->accountService->expects(self::once())
@@ -426,6 +426,11 @@ public function testSend($messageStatus, $expected): void {
$this->outboxService->expects(self::once())
->method('sendMessage')
->willReturn($this->message);
+ if ($expectedLogMessage !== null) {
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, $expectedLogMessage);
+ }
$actual = $this->controller->send(
$this->accountId,
@@ -475,11 +480,11 @@ public function testSendNoRecipient(): void {
public function mailData() {
return [
- [LocalMessage::STATUS_PROCESSED, new DataResponse('', Http::STATUS_OK)],
- [LocalMessage::STATUS_NO_SENT_MAILBOX, new DataResponse('Configuration error: Cannot send message without sent mailbox.', Http::STATUS_FORBIDDEN)],
- [LocalMessage::STATUS_SMPT_SEND_FAIL, new DataResponse('SMTP error: could not send message. Message sending will be retried. Please check the logs.', Http::STATUS_INTERNAL_SERVER_ERROR)],
- [LocalMessage::STATUS_IMAP_SENT_MAILBOX_FAIL, new DataResponse('Email was sent but could not be copied to sent mailbox. Copying will be retried. Please check the logs.', Http::STATUS_ACCEPTED)],
- [LocalMessage::STATUS_TOO_MANY_RECIPIENTS, new DataResponse('An error occured. Please check the logs.', Http::STATUS_INTERNAL_SERVER_ERROR)],
+ [LocalMessage::STATUS_PROCESSED, new DataResponse('', Http::STATUS_OK), 'john sent a message on behalf of john'],
+ [LocalMessage::STATUS_NO_SENT_MAILBOX, new DataResponse('Configuration error: Cannot send message without sent mailbox.', Http::STATUS_FORBIDDEN), 'john attempted sending a message on behalf of john but no sent mailbox is configured'],
+ [LocalMessage::STATUS_SMPT_SEND_FAIL, new DataResponse('SMTP error: could not send message. Message sending will be retried. Please check the logs.', Http::STATUS_INTERNAL_SERVER_ERROR), 'john attempted sending a message on behalf of john but SMTP sending failed'],
+ [LocalMessage::STATUS_IMAP_SENT_MAILBOX_FAIL, new DataResponse('Email was sent but could not be copied to sent mailbox. Copying will be retried. Please check the logs.', Http::STATUS_ACCEPTED), 'john sent a message on behalf of john but copying to sent mailbox failed'],
+ [LocalMessage::STATUS_TOO_MANY_RECIPIENTS, new DataResponse('An error occured. Please check the logs.', Http::STATUS_INTERNAL_SERVER_ERROR), 'john attempted sending a message on behalf of john but an unknown error occurred'],
];
}
diff --git a/tests/Unit/Controller/MessagesControllerTest.php b/tests/Unit/Controller/MessagesControllerTest.php
index 6f57b3ca72..5651124b18 100644
--- a/tests/Unit/Controller/MessagesControllerTest.php
+++ b/tests/Unit/Controller/MessagesControllerTest.php
@@ -697,6 +697,9 @@ public function testSetFlagsUnseen() {
$this->mailManager->expects($this->once())
->method('flagMessage')
->with($this->account, 'INBOX', 444, 'seen', false);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated flags on message <$id> with [seen=false] on behalf of $this->userId");
$expected = new JSONResponse();
$response = $this->controller->setFlags(
@@ -804,6 +807,9 @@ public function testSetTag() {
$this->mailManager->expects($this->once())
->method('tagMessage')
->with($this->account, $mailbox->getName(), $message, $tag, true);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId added tag <{$tag->getImapLabel()}> on message <$id> on behalf of $this->userId");
$this->controller->setTag($id, $tag->getImapLabel());
}
@@ -905,6 +911,9 @@ public function testRemoveTag() {
$this->mailManager->expects($this->once())
->method('tagMessage')
->with($this->account, $mailbox->getName(), $message, $tag, false);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId removed tag <{$tag->getImapLabel()}> on message <$id> on behalf of $this->userId");
$this->controller->removeTag($id, $tag->getImapLabel());
}
@@ -937,6 +946,9 @@ public function testSetFlagsFlagged() {
$this->mailManager->expects($this->once())
->method('flagMessage')
->with($this->account, 'INBOX', 444, 'flagged', true);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated flags on message <$id> with [flagged=true] on behalf of $this->userId");
$expected = new JSONResponse();
$response = $this->controller->setFlags(
@@ -972,6 +984,9 @@ public function testDestroy() {
$this->mailManager->expects($this->once())
->method('deleteMessage')
->with($this->account, 'INBOX', 444);
+ $this->delegationService->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted message <$id> on behalf of $this->userId");
$expected = new JSONResponse();
$result = $this->controller->destroy($id);
diff --git a/tests/Unit/Controller/OutboxControllerTest.php b/tests/Unit/Controller/OutboxControllerTest.php
index ff31d91315..ccf9044baf 100644
--- a/tests/Unit/Controller/OutboxControllerTest.php
+++ b/tests/Unit/Controller/OutboxControllerTest.php
@@ -154,6 +154,9 @@ public function testSend(): void {
->method('sendMessage')
->with($message, $account)
->willReturn($newMessage);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId sent outbox message <{$message->getId()}> on behalf of $this->userId");
$expected = JsonResponse::success('Message sent', Http::STATUS_ACCEPTED);
$actual = $this->controller->send($message->getId());
@@ -161,6 +164,37 @@ public function testSend(): void {
$this->assertEquals($expected, $actual);
}
+ public function testSendFailedLogsFailureAction(): void {
+ $message = new LocalMessage();
+ $message->setId(1);
+ $message->setAccountId(1);
+ $newMessage = new LocalMessage();
+ $newMessage->setId(1);
+ $newMessage->setAccountId(1);
+ $newMessage->setStatus(LocalMessage::STATUS_SMPT_SEND_FAIL);
+ $account = new Account(new MailAccount());
+
+ $this->service->expects(self::once())
+ ->method('getMessage')
+ ->with($message->getId(), $this->userId)
+ ->willReturn($message);
+ $this->accountService->expects(self::once())
+ ->method('find')
+ ->with($this->userId, $message->getAccountId())
+ ->willReturn($account);
+ $this->service->expects(self::once())
+ ->method('sendMessage')
+ ->with($message, $account)
+ ->willReturn($newMessage);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId attempted sending outbox message <{$message->getId()}> on behalf of $this->userId but sending failed");
+
+ $actual = $this->controller->send($message->getId());
+
+ $this->assertEquals(Http::STATUS_INTERNAL_SERVER_ERROR, $actual->getStatus());
+ }
+
public function testSendNoMessage(): void {
$message = new LocalMessage();
$message->setId(1);
@@ -237,6 +271,9 @@ public function testDestroy(): void {
$this->service->expects(self::once())
->method('deleteMessage')
->with($this->userId, $message);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted outbox message <{$message->getId()}> on behalf of $this->userId");
$expected = JsonResponse::success('Message deleted', Http::STATUS_ACCEPTED);
$actual = $this->controller->destroy($message->getId());
@@ -289,6 +326,9 @@ public function testCreate(): void {
$this->service->expects(self::once())
->method('saveMessage')
->with($account, $message, $to, $cc, [], []);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId created an outbox message for account <{$message->getAccountId()}> on behalf of $this->userId");
$expected = JsonResponse::success($message, Http::STATUS_CREATED);
$actual = $this->controller->create(
@@ -428,6 +468,9 @@ public function testUpdate(): void {
->method('updateMessage')
->with($account, $message, $to, $cc, [], [])
->willReturn($message);
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated outbox message <{$message->getId()}> for account <{$message->getAccountId()}> on behalf of $this->userId");
$expected = JsonResponse::success($message, Http::STATUS_ACCEPTED);
$actual = $this->controller->update(
diff --git a/tests/Unit/Controller/SieveControllerTest.php b/tests/Unit/Controller/SieveControllerTest.php
index 9a7bde01b9..6fa6bd6956 100644
--- a/tests/Unit/Controller/SieveControllerTest.php
+++ b/tests/Unit/Controller/SieveControllerTest.php
@@ -29,6 +29,8 @@ class SieveControllerTest extends TestCase {
/** @var SieveController */
private $sieveController;
+ private string $userId = 'testUser';
+
protected function setUp(): void {
parent::setUp();
@@ -40,12 +42,12 @@ protected function setUp(): void {
SieveController::class,
[
'hostValidator' => $this->remoteHostValidator,
- 'userId' => '1',
+ 'userId' => $this->userId,
]
);
$this->serviceMock->getParameter('delegationService')
->method('resolveAccountUserId')
- ->willReturn('1');
+ ->willReturn($this->userId);
$this->sieveController = $this->serviceMock->getService();
}
@@ -53,10 +55,14 @@ public function testUpdateAccountDisable(): void {
$mailAccountMapper = $this->serviceMock->getParameter('mailAccountMapper');
$mailAccountMapper->expects($this->once())
->method('find')
- ->with('1', 2)
+ ->with($this->userId, 2)
->willReturn(new MailAccount());
$mailAccountMapper->expects($this->once())
->method('save');
+ $this->serviceMock->getParameter('delegationService')
+ ->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated sieve settings for account <2> on behalf of $this->userId");
$response = $this->sieveController->updateAccount(2, false, '', 0, '', '', '');
@@ -68,7 +74,7 @@ public function testUpdateAccountEnable(): void {
$mailAccountMapper = $this->serviceMock->getParameter('mailAccountMapper');
$mailAccountMapper->expects($this->once())
->method('find')
- ->with('1', 2)
+ ->with($this->userId, 2)
->willReturn(new MailAccount());
$mailAccountMapper->expects($this->once())
->method('save');
@@ -87,7 +93,7 @@ public function testUpdateAccountEnableImapCredentials(): void {
$mailAccountMapper = $this->serviceMock->getParameter('mailAccountMapper');
$mailAccountMapper->expects($this->once())
->method('find')
- ->with('1', 2)
+ ->with($this->userId, 2)
->willReturn($mailAccount);
$mailAccountMapper->expects($this->once())
->method('save');
@@ -105,7 +111,7 @@ public function testUpdateAccountEnableNoConnection(): void {
$mailAccountMapper = $this->serviceMock->getParameter('mailAccountMapper');
$mailAccountMapper->expects($this->once())
->method('find')
- ->with('1', 2)
+ ->with($this->userId, 2)
->willReturn(new MailAccount());
$sieveClientFactory = $this->serviceMock->getParameter('sieveClientFactory');
@@ -120,7 +126,7 @@ public function testGetActiveScript(): void {
$sieveService = $this->serviceMock->getParameter('sieveService');
$sieveService->expects($this->once())
->method('getActiveScript')
- ->with('1', 2)
+ ->with($this->userId, 2)
->willReturn(new NamedSieveScript('nextcloud', '# foo bar'));
$response = $this->sieveController->getActiveScript(2);
@@ -133,7 +139,11 @@ public function testUpdateActiveScript(): void {
$sieveService = $this->serviceMock->getParameter('sieveService');
$sieveService->expects($this->once())
->method('updateActiveScript')
- ->with('1', 2, 'sieve script');
+ ->with($this->userId, 2, 'sieve script');
+ $this->serviceMock->getParameter('delegationService')
+ ->expects($this->once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId updated the active sieve script for account <2> on behalf of $this->userId");
$response = $this->sieveController->updateActiveScript(2, 'sieve script');
diff --git a/tests/Unit/Controller/ThreadControllerTest.php b/tests/Unit/Controller/ThreadControllerTest.php
index 1dcf67c695..2df5353ee9 100644
--- a/tests/Unit/Controller/ThreadControllerTest.php
+++ b/tests/Unit/Controller/ThreadControllerTest.php
@@ -127,6 +127,9 @@ public function testMoveInbox(): void {
$this->mailManager
->expects(self::once())
->method('moveThread');
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId moved thread <{$message->getId()}> to mailbox <{$dstMailbox->getId()}> on behalf of $this->userId");
$response = $this->controller->move($message->getId(), $dstMailbox->getId());
@@ -203,6 +206,9 @@ public function testDeleteInbox(): void {
$this->mailManager
->expects(self::once())
->method('deleteThread');
+ $this->delegationService->expects(self::once())
+ ->method('logDelegatedAction')
+ ->with($this->userId, $this->userId, "$this->userId deleted thread <{$message->getId()}> on behalf of $this->userId");
$response = $this->controller->delete(300);
diff --git a/tests/Unit/Service/DelegationServiceTest.php b/tests/Unit/Service/DelegationServiceTest.php
index 14b84275e3..cc5e1d8d68 100644
--- a/tests/Unit/Service/DelegationServiceTest.php
+++ b/tests/Unit/Service/DelegationServiceTest.php
@@ -24,8 +24,10 @@
use OCA\Mail\Service\DelegationService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\Log\Audit\CriticalActionPerformedEvent;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use PHPUnit\Framework\MockObject\MockObject;
@@ -41,6 +43,7 @@ class DelegationServiceTest extends TestCase {
private IUserManager&MockObject $userManager;
private IManager&MockObject $notificationManager;
private ITimeFactory&MockObject $timeFactory;
+ private IEventDispatcher&MockObject $eventDispatcher;
private LoggerInterface&MockObject $logger;
private DelegationService $service;
@@ -58,6 +61,7 @@ protected function setUp(): void {
$this->userManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(IManager::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->service = new DelegationService(
@@ -70,6 +74,7 @@ protected function setUp(): void {
$this->userManager,
$this->notificationManager,
$this->timeFactory,
+ $this->eventDispatcher,
$this->logger,
);
@@ -397,4 +402,20 @@ public function testUnDelegateSendsRevokedNotification(): void {
$this->service->unDelegate($this->account, 'delegatee', 'owner');
}
+
+ public function testLogDelegatedActionDispatchesEvent(): void {
+ $this->eventDispatcher->expects($this->once())
+ ->method('dispatchTyped')
+ ->with($this->callback(fn ($event) => $event instanceof CriticalActionPerformedEvent
+ && $event->getLogMessage() === 'delegatee performed an action on behalf of owner'));
+
+ $this->service->logDelegatedAction('delegatee', 'owner', 'delegatee performed an action on behalf of owner');
+ }
+
+ public function testLogDelegatedActionSkipsWhenNotDelegated(): void {
+ $this->eventDispatcher->expects($this->never())
+ ->method('dispatchTyped');
+
+ $this->service->logDelegatedAction('owner', 'owner', 'owner performed an action on their own account');
+ }
}
From c44f12b2f294d04cac1c73b41b68d6f9ce8e9af1 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Tue, 2 Jun 2026 16:34:39 +0200
Subject: [PATCH 071/228] fix(ui): restore isSubscribed getter on mailbox
update
updateMailboxMutation replaced the mailbox object with the server
response, losing the Object.defineProperty getter for isSubscribed
(originally added in addMailboxToState). Without the getter,
isSubscribed became undefined after any patch, causing
NcActionCheckbox to re-emit update:checked and trigger an
unintended subscription change.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/store/mainStore/actions.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/store/mainStore/actions.js b/src/store/mainStore/actions.js
index bc6df484b2..055a71b9c3 100644
--- a/src/store/mainStore/actions.js
+++ b/src/store/mainStore/actions.js
@@ -1956,6 +1956,11 @@ export default function mainStoreActions() {
updateMailboxMutation({ mailbox }) {
const account = this.accountsUnmapped[mailbox.accountId]
transformMailboxName(account, mailbox)
+ Object.defineProperty(mailbox, 'isSubscribed', {
+ get() {
+ return this.attributes?.includes('\\subscribed') ?? false
+ },
+ })
Vue.set(this.mailboxes, mailbox.databaseId, mailbox)
},
removeMailboxMutation({ id }) {
From b2bbd4e29f13b774bacb963bedc44e4e6c2911a6 Mon Sep 17 00:00:00 2001
From: greta
Date: Wed, 3 Jun 2026 12:41:51 +0200
Subject: [PATCH 072/228] fix: deleting a message should move the focus one
below
Signed-off-by: greta
---
src/components/Mailbox.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue
index bbaaf8c1c6..01c957e455 100644
--- a/src/components/Mailbox.vue
+++ b/src/components/Mailbox.vue
@@ -559,7 +559,7 @@ export default {
return
}
- const next = this.envelopes[idx === 0 ? 1 : idx - 1]
+ const next = this.envelopes[idx + 1] ?? this.envelopes[idx - 1]
if (!next) {
logger.debug('no next/previous envelope, not navigating')
return
From 3cf70a14c33152afd8e050f07438a6cca7b6c67e Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 3 Jun 2026 13:58:30 +0200
Subject: [PATCH 073/228] chore(agents): tell Claude to look at AGENTS.md
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.nextcloudignore | 1 +
CLAUDE.md | 1 +
REUSE.toml | 6 ++++++
3 files changed, 8 insertions(+)
create mode 100644 CLAUDE.md
diff --git a/.nextcloudignore b/.nextcloudignore
index 4605780a89..02c80b50fd 100644
--- a/.nextcloudignore
+++ b/.nextcloudignore
@@ -4,6 +4,7 @@
/babel.config.js
/.babelrc
/build
+CLAUDE.md
codecov.yml
/.coderabbit.yaml
/composer.*
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000000..43c994c2d3
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1 @@
+@AGENTS.md
diff --git a/REUSE.toml b/REUSE.toml
index a54195f80c..b39e489efc 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -5,6 +5,12 @@ SPDX-PackageName = "mail"
SPDX-PackageSupplier = "Nextcloud "
SPDX-PackageDownloadLocation = "https://github.com/nextcloud/mail"
+[[annotations]]
+path = "CLAUDE.md"
+precedence = "aggregate"
+SPDX-FileCopyrightText = "2026 Nextcloud GmbH and Nextcloud contributors"
+SPDX-License-Identifier = "AGPL-3.0-or-later"
+
[[annotations]]
path = ["l10n/**.js", "l10n/**.json", "js/**.js.map", "js/**.js"]
precedence = "aggregate"
From 57c1d41b60064016f92ad2f79047dcbb8d177e51 Mon Sep 17 00:00:00 2001
From: Hamza
Date: Wed, 3 Jun 2026 17:12:06 +0200
Subject: [PATCH 074/228] fix(delegation): missing mailbox id in audit log
Signed-off-by: Hamza
---
lib/Controller/MailboxesController.php | 2 +-
tests/Unit/Controller/MailboxesControllerTest.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/Controller/MailboxesController.php b/lib/Controller/MailboxesController.php
index 06962b07a0..e866977726 100644
--- a/lib/Controller/MailboxesController.php
+++ b/lib/Controller/MailboxesController.php
@@ -126,7 +126,7 @@ public function patch(int $id,
$mailbox,
$name
);
- $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId changed mailbox: id 's name to $name on behalf of $effectiveUserId");
+ $this->delegationService->logDelegatedAction($this->currentUserId, $effectiveUserId, "$this->currentUserId changed mailbox: $id's name to $name on behalf of $effectiveUserId");
}
if ($subscribed !== null) {
$mailbox = $this->mailManager->updateSubscription(
diff --git a/tests/Unit/Controller/MailboxesControllerTest.php b/tests/Unit/Controller/MailboxesControllerTest.php
index e25b3d7e30..8531b024af 100644
--- a/tests/Unit/Controller/MailboxesControllerTest.php
+++ b/tests/Unit/Controller/MailboxesControllerTest.php
@@ -161,7 +161,7 @@ public function testPatchRenameLogsDelegatedAction(): void {
->willReturn($mailbox);
$this->delegationService->expects($this->once())
->method('logDelegatedAction')
- ->with($this->userId, $this->userId, "$this->userId changed mailbox: id 's name to renamed on behalf of $this->userId");
+ ->with($this->userId, $this->userId, "$this->userId changed mailbox: {$mailboxId}'s name to renamed on behalf of $this->userId");
$response = $this->controller->patch($mailboxId, 'renamed');
From fe607453a5a320e8324e1c81a2c6f353bde4917a Mon Sep 17 00:00:00 2001
From: greta
Date: Wed, 3 Jun 2026 13:36:17 +0200
Subject: [PATCH 075/228] feat: add ai hint on reply with meeting when ai is
used
Signed-off-by: greta
---
src/components/EventModal.vue | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/components/EventModal.vue b/src/components/EventModal.vue
index d81fbe5f62..670f3ed646 100644
--- a/src/components/EventModal.vue
+++ b/src/components/EventModal.vue
@@ -240,9 +240,13 @@ export default {
try {
this.generatingData = true
- const { summary, description } = await generateEventData(this.envelope.databaseId)
+ const result = await generateEventData(this.envelope.databaseId)
+ if (!result) {
+ return
+ }
+ const { summary, description } = result
this.eventTitle = summary
- this.description = description
+ this.description = description + '\n\n' + t('mail', 'This description was generated by AI.')
} finally {
this.generatingData = false
}
From 04d1a48007a67902441f8d65e3e133de19a67e2f Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Sat, 6 Jun 2026 01:32:31 +0000
Subject: [PATCH 076/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/lt_LT.js | 26 +++++++++++++-------------
l10n/lt_LT.json | 26 +++++++++++++-------------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index 35065187b5..3abfd0de84 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -198,8 +198,8 @@ OC.L10N.register(
"Ok" : "Gerai",
"Automatically create tentative appointments in calendar" : "Automatiškai kurti preliminarius susitikimus kalendoriuje",
"No certificate" : "Sertifikato nėra",
- "Certificate updated" : "Liudijimas atnaujintas",
- "Could not update certificate" : "Nepavyko atnaujinti liudijimo",
+ "Certificate updated" : "Sertifikatas atnaujintas",
+ "Could not update certificate" : "Nepavyko atnaujinti sertifikato",
"{commonName} - Valid until {expiryDate}" : "{commonName} – Galioja iki {expiryDate}",
"Select an alias" : "Pasirinkite slapyvardį",
"Select certificates" : "Pasirinkti sertifikatus",
@@ -227,7 +227,7 @@ OC.L10N.register(
"Subject" : "Tema",
"Subject …" : "Pasirinkti ...",
"This message came from a noreply address so your reply will probably not be read." : "Šis laiškas atėjo iš adreso, kuris nėra skirtas atsakyti, taigi jūsų atsakymas, tikriausiai, nebus perskaitytas.",
- "The following recipients do not have a S/MIME certificate: {recipients}." : "Šie gavėjai neturi S/MIME liudijimo: {recipients}.",
+ "The following recipients do not have a S/MIME certificate: {recipients}." : "Šie gavėjai neturi S/MIME sertifikato: {recipients}.",
"The following recipients do not have a PGP key: {recipients}." : "Šie gavėjai neturi PGP rakto: {recipients}.",
"Write message …" : "Rašyti žinutę ...",
"Saving draft …" : "Išsaugomas juodraštis …",
@@ -843,20 +843,20 @@ OC.L10N.register(
"With the settings above, the app will create account settings in the following way:" : "Naudodama aukščiau esančius nustatymus, programėlė sukurs paskyrai nustatymus štai tokiu būdu: ",
"The provided PKCS #12 certificate must contain at least one certificate and exactly one private key." : "Pateiktame PKCS #12 sertifikate turi būti bent vienas sertifikatas ir lygiai vienas privatusis raktas.",
"Failed to import the certificate. Please check the password." : "Nepavyko importuoti sertifikato. Patikrinkite slaptažodį.",
- "Certificate imported successfully" : "Liudijimas sėkmingai importuotas",
+ "Certificate imported successfully" : "Sertifikatas sėkmingai importuotas",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nepavyko importuoti sertifikato. Įsitikinkite, kad privatusis raktas atitinka sertifikatą ir nėra apsaugotas slaptafraze.",
- "Failed to import the certificate" : "Nepavyko importuoti liudijimo",
- "Import S/MIME certificate" : "Importuoti S/MIME liudijimą",
- "S/MIME certificates" : "S/MIME liudijimai",
- "Certificate name" : "Liudijimo pavadinimas",
+ "Failed to import the certificate" : "Nepavyko importuoti sertifikato",
+ "Import S/MIME certificate" : "Importuoti S/MIME sertifikatą",
+ "S/MIME certificates" : "S/MIME sertifikatai",
+ "Certificate name" : "Sertifikato pavadinimas",
"E-mail address" : "El. pašto adresas",
"Valid until" : "Galioja iki",
- "Delete certificate" : "Ištrinti liudijimą",
+ "Delete certificate" : "Ištrinti sertifikatą",
"No certificate imported yet" : "Dar neimportuotas joks sertifikatas",
- "Import certificate" : "Importuoti liudijimą",
- "PKCS #12 Certificate" : "PKCS #12 liudijimas",
- "PEM Certificate" : "PEM liudijimas",
- "Certificate" : "Liudijimas",
+ "Import certificate" : "Importuoti sertifikatą",
+ "PKCS #12 Certificate" : "PKCS #12 sertifikatas",
+ "PEM Certificate" : "PEM sertifikatas",
+ "Certificate" : "Sertifikatas",
"Private key (optional)" : "Privatus raktas (neprivaloma)",
"The private key is only required if you intend to send signed and encrypted emails using this certificate." : "Privatusis raktas reikalingas tik tuo atveju, jei ketinate siųsti pasirašytus ir užšifruotus el. laiškus naudodami šį sertifikatą.",
"Submit" : "Pateikti",
diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json
index 70017575c9..062b2b68c3 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -196,8 +196,8 @@
"Ok" : "Gerai",
"Automatically create tentative appointments in calendar" : "Automatiškai kurti preliminarius susitikimus kalendoriuje",
"No certificate" : "Sertifikato nėra",
- "Certificate updated" : "Liudijimas atnaujintas",
- "Could not update certificate" : "Nepavyko atnaujinti liudijimo",
+ "Certificate updated" : "Sertifikatas atnaujintas",
+ "Could not update certificate" : "Nepavyko atnaujinti sertifikato",
"{commonName} - Valid until {expiryDate}" : "{commonName} – Galioja iki {expiryDate}",
"Select an alias" : "Pasirinkite slapyvardį",
"Select certificates" : "Pasirinkti sertifikatus",
@@ -225,7 +225,7 @@
"Subject" : "Tema",
"Subject …" : "Pasirinkti ...",
"This message came from a noreply address so your reply will probably not be read." : "Šis laiškas atėjo iš adreso, kuris nėra skirtas atsakyti, taigi jūsų atsakymas, tikriausiai, nebus perskaitytas.",
- "The following recipients do not have a S/MIME certificate: {recipients}." : "Šie gavėjai neturi S/MIME liudijimo: {recipients}.",
+ "The following recipients do not have a S/MIME certificate: {recipients}." : "Šie gavėjai neturi S/MIME sertifikato: {recipients}.",
"The following recipients do not have a PGP key: {recipients}." : "Šie gavėjai neturi PGP rakto: {recipients}.",
"Write message …" : "Rašyti žinutę ...",
"Saving draft …" : "Išsaugomas juodraštis …",
@@ -841,20 +841,20 @@
"With the settings above, the app will create account settings in the following way:" : "Naudodama aukščiau esančius nustatymus, programėlė sukurs paskyrai nustatymus štai tokiu būdu: ",
"The provided PKCS #12 certificate must contain at least one certificate and exactly one private key." : "Pateiktame PKCS #12 sertifikate turi būti bent vienas sertifikatas ir lygiai vienas privatusis raktas.",
"Failed to import the certificate. Please check the password." : "Nepavyko importuoti sertifikato. Patikrinkite slaptažodį.",
- "Certificate imported successfully" : "Liudijimas sėkmingai importuotas",
+ "Certificate imported successfully" : "Sertifikatas sėkmingai importuotas",
"Failed to import the certificate. Please make sure that the private key matches the certificate and is not protected by a passphrase." : "Nepavyko importuoti sertifikato. Įsitikinkite, kad privatusis raktas atitinka sertifikatą ir nėra apsaugotas slaptafraze.",
- "Failed to import the certificate" : "Nepavyko importuoti liudijimo",
- "Import S/MIME certificate" : "Importuoti S/MIME liudijimą",
- "S/MIME certificates" : "S/MIME liudijimai",
- "Certificate name" : "Liudijimo pavadinimas",
+ "Failed to import the certificate" : "Nepavyko importuoti sertifikato",
+ "Import S/MIME certificate" : "Importuoti S/MIME sertifikatą",
+ "S/MIME certificates" : "S/MIME sertifikatai",
+ "Certificate name" : "Sertifikato pavadinimas",
"E-mail address" : "El. pašto adresas",
"Valid until" : "Galioja iki",
- "Delete certificate" : "Ištrinti liudijimą",
+ "Delete certificate" : "Ištrinti sertifikatą",
"No certificate imported yet" : "Dar neimportuotas joks sertifikatas",
- "Import certificate" : "Importuoti liudijimą",
- "PKCS #12 Certificate" : "PKCS #12 liudijimas",
- "PEM Certificate" : "PEM liudijimas",
- "Certificate" : "Liudijimas",
+ "Import certificate" : "Importuoti sertifikatą",
+ "PKCS #12 Certificate" : "PKCS #12 sertifikatas",
+ "PEM Certificate" : "PEM sertifikatas",
+ "Certificate" : "Sertifikatas",
"Private key (optional)" : "Privatus raktas (neprivaloma)",
"The private key is only required if you intend to send signed and encrypted emails using this certificate." : "Privatusis raktas reikalingas tik tuo atveju, jei ketinate siųsti pasirašytus ir užšifruotus el. laiškus naudodami šį sertifikatą.",
"Submit" : "Pateikti",
From b4764bea3d51e2cdcc4915747e3301b66ea3f9cd Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Sun, 7 Jun 2026 01:31:14 +0000
Subject: [PATCH 077/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/de.js | 1 +
l10n/de.json | 1 +
l10n/de_DE.js | 1 +
l10n/de_DE.json | 1 +
l10n/et_EE.js | 3 ++-
l10n/et_EE.json | 3 ++-
l10n/fa.js | 1 +
l10n/fa.json | 1 +
l10n/lt_LT.js | 1 +
l10n/lt_LT.json | 1 +
l10n/pt_BR.js | 1 +
l10n/pt_BR.json | 1 +
l10n/ru.js | 4 ++++
l10n/ru.json | 4 ++++
14 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/l10n/de.js b/l10n/de.js
index b7cf103d7e..4f2bad8350 100644
--- a/l10n/de.js
+++ b/l10n/de.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Als unwichtig markieren",
"Mark as important" : "Als wichtig markieren",
"Report this bug" : "Diesen Bug melden",
+ "This description was generated by AI." : "Diese Beschreibung wurde von einer KI erstellt.",
"Event created" : "Termin wurde erstellt",
"Could not create event" : "Termin konnte nicht erstellt werden",
"Create event" : "Termin erstellen",
diff --git a/l10n/de.json b/l10n/de.json
index ed748a04ee..8d611e08b1 100644
--- a/l10n/de.json
+++ b/l10n/de.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Als unwichtig markieren",
"Mark as important" : "Als wichtig markieren",
"Report this bug" : "Diesen Bug melden",
+ "This description was generated by AI." : "Diese Beschreibung wurde von einer KI erstellt.",
"Event created" : "Termin wurde erstellt",
"Could not create event" : "Termin konnte nicht erstellt werden",
"Create event" : "Termin erstellen",
diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index c57ba4c353..6e5380227a 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Als unwichtig markieren",
"Mark as important" : "Als wichtig markieren",
"Report this bug" : "Diesen Fehler melden",
+ "This description was generated by AI." : "Diese Beschreibung wurde von einer KI erstellt.",
"Event created" : "Termin wurde erstellt",
"Could not create event" : "Termin konnte nicht erstellt werden",
"Create event" : "Termin erstellen",
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index 1e87e0d77f..d26cdc15c6 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Als unwichtig markieren",
"Mark as important" : "Als wichtig markieren",
"Report this bug" : "Diesen Fehler melden",
+ "This description was generated by AI." : "Diese Beschreibung wurde von einer KI erstellt.",
"Event created" : "Termin wurde erstellt",
"Could not create event" : "Termin konnte nicht erstellt werden",
"Create event" : "Termin erstellen",
diff --git a/l10n/et_EE.js b/l10n/et_EE.js
index 1e434f5190..9fc2a0df27 100644
--- a/l10n/et_EE.js
+++ b/l10n/et_EE.js
@@ -36,7 +36,7 @@ OC.L10N.register(
"💌 A mail app for Nextcloud" : "💌 E-postirakendus Nextcloudi jaoks",
"**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 E-posti rakendus Nextcloudi jaoks**\n\n- **🚀 Lõiming muude Nextcloudi rakendustega!** Hetkel kontakti-, kalendri ja failirakendused, aga õige pea lisandub neid veel.\n- **📥 Mitu e-posti kontot!** Isiklik ja töökoha konto? Pole probleemi ja kauba peale saad kena ja ühise sisendposti kausta. Võid ühendada kõiki IMAP-i kasutajakontosid.\n- **🔒 Saada krüptitud e-kirju ja võta neid vastu!** Selleks on kasutusel suurepärase veebibrauseri lisamoodul [Mailvelope](https://mailvelope.com).\n- **🙈 Me ei leiuta midagi uut!** Rakendus põhineb suurepärastel [Horde](https://www.horde.org) teekidel.\n- **📬 Tahad kasutada oma serverit?** Me ei hakanud seda ise leiutama, on ju olemas [Mail-in-a-Box](https://mailinabox.email) teenus!\n\n## Tehisaru eetiline kasutaus\n\n### Prioriteediga kirjad saabuvate kirjade postkastis\n\nPositiivne lähenemine:\n* Selle mudeli treenimiseks ja järelduste tegemiseks mõeldud tarkvara on avatud lähtekoodiga.\n* Mudel luuakse ja treenitakse kohapeal, tuginedes kasutaja enda andmetele.\n* Kasutajal on juurdepääs treeningandmetele, mis võimaldab kontrollida ja parandada võimalikke eelarvamusi ning optimeerida mudeli jõudlust ja CO2-heiteid.\n\n### Jutulõngade kokkuvõtted (kui tahad kasutada)\n\n**Hinnang:** 🟢/🟡/🟠/🔴\n\nHindamine sõltub paigaldatud tekstitöötluse taustateenusest. Üksikasju vaata dokumentatsioonist, mis kirjeldab [ülevaadet hindamisest](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html).\n\nTehisaru eetilisest kasutusest Nextcloudi raames leiad [teavet meie ajaveebist](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).",
"Your session has expired. The page will be reloaded." : "Sinu sessioon on aegunud. Leht saab olema uuesti laaditud.",
- "Drafts are saved in:" : "Kirjade kavandis on salvestatud siia:",
+ "Drafts are saved in:" : "Kirjade kavandid on salvestatud siia:",
"Sent messages are saved in:" : "Saadetud kirjad on salvestatud siia:",
"Deleted messages are moved in:" : "Kustutatud kirjad on tõstetud siia:",
"Archived messages are moved in:" : "Arhiveeritud kirjad on tõstetud siia:",
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Märgi mitteoluliseks",
"Mark as important" : "Märgi oluliseks",
"Report this bug" : "Teata sellest veast",
+ "This description was generated by AI." : "See kirjeldus on koostatud tehisaru poolt.",
"Event created" : "Sündmus on loodud",
"Could not create event" : "Sündmuse loomine ei õnnestunud",
"Create event" : "Lisa sündmus",
diff --git a/l10n/et_EE.json b/l10n/et_EE.json
index 6254e580d8..f1ed386fd8 100644
--- a/l10n/et_EE.json
+++ b/l10n/et_EE.json
@@ -34,7 +34,7 @@
"💌 A mail app for Nextcloud" : "💌 E-postirakendus Nextcloudi jaoks",
"**💌 A mail app for Nextcloud**\n\n- **🚀 Integration with other Nextcloud apps!** Currently Contacts, Calendar & Files – more to come.\n- **📥 Multiple mail accounts!** Personal and company account? No problem, and a nice unified inbox. Connect any IMAP account.\n- **🔒 Send & receive encrypted mails!** Using the great [Mailvelope](https://mailvelope.com) browser extension.\n- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](https://www.horde.org) libraries.\n- **📬 Want to host your own mail server?** We do not have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!\n\n## Ethical AI Rating\n\n### Priority Inbox\n\nPositive:\n* The software for training and inferencing of this model is open source.\n* The model is created and trained on-premises based on the user's own data.\n* The training data is accessible to the user, making it possible to check or correct for bias or optimise the performance and CO2 usage.\n\n### Thread Summaries (opt-in)\n\n**Rating:** 🟢/🟡/🟠/🔴\n\nThe rating depends on the installed text processing backend. See [the rating overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) for details.\n\nLearn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/)." : "**💌 E-posti rakendus Nextcloudi jaoks**\n\n- **🚀 Lõiming muude Nextcloudi rakendustega!** Hetkel kontakti-, kalendri ja failirakendused, aga õige pea lisandub neid veel.\n- **📥 Mitu e-posti kontot!** Isiklik ja töökoha konto? Pole probleemi ja kauba peale saad kena ja ühise sisendposti kausta. Võid ühendada kõiki IMAP-i kasutajakontosid.\n- **🔒 Saada krüptitud e-kirju ja võta neid vastu!** Selleks on kasutusel suurepärase veebibrauseri lisamoodul [Mailvelope](https://mailvelope.com).\n- **🙈 Me ei leiuta midagi uut!** Rakendus põhineb suurepärastel [Horde](https://www.horde.org) teekidel.\n- **📬 Tahad kasutada oma serverit?** Me ei hakanud seda ise leiutama, on ju olemas [Mail-in-a-Box](https://mailinabox.email) teenus!\n\n## Tehisaru eetiline kasutaus\n\n### Prioriteediga kirjad saabuvate kirjade postkastis\n\nPositiivne lähenemine:\n* Selle mudeli treenimiseks ja järelduste tegemiseks mõeldud tarkvara on avatud lähtekoodiga.\n* Mudel luuakse ja treenitakse kohapeal, tuginedes kasutaja enda andmetele.\n* Kasutajal on juurdepääs treeningandmetele, mis võimaldab kontrollida ja parandada võimalikke eelarvamusi ning optimeerida mudeli jõudlust ja CO2-heiteid.\n\n### Jutulõngade kokkuvõtted (kui tahad kasutada)\n\n**Hinnang:** 🟢/🟡/🟠/🔴\n\nHindamine sõltub paigaldatud tekstitöötluse taustateenusest. Üksikasju vaata dokumentatsioonist, mis kirjeldab [ülevaadet hindamisest](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html).\n\nTehisaru eetilisest kasutusest Nextcloudi raames leiad [teavet meie ajaveebist](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).",
"Your session has expired. The page will be reloaded." : "Sinu sessioon on aegunud. Leht saab olema uuesti laaditud.",
- "Drafts are saved in:" : "Kirjade kavandis on salvestatud siia:",
+ "Drafts are saved in:" : "Kirjade kavandid on salvestatud siia:",
"Sent messages are saved in:" : "Saadetud kirjad on salvestatud siia:",
"Deleted messages are moved in:" : "Kustutatud kirjad on tõstetud siia:",
"Archived messages are moved in:" : "Arhiveeritud kirjad on tõstetud siia:",
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Märgi mitteoluliseks",
"Mark as important" : "Märgi oluliseks",
"Report this bug" : "Teata sellest veast",
+ "This description was generated by AI." : "See kirjeldus on koostatud tehisaru poolt.",
"Event created" : "Sündmus on loodud",
"Could not create event" : "Sündmuse loomine ei õnnestunud",
"Create event" : "Lisa sündmus",
diff --git a/l10n/fa.js b/l10n/fa.js
index 85663cdff2..dea7c638fb 100644
--- a/l10n/fa.js
+++ b/l10n/fa.js
@@ -261,6 +261,7 @@ OC.L10N.register(
"You are not allowed to move this message to the archive folder and/or delete this message from the current folder" : "You are not allowed to move this message to the archive folder and/or delete this message from the current folder",
"Last hour" : "Last hour",
"Today" : "امروز.",
+ "Yesterday" : "دیروز",
"Last week" : "هفته گذشته",
"Last month" : "ماه گذشته",
"Choose target folder" : "پوشهٔ هدف را انتخاب کنید",
diff --git a/l10n/fa.json b/l10n/fa.json
index a5ba5fffb7..01334f2c05 100644
--- a/l10n/fa.json
+++ b/l10n/fa.json
@@ -259,6 +259,7 @@
"You are not allowed to move this message to the archive folder and/or delete this message from the current folder" : "You are not allowed to move this message to the archive folder and/or delete this message from the current folder",
"Last hour" : "Last hour",
"Today" : "امروز.",
+ "Yesterday" : "دیروز",
"Last week" : "هفته گذشته",
"Last month" : "ماه گذشته",
"Choose target folder" : "پوشهٔ هدف را انتخاب کنید",
diff --git a/l10n/lt_LT.js b/l10n/lt_LT.js
index 3abfd0de84..fd22943ee4 100644
--- a/l10n/lt_LT.js
+++ b/l10n/lt_LT.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Žymėti kaip nesvarbų",
"Mark as important" : "Žymėti kaip svarbų",
"Report this bug" : "Pranešti apie šią klaidą",
+ "This description was generated by AI." : "Šį aprašymą sugeneravo DI.",
"Event created" : "Įvykis sukurtas",
"Could not create event" : "Nepavyko sukurti įvykio",
"Create event" : "Sukurti įvykį",
diff --git a/l10n/lt_LT.json b/l10n/lt_LT.json
index 062b2b68c3..b3bdf2f874 100644
--- a/l10n/lt_LT.json
+++ b/l10n/lt_LT.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Žymėti kaip nesvarbų",
"Mark as important" : "Žymėti kaip svarbų",
"Report this bug" : "Pranešti apie šią klaidą",
+ "This description was generated by AI." : "Šį aprašymą sugeneravo DI.",
"Event created" : "Įvykis sukurtas",
"Could not create event" : "Nepavyko sukurti įvykio",
"Create event" : "Sukurti įvykį",
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index f0d416faaa..f9f26e5866 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Marcar como não importante",
"Mark as important" : "Marcar como importante",
"Report this bug" : "Reportar este erro",
+ "This description was generated by AI." : "Esta descrição foi gerada por IA.",
"Event created" : "Evento criado",
"Could not create event" : "Não foi possível criar o evento",
"Create event" : "Criar evento",
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index c3e06c4021..3a54ed9692 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Marcar como não importante",
"Mark as important" : "Marcar como importante",
"Report this bug" : "Reportar este erro",
+ "This description was generated by AI." : "Esta descrição foi gerada por IA.",
"Event created" : "Evento criado",
"Could not create event" : "Não foi possível criar o evento",
"Create event" : "Criar evento",
diff --git a/l10n/ru.js b/l10n/ru.js
index 81d008fc99..aa9c913577 100644
--- a/l10n/ru.js
+++ b/l10n/ru.js
@@ -248,6 +248,10 @@ OC.L10N.register(
"Untitled message" : "Сообщение без названия",
"Confirm" : "Подтвердить",
"Revoke" : "Отозвать",
+ "Delegation" : " Делегирование",
+ "Revoke access" : "Отозвать доступ",
+ "Add delegate" : "Добавить делегата",
+ "Revoke access?" : "Отозвать доступ?",
"Tag: {name} deleted" : "Тег: {name} удален",
"An error occurred, unable to delete the tag." : "Произошла ошибка, не удалось удалить тег.",
"The tag will be deleted from all messages." : "Тег будет удален из всех сообщений.",
diff --git a/l10n/ru.json b/l10n/ru.json
index cef5d3f65a..9bfa01d63a 100644
--- a/l10n/ru.json
+++ b/l10n/ru.json
@@ -246,6 +246,10 @@
"Untitled message" : "Сообщение без названия",
"Confirm" : "Подтвердить",
"Revoke" : "Отозвать",
+ "Delegation" : " Делегирование",
+ "Revoke access" : "Отозвать доступ",
+ "Add delegate" : "Добавить делегата",
+ "Revoke access?" : "Отозвать доступ?",
"Tag: {name} deleted" : "Тег: {name} удален",
"An error occurred, unable to delete the tag." : "Произошла ошибка, не удалось удалить тег.",
"The tag will be deleted from all messages." : "Тег будет удален из всех сообщений.",
From f9f5dde5be1e759e30cebfe02d5022402c3b1919 Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Mon, 8 Jun 2026 01:34:56 +0000
Subject: [PATCH 078/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/fi.js | 2 ++
l10n/fi.json | 2 ++
l10n/ga.js | 1 +
l10n/ga.json | 1 +
l10n/uk.js | 4 ++++
l10n/uk.json | 4 ++++
6 files changed, 14 insertions(+)
diff --git a/l10n/fi.js b/l10n/fi.js
index ee28e8db6f..7cf6bc4b8a 100644
--- a/l10n/fi.js
+++ b/l10n/fi.js
@@ -185,6 +185,8 @@ OC.L10N.register(
"Close composer" : "Sulje lähetysikkuna",
"Confirm" : "Vahvista",
"Revoke" : "Peru oikeus",
+ "Revoke access" : "Peru pääsyoikeus",
+ "Revoke access?" : "Perutaanko pääsyoikeus?",
"Plain text" : "Raakateksti",
"Rich text" : "Rikas teksti",
"No messages in this folder" : "Tässä kansiossa ei ole viestejä",
diff --git a/l10n/fi.json b/l10n/fi.json
index efecce2dbf..4035484223 100644
--- a/l10n/fi.json
+++ b/l10n/fi.json
@@ -183,6 +183,8 @@
"Close composer" : "Sulje lähetysikkuna",
"Confirm" : "Vahvista",
"Revoke" : "Peru oikeus",
+ "Revoke access" : "Peru pääsyoikeus",
+ "Revoke access?" : "Perutaanko pääsyoikeus?",
"Plain text" : "Raakateksti",
"Rich text" : "Rikas teksti",
"No messages in this folder" : "Tässä kansiossa ei ole viestejä",
diff --git a/l10n/ga.js b/l10n/ga.js
index f2b21a1779..f2988859a3 100644
--- a/l10n/ga.js
+++ b/l10n/ga.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Marcáil mar neamhthábhachtach",
"Mark as important" : "Marcáil chomh tábhachtach",
"Report this bug" : "Tuairiscigh an fabht seo",
+ "This description was generated by AI." : "Gineadh an cur síos seo le hintleacht shaorga.",
"Event created" : "Imeacht cruthaithe",
"Could not create event" : "Níorbh fhéidir imeacht a chruthú",
"Create event" : "Cruthaigh imeacht",
diff --git a/l10n/ga.json b/l10n/ga.json
index 2c581d672a..897651b2f9 100644
--- a/l10n/ga.json
+++ b/l10n/ga.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Marcáil mar neamhthábhachtach",
"Mark as important" : "Marcáil chomh tábhachtach",
"Report this bug" : "Tuairiscigh an fabht seo",
+ "This description was generated by AI." : "Gineadh an cur síos seo le hintleacht shaorga.",
"Event created" : "Imeacht cruthaithe",
"Could not create event" : "Níorbh fhéidir imeacht a chruthú",
"Create event" : "Cruthaigh imeacht",
diff --git a/l10n/uk.js b/l10n/uk.js
index 7ac32a443c..1d69114037 100644
--- a/l10n/uk.js
+++ b/l10n/uk.js
@@ -219,6 +219,10 @@ OC.L10N.register(
"Close composer" : "Закрити редактор",
"Confirm" : "Підтвердити",
"Revoke" : "Відкликати",
+ "Delegation" : "Делегування",
+ "Revoke access" : "Відкликати доступ",
+ "Add delegate" : "Додати делегата",
+ "Revoke access?" : "Відкликати доступ?",
"Tag: {name} deleted" : "Мітка: {name} вилучено",
"An error occurred, unable to delete the tag." : "Пимилка під час вилучення мітки.",
"The tag will be deleted from all messages." : "Мітку буде вилучено зі всіх листів.",
diff --git a/l10n/uk.json b/l10n/uk.json
index 29cf5bcc8b..afef9fce6e 100644
--- a/l10n/uk.json
+++ b/l10n/uk.json
@@ -217,6 +217,10 @@
"Close composer" : "Закрити редактор",
"Confirm" : "Підтвердити",
"Revoke" : "Відкликати",
+ "Delegation" : "Делегування",
+ "Revoke access" : "Відкликати доступ",
+ "Add delegate" : "Додати делегата",
+ "Revoke access?" : "Відкликати доступ?",
"Tag: {name} deleted" : "Мітка: {name} вилучено",
"An error occurred, unable to delete the tag." : "Пимилка під час вилучення мітки.",
"The tag will be deleted from all messages." : "Мітку буде вилучено зі всіх листів.",
From c6603eec1eac1955ffc99cbe84ef838503ac511c Mon Sep 17 00:00:00 2001
From: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Date: Sat, 6 Jun 2026 14:45:10 +0200
Subject: [PATCH 079/228] chore(lint): Reduce linting time with PHP 8.3+
Signed-off-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
---
composer.json | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index ac760bbf23..fe7c3946f0 100644
--- a/composer.json
+++ b/composer.json
@@ -64,7 +64,12 @@
"scripts": {
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
- "lint": "find . -name \\*.php -not -path './vendor*/*' -not -path './tests/stubs/*' -print0 | xargs -0 -n1 php -l",
+ "lint": [
+ "@lint-8.2-or-earlier",
+ "@lint-8.3-or-later"
+ ],
+ "lint-8.2-or-earlier": "[ $(php -r \"echo PHP_VERSION_ID;\") -ge 80300 ] || find . -type f -name '*.php' -not -path './vendor/*' -not -path './vendor-bin/*' -not -path './tests/stubs/*' -print0 | xargs -0 -n1 -P$(nproc) php -l",
+ "lint-8.3-or-later": "[ $(php -r \"echo PHP_VERSION_ID;\") -lt 80300 ] || find . -type f -name '*.php' -not -path './vendor/*' -not -path './vendor-bin/*' -not -path './tests/stubs/*' -print0 | xargs -0 -n200 -P$(nproc) php -l",
"psalm": "psalm.phar",
"psalm:fix": "psalm.phar --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
"post-install-cmd": [
From 97e5a2a5ca1656a14409cd0cae3188149d812c9b Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 8 Jun 2026 17:08:19 +0000
Subject: [PATCH 080/228] chore(deps): bump codecov/codecov-action action from
v6.0.1 to v6.0.2 (#13040)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/test.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 081f5b22d2..4da8904f4b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -53,7 +53,7 @@ jobs:
env:
XDEBUG_MODE: ${{ matrix.coverage && 'coverage' || 'off' }}
- name: Report coverage
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
+ uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6.0.2
if: ${{ !cancelled() && matrix.coverage }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
@@ -198,7 +198,7 @@ jobs:
if: ${{ always() }}
run: cat nextcloud/data/mail-*-*-imap.log
- name: Report coverage
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
+ uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6.0.2
if: ${{ !cancelled() && matrix.coverage }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
From 8838e8866c818641dba21f53466bb6c50f4b40aa Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 8 Jun 2026 17:21:06 +0000
Subject: [PATCH 081/228] chore(deps): bump codecov/codecov-action action from
v6.0.2 to v7
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/test.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4da8904f4b..d1993d0b59 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -53,7 +53,7 @@ jobs:
env:
XDEBUG_MODE: ${{ matrix.coverage && 'coverage' || 'off' }}
- name: Report coverage
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6.0.2
+ uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
if: ${{ !cancelled() && matrix.coverage }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
@@ -198,7 +198,7 @@ jobs:
if: ${{ always() }}
run: cat nextcloud/data/mail-*-*-imap.log
- name: Report coverage
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6.0.2
+ uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
if: ${{ !cancelled() && matrix.coverage }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
From c9ee3732149ae62141e093633bca6c93a50eef1d Mon Sep 17 00:00:00 2001
From: Nextcloud bot
Date: Tue, 9 Jun 2026 01:31:31 +0000
Subject: [PATCH 082/228] fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot
---
l10n/tr.js | 1 +
l10n/tr.json | 1 +
l10n/zh_TW.js | 1 +
l10n/zh_TW.json | 1 +
4 files changed, 4 insertions(+)
diff --git a/l10n/tr.js b/l10n/tr.js
index 0ca0ad3b8a..a4545aad8b 100644
--- a/l10n/tr.js
+++ b/l10n/tr.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "Önemsiz olarak işaretle",
"Mark as important" : "Önemli olarak işaretle",
"Report this bug" : "Bu hatayı bildirin",
+ "This description was generated by AI." : "Bu açıklama yapay zeka tarafından oluşturulmuştur.",
"Event created" : "Etkinlik oluşturuldu",
"Could not create event" : "Etkinlik oluşturulamadı",
"Create event" : "Etkinlik oluştur",
diff --git a/l10n/tr.json b/l10n/tr.json
index 347038da1d..71c6a8c182 100644
--- a/l10n/tr.json
+++ b/l10n/tr.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "Önemsiz olarak işaretle",
"Mark as important" : "Önemli olarak işaretle",
"Report this bug" : "Bu hatayı bildirin",
+ "This description was generated by AI." : "Bu açıklama yapay zeka tarafından oluşturulmuştur.",
"Event created" : "Etkinlik oluşturuldu",
"Could not create event" : "Etkinlik oluşturulamadı",
"Create event" : "Etkinlik oluştur",
diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js
index 757f4bbe31..4149a7036f 100644
--- a/l10n/zh_TW.js
+++ b/l10n/zh_TW.js
@@ -350,6 +350,7 @@ OC.L10N.register(
"Mark as unimportant" : "標記為不重要",
"Mark as important" : "標記為重要",
"Report this bug" : "回報此臭蟲",
+ "This description was generated by AI." : "此描述由人工智慧產生。",
"Event created" : "已建立事件",
"Could not create event" : "無法建立活動",
"Create event" : "建立事件",
diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json
index 3ec1375e6e..9dea4f6b32 100644
--- a/l10n/zh_TW.json
+++ b/l10n/zh_TW.json
@@ -348,6 +348,7 @@
"Mark as unimportant" : "標記為不重要",
"Mark as important" : "標記為重要",
"Report this bug" : "回報此臭蟲",
+ "This description was generated by AI." : "此描述由人工智慧產生。",
"Event created" : "已建立事件",
"Could not create event" : "無法建立活動",
"Create event" : "建立事件",
From 47820ad24482622c1c9e5593186a76ccd09595a0 Mon Sep 17 00:00:00 2001
From: Grigory Vodyanov
Date: Mon, 8 Jun 2026 15:33:15 +0200
Subject: [PATCH 083/228] fix: mail printing
Signed-off-by: Grigory Vodyanov
---
src/components/MessageHTMLBody.vue | 14 ++-
src/components/Thread.vue | 138 ++++++++++++++++-------------
2 files changed, 91 insertions(+), 61 deletions(-)
diff --git a/src/components/MessageHTMLBody.vue b/src/components/MessageHTMLBody.vue
index 7e538df71a..cbb10eb859 100644
--- a/src/components/MessageHTMLBody.vue
+++ b/src/components/MessageHTMLBody.vue
@@ -100,6 +100,7 @@ export default {
isSenderTrusted: this.message.isSenderTrusted,
needsTranslation: false,
enabledFreePrompt: loadState('mail', 'llm_freeprompt_available', false),
+ printOriginalHeight: null,
}
},
@@ -115,6 +116,7 @@ export default {
beforeMount() {
scout.on('beforeprint', this.onBeforePrint)
+ scout.on('afterprint', this.onAfterPrint)
},
async mounted() {
@@ -131,6 +133,7 @@ export default {
beforeUnmount() {
scout.off('beforeprint', this.onBeforePrint)
+ scout.off('afterprint', this.onAfterPrint)
this.$refs.iframe.iFrameResizer.close()
},
@@ -154,7 +157,16 @@ export default {
},
onBeforePrint() {
- // this.$refs.iframe.style.setProperty('height', `${this.getIframeDoc().body.scrollHeight}px`, 'important')
+ const iframe = this.$refs.iframe
+ this.printOriginalHeight = iframe.style.height
+ iframe.style.setProperty('height', `${this.getIframeDoc().body.scrollHeight}px`, 'important')
+ },
+
+ onAfterPrint() {
+ if (this.printOriginalHeight !== null) {
+ this.$refs.iframe.style.height = this.printOriginalHeight
+ this.printOriginalHeight = null
+ }
},
displayIframe() {
diff --git a/src/components/Thread.vue b/src/components/Thread.vue
index 91835960f4..bd43a01f0d 100644
--- a/src/components/Thread.vue
+++ b/src/components/Thread.vue
@@ -135,6 +135,20 @@ export default {
return thread[0].subject || this.t('mail', 'No subject')
},
+ threadParticipants() {
+ const seen = new Set()
+ return this.thread.flatMap((envelope) => [
+ ...(envelope.from ?? []),
+ ...(envelope.to ?? []),
+ ]).filter(({ email }) => {
+ if (seen.has(email)) {
+ return false
+ }
+ seen.add(email)
+ return true
+ })
+ },
+
showSummaryBox() {
return this.thread.length > 2 && this.enabledThreadSummary && !this.summaryError
},
@@ -267,81 +281,84 @@ export default {
if ((event.ctrlKey || event.metaKey) && event.key === 'p') {
event.preventDefault()
- this.thread.forEach((thread) => {
- if (!this.expandedThreads.includes(thread.databaseId)) {
- this.expandedThreads.push(thread.databaseId)
- }
- })
+ try {
+ this.thread.forEach((thread) => {
+ if (!this.expandedThreads.includes(thread.databaseId)) {
+ this.expandedThreads.push(thread.databaseId)
+ }
+ })
- while (true) {
- if (this.loadedThreads === this.thread.length) {
- break
+ while (true) {
+ if (this.loadedThreads === this.thread.length) {
+ break
+ }
+ await new Promise((resolve) => setTimeout(resolve, 100))
}
- await new Promise((resolve) => setTimeout(resolve, 100))
- }
- const virtualIframe = document.createElement('iframe')
- virtualIframe.style.display = 'none'
- document.body.appendChild(virtualIframe)
- const virtualIframeDocument = virtualIframe.contentDocument || virtualIframe.contentWindow.document
- virtualIframeDocument.open()
- virtualIframeDocument.write(`${t('mail', 'Print')}`)
- virtualIframeDocument.close()
+ const virtualIframe = document.createElement('iframe')
+ virtualIframe.style.position = 'absolute'
+ document.body.appendChild(virtualIframe)
+ const virtualIframeDocument = virtualIframe.contentDocument || virtualIframe.contentWindow.document
+ virtualIframeDocument.open()
+ virtualIframeDocument.write(`${t('mail', 'Print')}`)
+ virtualIframeDocument.close()
- virtualIframeDocument.body.appendChild(this.addThreadInfo(virtualIframeDocument))
+ virtualIframeDocument.body.appendChild(this.addThreadInfo(virtualIframeDocument))
- const messageContainers = document.querySelectorAll('#message-container')
- for (const [index, messageContainer] of messageContainers.entries()) {
- const iframe = messageContainer.querySelector('iframe')
+ const messageContainers = document.querySelectorAll('#message-container')
+ for (const [index, messageContainer] of messageContainers.entries()) {
+ const iframe = messageContainer.querySelector('iframe')
- this.addMessageInfo(virtualIframeDocument, index)
+ this.addMessageInfo(virtualIframeDocument, index)
+
+ if (!iframe) {
+ const div = virtualIframeDocument.createElement('div')
+ div.innerHTML = messageContainer.innerHTML
+ virtualIframeDocument.body.appendChild(div)
+ continue
+ }
- if (!iframe) {
+ if (iframe.contentWindow.document.readyState !== 'complete') {
+ await new Promise((resolve) => {
+ iframe.contentWindow.onload = resolve
+ })
+ }
+
+ const iframeDocument = iframe.contentDocument || iframe.contentWindow.document
+ const iframeContent = iframeDocument.body.innerHTML
const div = virtualIframeDocument.createElement('div')
- div.innerHTML = messageContainer.innerHTML
+
+ div.innerHTML = iframeContent
virtualIframeDocument.body.appendChild(div)
- continue
}
- iframe.setAttribute('data-iframe-size', 'true')
+ const images = virtualIframeDocument.querySelectorAll('img')
+ let imagesLoaded = 0
- if (!iframe.contentWindow.document.readyState === 'complete') {
- await new Promise((resolve) => {
- iframe.contentWindow.onload = resolve
+ images.forEach((img) => {
+ img.addEventListener('load', () => {
+ imagesLoaded++
+ if (imagesLoaded === images.length) {
+ virtualIframe.contentWindow.print()
+ this.removeIframe(virtualIframe)
+ }
+ })
+ img.addEventListener('error', () => {
+ imagesLoaded++
+ if (imagesLoaded === images.length) {
+ virtualIframe.contentWindow.print()
+ this.removeIframe(virtualIframe)
+ }
})
- }
-
- const iframeDocument = iframe.contentDocument || iframe.contentWindow.document
- const iframeContent = iframeDocument.body.innerHTML
- const div = virtualIframeDocument.createElement('div')
-
- div.innerHTML = iframeContent
- virtualIframeDocument.body.appendChild(div)
- }
-
- const images = virtualIframeDocument.querySelectorAll('img')
- let imagesLoaded = 0
-
- images.forEach((img) => {
- img.addEventListener('load', () => {
- imagesLoaded++
- if (imagesLoaded === images.length) {
- virtualIframe.contentWindow.print()
- this.removeIframe(virtualIframe)
- }
- })
- img.addEventListener('error', () => {
- imagesLoaded++
- if (imagesLoaded === images.length) {
- virtualIframe.contentWindow.print()
- this.removeIframe(virtualIframe)
- }
})
- })
- if (images.length === 0) {
- virtualIframe.contentWindow.print()
- this.removeIframe(virtualIframe)
+ if (images.length === 0) {
+ virtualIframe.contentWindow.print()
+ this.removeIframe(virtualIframe)
+ }
+ } catch (error) {
+ logger.error('Could not print message', { error })
+ showError(t('mail', 'Could not print message'))
}
}
},
@@ -474,6 +491,7 @@ export default {
iframe.contentWindow.print()
} catch (error) {
+ logger.error('Could not print message', { error })
showError(t('mail', 'Could not print message'))
}
}, 100)
From bd5250efdd8e15cbf4e0d06efbbdb02b15bdcba2 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Mon, 8 Jun 2026 14:13:51 +0200
Subject: [PATCH 084/228] ci: bump mariadb from 11.4 to 11.8
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.github/workflows/test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4da8904f4b..1fd5c76a15 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -112,7 +112,7 @@ jobs:
- 993:993
- 4190:4190
mariadb-service:
- image: ghcr.io/nextcloud/continuous-integration-mariadb-11.4:latest
+ image: ghcr.io/nextcloud/continuous-integration-mariadb-11.8:latest
env:
MARIADB_ROOT_PASSWORD: my-secret-pw
MARIADB_DATABASE: nextcloud
From 3473b1dfdb05602ea4baaee0e1a5c6e9c0e0bd75 Mon Sep 17 00:00:00 2001
From: Jarl Gullberg
Date: Mon, 8 Jun 2026 09:12:02 +0000
Subject: [PATCH 085/228] fix(ui): prefer sans-serif over Noto Color Emoji for
text rendering
If Noto Color Emoji is installed, but none of the preceding fonts are, the UI for plaintext emails gets pretty messed up with super-wide spaces as the emoji font takes precedence. The rest of NC has sans-serif placed ahead of the Noto emoji font for this reason.
Signed-off-by: Jarl Gullberg
---
css/html-response.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/css/html-response.css b/css/html-response.css
index c9520f7a64..3b5a28baaf 100644
--- a/css/html-response.css
+++ b/css/html-response.css
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
* {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Cantarell, Ubuntu, 'Helvetica Neue', Arial, 'Noto Color Emoji', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Cantarell, Ubuntu, 'Helvetica Neue', Arial, sans-serif, 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
}
html {
From 6b5b3bd86dbee0123f58053ee7736537ae810937 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 10 Jun 2026 11:59:55 +0200
Subject: [PATCH 086/228] ci: pin front-end unit tests to ubuntu-24.04
vitest v4 with vmForks fails to apply vi.mock() reliably on the org's
self-hosted runners (deterministic 11/261 failures in actions.spec.js
and MessageService.spec.js). The same setup passes on GitHub-hosted
runners. Pin ubuntu-24.04 to force the job onto the GitHub-hosted pool
until the underlying runner issue is fixed.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
.github/workflows/test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 1fd5c76a15..0a0a342499 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -208,7 +208,7 @@ jobs:
fail_ci_if_error: ${{ !github.event.pull_request.head.repo.fork }}
verbose: true
frontend-unit-test:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
name: Front-end unit tests
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
From 79629b60cb1aa755b1361575e7d6f9c63ed3a3af Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Mon, 8 Jun 2026 14:19:36 +0200
Subject: [PATCH 087/228] fix(frontend): log swallowed errors in catch blocks
Add logger.error() calls to catch blocks that previously only showed
a user-facing notification without logging the caught error, making
these failures invisible to prod debugging.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/components/NavigationMailbox.vue | 1 +
src/components/RecipientBubble.vue | 1 +
src/components/ThreadEnvelope.vue | 1 +
src/components/TranslationModal.vue | 1 +
src/components/textBlocks/ListItem.vue | 5 ++++-
5 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/components/NavigationMailbox.vue b/src/components/NavigationMailbox.vue
index 4754fe73df..0d22af8f1c 100644
--- a/src/components/NavigationMailbox.vue
+++ b/src/components/NavigationMailbox.vue
@@ -810,6 +810,7 @@ export default {
// Handle rate limit: 429 Too Many Requests
// Ref https://axios-http.com/docs/handling_errors
if (error.response?.status === 429) {
+ logger.error('mailbox repair rate-limited', { error })
showError(t('mail', 'Please wait 10 minutes before repairing again'))
} else {
throw error
diff --git a/src/components/RecipientBubble.vue b/src/components/RecipientBubble.vue
index 96d0952275..b4fee32c93 100644
--- a/src/components/RecipientBubble.vue
+++ b/src/components/RecipientBubble.vue
@@ -229,6 +229,7 @@ export default {
await navigator.clipboard.writeText(this.email)
showSuccess(t('mail', 'Copied email address to clipboard'))
} catch (e) {
+ logger.error('could not copy email address to clipboard', { error: e })
showError(t('mail', 'Could not copy email address to clipboard'))
}
},
diff --git a/src/components/ThreadEnvelope.vue b/src/components/ThreadEnvelope.vue
index 745d9fb7b9..cc3de195a7 100644
--- a/src/components/ThreadEnvelope.vue
+++ b/src/components/ThreadEnvelope.vue
@@ -1141,6 +1141,7 @@ export default {
}
this.showTranslationModal = true
} catch (error) {
+ logger.error('could not open translation modal, message not loaded', { error })
showError(t('mail', 'Please wait for the message to load'))
}
},
diff --git a/src/components/TranslationModal.vue b/src/components/TranslationModal.vue
index 1f80d9d8d3..24df5cc95a 100644
--- a/src/components/TranslationModal.vue
+++ b/src/components/TranslationModal.vue
@@ -188,6 +188,7 @@ export default {
await navigator.clipboard.writeText(this.translatedMessage)
showSuccess(t('mail', 'Translation copied to clipboard'))
} catch (error) {
+ logger.error('could not copy translation to clipboard', { error })
showError(t('mail', 'Translation could not be copied'))
}
},
diff --git a/src/components/textBlocks/ListItem.vue b/src/components/textBlocks/ListItem.vue
index ce3c0e4b89..f0e994d281 100644
--- a/src/components/textBlocks/ListItem.vue
+++ b/src/components/textBlocks/ListItem.vue
@@ -209,7 +209,8 @@ export default {
async deleteTextBlock() {
await this.mainStore.deleteTextBlock({ id: this.textBlock.id }).then(() => {
showSuccess(t('mail', 'Text block deleted'))
- }).catch(() => {
+ }).catch((error) => {
+ logger.error('failed to delete text block', { error })
showError(t('mail', 'Failed to delete text block'))
})
},
@@ -222,6 +223,7 @@ export default {
showSuccess(t('mail', 'Text block shared with {sharee}', { sharee: sharee.shareWith }))
this.share = null
} catch (error) {
+ logger.error('failed to share text block', { error })
showError(t('mail', 'Failed to share text block with {sharee}', { sharee: sharee.shareWith }))
}
},
@@ -232,6 +234,7 @@ export default {
this.shares = this.shares.filter((share) => share.shareWith !== sharee.shareWith)
showSuccess(t('mail', 'Share deleted for {name}', { name: sharee.shareWith }))
} catch (error) {
+ logger.error('failed to delete text block share', { error })
showError(t('mail', 'Failed to delete share with {name}', { name: sharee.shareWith }))
}
},
From 5845e270b21757762b42d01aa5424a5718bdff17 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 10 Jun 2026 13:05:27 +0000
Subject: [PATCH 088/228] fix(deps): bump dompurify from ^3.4.2 to ^3.4.7
(#13043)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
package-lock.json | 8 ++++----
package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 240b7038e5..d7d026c2d0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -35,7 +35,7 @@
"color-convert": "^2.0.1",
"core-js": "^3.49.0",
"debounce-promise": "^3.1.2",
- "dompurify": "^3.4.2",
+ "dompurify": "^3.4.8",
"escape-html": "^1.0.3",
"html-to-text": "^9.0.5",
"ical.js": "^2.2.1",
@@ -8600,9 +8600,9 @@
}
},
"node_modules/dompurify": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz",
- "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==",
+ "version": "3.4.8",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.8.tgz",
+ "integrity": "sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
diff --git a/package.json b/package.json
index 2120405d69..5f832d83f8 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
"color-convert": "^2.0.1",
"core-js": "^3.49.0",
"debounce-promise": "^3.1.2",
- "dompurify": "^3.4.2",
+ "dompurify": "^3.4.8",
"escape-html": "^1.0.3",
"html-to-text": "^9.0.5",
"ical.js": "^2.2.1",
From ac447f2e6e3acacbaeba28b585046ed253edaa6b Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 10 Jun 2026 15:43:46 +0200
Subject: [PATCH 089/228] feat(ui): add password change shortcut to server
settings
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/components/AccountSettings.vue | 15 +++++++++++++++
src/components/Navigation.vue | 12 ++++++++++--
src/components/NavigationAccount.vue | 10 +++++++++-
src/store/mainStore/actions.js | 15 ++++++++++++---
4 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/src/components/AccountSettings.vue b/src/components/AccountSettings.vue
index 51f97a7d04..942c9757a7 100644
--- a/src/components/AccountSettings.vue
+++ b/src/components/AccountSettings.vue
@@ -108,6 +108,7 @@
{
+ this.$refs[newState]?.$el?.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start',
+ })
+ })
+ },
},
methods: {
diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue
index 880591eddc..cce5e72694 100644
--- a/src/components/Navigation.vue
+++ b/src/components/Navigation.vue
@@ -33,8 +33,11 @@
-
+
{{ t('mail', 'Connection failed. Please verify your information and try again') }}
+ {{ t('mail', 'Change password') }}
@@ -83,7 +86,7 @@
From 6ba42aa9c3334a543977a0a16a5afd8955a1d29d Mon Sep 17 00:00:00 2001
From: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Date: Wed, 15 Jul 2026 20:57:39 +0200
Subject: [PATCH 218/228] fix(ui): rename beforeUnmount hooks back to
beforeDestroy
Vue 2.7 only invokes the Options API hook beforeDestroy; the Vue 3
name beforeUnmount is silently ignored. The premature rename meant
cleanup code in these components never ran, leaking window listeners
and event bus subscriptions. Most visibly, the composer's beforeunload
handler survived after sending or discarding a message and blocked
navigation with a bogus confirmation popup.
The hooks must be renamed again when the app actually switches to
Vue 3.
Fixes #13031
Assisted-by: Claude:claude-fable-5
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
---
src/components/Composer.vue | 2 +-
src/components/DisplayContactDetails.vue | 2 +-
src/components/EnvelopeList.vue | 2 +-
src/components/Loading.vue | 2 +-
src/components/MailboxThread.vue | 2 +-
src/components/MessageAttachment.vue | 2 +-
src/components/MessageHTMLBody.vue | 2 +-
src/components/NavigationMailbox.vue | 2 +-
src/components/NewMessageModal.vue | 2 +-
src/components/Thread.vue | 2 +-
src/components/ThreadEnvelope.vue | 2 +-
11 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/components/Composer.vue b/src/components/Composer.vue
index 846c9ece14..5aeaeec588 100644
--- a/src/components/Composer.vue
+++ b/src/components/Composer.vue
@@ -1129,7 +1129,7 @@ export default {
}
},
- beforeUnmount() {
+ beforeDestroy() {
window.removeEventListener('mailvelope', this.onMailvelopeLoaded)
},
diff --git a/src/components/DisplayContactDetails.vue b/src/components/DisplayContactDetails.vue
index 3564689e0b..0f28b880c4 100644
--- a/src/components/DisplayContactDetails.vue
+++ b/src/components/DisplayContactDetails.vue
@@ -35,7 +35,7 @@ export default {
}
},
- async beforeUnmount() {
+ async beforeDestroy() {
if (this.vm) {
this.vm.$destroy()
}
diff --git a/src/components/EnvelopeList.vue b/src/components/EnvelopeList.vue
index 45aebf4271..e4d7165d80 100644
--- a/src/components/EnvelopeList.vue
+++ b/src/components/EnvelopeList.vue
@@ -377,7 +377,7 @@ export default {
dragEventBus.on('envelopes-dropped', this.unselectAll)
},
- beforeUnmount() {
+ beforeDestroy() {
dragEventBus.off('envelopes-dropped', this.unselectAll)
},
diff --git a/src/components/Loading.vue b/src/components/Loading.vue
index 9b2544cff5..d3b394f024 100644
--- a/src/components/Loading.vue
+++ b/src/components/Loading.vue
@@ -59,7 +59,7 @@ export default {
}, 3500)
},
- beforeUnmount() {
+ beforeDestroy() {
clearTimeout(this.slowTimer)
},
}
diff --git a/src/components/MailboxThread.vue b/src/components/MailboxThread.vue
index f1fd5bf3ab..76464d1c93 100644
--- a/src/components/MailboxThread.vue
+++ b/src/components/MailboxThread.vue
@@ -473,7 +473,7 @@ export default {
}
},
- beforeUnmount() {
+ beforeDestroy() {
clearTimeout(this.startMailboxTimer)
},
diff --git a/src/components/MessageAttachment.vue b/src/components/MessageAttachment.vue
index 8fb911bdcd..e0679e0337 100644
--- a/src/components/MessageAttachment.vue
+++ b/src/components/MessageAttachment.vue
@@ -206,7 +206,7 @@ export default {
document.addEventListener('click', this.handleClickOutside)
},
- beforeUnmount() {
+ beforeDestroy() {
document.removeEventListener('click', this.handleClickOutside)
},
diff --git a/src/components/MessageHTMLBody.vue b/src/components/MessageHTMLBody.vue
index cbb10eb859..978a58c640 100644
--- a/src/components/MessageHTMLBody.vue
+++ b/src/components/MessageHTMLBody.vue
@@ -131,7 +131,7 @@ export default {
}
},
- beforeUnmount() {
+ beforeDestroy() {
scout.off('beforeprint', this.onBeforePrint)
scout.off('afterprint', this.onAfterPrint)
this.$refs.iframe.iFrameResizer.close()
diff --git a/src/components/NavigationMailbox.vue b/src/components/NavigationMailbox.vue
index 1399e2698b..b858c35cb4 100644
--- a/src/components/NavigationMailbox.vue
+++ b/src/components/NavigationMailbox.vue
@@ -518,7 +518,7 @@ export default {
dragEventBus.on('envelopes-moved', this.onEnvelopesMoved)
},
- beforeUnmount() {
+ beforeDestroy() {
dragEventBus.off('drag-start', this.onDragStart)
dragEventBus.off('drag-end', this.onDragEnd)
dragEventBus.off('envelopes-moved', this.onEnvelopesMoved)
diff --git a/src/components/NewMessageModal.vue b/src/components/NewMessageModal.vue
index 70bf666100..bf41f3c29b 100644
--- a/src/components/NewMessageModal.vue
+++ b/src/components/NewMessageModal.vue
@@ -271,7 +271,7 @@ export default {
window.addEventListener('resize', this.checkScreenSize)
},
- beforeUnmount() {
+ beforeDestroy() {
window.removeEventListener('beforeunload', this.onBeforeUnload)
window.removeEventListener('resize', this.checkScreenSize)
},
diff --git a/src/components/Thread.vue b/src/components/Thread.vue
index 08fb567def..d301ae1ab6 100644
--- a/src/components/Thread.vue
+++ b/src/components/Thread.vue
@@ -175,7 +175,7 @@ export default {
window.addEventListener('keydown', this.handleKeyDown)
},
- beforeUnmount() {
+ beforeDestroy() {
window.removeEventListener('keydown', this.handleKeyDown)
},
diff --git a/src/components/ThreadEnvelope.vue b/src/components/ThreadEnvelope.vue
index 92e3415034..7484e623aa 100644
--- a/src/components/ThreadEnvelope.vue
+++ b/src/components/ThreadEnvelope.vue
@@ -803,7 +803,7 @@ export default {
}, 100)
},
- beforeUnmount() {
+ beforeDestroy() {
if (this.seenTimer !== undefined) {
logger.info('Navigating away before seenTimer delay, will not mark message as seen/read')
clearTimeout(this.seenTimer)
From 16d4a09889490fa243a8047e2f5b588972c42bc4 Mon Sep 17 00:00:00 2001
From: steven-mpawulo
Date: Thu, 16 Jul 2026 10:35:00 +0300
Subject: [PATCH 219/228] feat: adds drag, drop and pasting of attachments
Add support for attaching files via drag-and-drop and clipboard
paste in the message composer
Signed-off-by: steven-mpawulo
---
src/components/Composer.vue | 42 +++++++++++++++++++++++++-
src/components/ComposerAttachments.vue | 11 +++++--
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/src/components/Composer.vue b/src/components/Composer.vue
index e8c217aeb1..04137cfec9 100644
--- a/src/components/Composer.vue
+++ b/src/components/Composer.vue
@@ -3,7 +3,11 @@
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
-
+
diff --git a/src/components/ComposerAttachments.vue b/src/components/ComposerAttachments.vue
index 38c65846b5..fb8994e29b 100644
--- a/src/components/ComposerAttachments.vue
+++ b/src/components/ComposerAttachments.vue
@@ -190,6 +190,7 @@ export default {
this.bus.on('on-add-cloud-attachment', this.openAttachementPicker)
this.bus.on('on-add-cloud-attachment-link', this.OpenLinkPicker)
this.bus.on('on-add-message-as-attachment', this.onAddMessageAsAttachment)
+ this.bus.on('on-add-local-files', this.addLocalFiles)
this.value.map((attachment) => {
this.attachments.push({
id: attachment.id,
@@ -240,11 +241,15 @@ export default {
},
onLocalAttachmentSelected(e) {
+ return this.addLocalFiles(Array.from(e.target.files))
+ },
+
+ addLocalFiles(files) {
this.uploading = true
// BUG - if choose again - progress lost/ move to complete()
Vue.set(this, 'uploads', {})
- const toUpload = sumBy(prop('size'), Object.values(e.target.files))
+ const toUpload = sumBy(prop('size'), Object.values(files))
const newTotal = toUpload + this.totalSizeOfUpload()
logger.debug('checking upload size limit', {
existingUploads: this.totalSizeOfUpload(),
@@ -253,7 +258,7 @@ export default {
newTotal,
})
if (this.uploadSizeLimit && newTotal > this.uploadSizeLimit) {
- this.showAttachmentFileSizeWarning(e.target.files.length)
+ this.showAttachmentFileSizeWarning(files.length)
this.uploading = false
return
}
@@ -318,7 +323,7 @@ export default {
} catch (error) {
logger.error('Could not upload file', { file, error })
}
- }, e.target.files)
+ }, files)
const done = Promise.all(promises)
.catch((error) => logger.error('could not upload all attachments', { error }))
From 933a6da3161b1928a9c9cc8009bd8a79110f6243 Mon Sep 17 00:00:00 2001
From: Mathias Riechsteiner
Date: Thu, 16 Jul 2026 10:16:41 +0200
Subject: [PATCH 220/228] fix(ui): archive shortcut in unified mailboxes
The 'arch' shortcut handler in Mailbox.vue reads archiveMailboxId from
this.account. In a unified mailbox that is the unified account, which
has no archiveMailboxId property: the strict === null guard misses
undefined and moveThread() is dispatched without a destination mailbox,
failing with 'Could not archive message'.
Resolve the envelope's actual account via
mainStore.getAccount(env.accountId) instead - the same pattern
Envelope.vue and ThreadEnvelope.vue use, which is why archiving from
the three-dot menu already works in the unified inbox.
Assisted-by: ClaudeCode:claude-fable-5
Signed-off-by: Mathias Riechsteiner
---
src/components/Mailbox.vue | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue
index f1d69697e7..a117f4d545 100644
--- a/src/components/Mailbox.vue
+++ b/src/components/Mailbox.vue
@@ -434,10 +434,14 @@ export default {
}
break
- case 'arch':
+ case 'arch': {
logger.debug('archiving via shortcut')
- if (this.account.archiveMailboxId === null) {
+ // In unified mailboxes this.account is the unified account which
+ // has no archive mailbox, so resolve the envelope's actual account
+ const account = this.mainStore.getAccount(env.accountId)
+
+ if (account.archiveMailboxId === null) {
showWarning(t('mail', 'To archive a message please configure an archive folder in account settings'))
return
}
@@ -447,7 +451,7 @@ export default {
return
}
- if (env.mailboxId === this.account.archiveMailboxId) {
+ if (env.mailboxId === account.archiveMailboxId) {
logger.debug('message is already in archive folder')
return
}
@@ -457,7 +461,7 @@ export default {
try {
await this.mainStore.moveThread({
envelope: env,
- destMailboxId: this.account.archiveMailboxId,
+ destMailboxId: account.archiveMailboxId,
})
} catch (error) {
logger.error('could not archive envelope', {
@@ -468,6 +472,7 @@ export default {
showError(t('mail', 'Could not archive message'))
}
break
+ }
case 'flag':
logger.debug('flagging envelope via shortkey', { env })
this.mainStore.toggleEnvelopeFlagged(env).catch((error) => logger.error('could not flag envelope via shortkey', {
From f8dedb197e67faa650ef896efa0d0981a22a3f52 Mon Sep 17 00:00:00 2001
From: Roberto Guido
Date: Thu, 16 Jul 2026 11:29:29 +0200
Subject: [PATCH 221/228] fix: subfolder selection for quick actions
Signed-off-by: Roberto Guido
---
src/components/quickActions/Action.vue | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/components/quickActions/Action.vue b/src/components/quickActions/Action.vue
index 2a59a1a8b4..3079aeae68 100644
--- a/src/components/quickActions/Action.vue
+++ b/src/components/quickActions/Action.vue
@@ -82,10 +82,14 @@ export default {
}))
}
if (this.action.name === 'moveThread') {
- return this.mainStore.getMailboxes(this.account.accountId).map((mailbox) => ({
- value: mailbox.displayName,
- id: mailbox.databaseId,
- }))
+ const ret = []
+ for (const mailbox of this.mainStore.getRecursiveMailboxIterator(this.account.accountId)) {
+ ret.push({
+ value: mailbox.name,
+ id: mailbox.databaseId,
+ })
+ }
+ return ret
}
return []
},
From 81ef139b4a89990fa3b94460771b49e861439878 Mon Sep 17 00:00:00 2001
From: Roberto Guido
Date: Thu, 16 Jul 2026 18:30:57 +0200
Subject: [PATCH 222/228] feat: save email as .eml file in Files
Signed-off-by: Roberto Guido
---
appinfo/routes.php | 5 ++
lib/Controller/MessagesController.php | 72 +++++++++++++++++++
src/components/Envelope.vue | 49 +++++++++++++
src/components/MenuEnvelope.vue | 52 ++++++++++++++
src/service/MessageService.js | 10 +++
.../Controller/MessagesControllerTest.php | 68 ++++++++++++++++++
6 files changed, 256 insertions(+)
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 26e7e17776..0e116e1349 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -210,6 +210,11 @@
'url' => '/api/messages/{id}/attachment/{attachmentId}',
'verb' => 'POST'
],
+ [
+ 'name' => 'messages#saveFile',
+ 'url' => '/api/messages/{id}/file',
+ 'verb' => 'POST'
+ ],
[
'name' => 'messages#getBody',
'url' => '/api/messages/{id}/body',
diff --git a/lib/Controller/MessagesController.php b/lib/Controller/MessagesController.php
index e3b25e4148..022964f703 100755
--- a/lib/Controller/MessagesController.php
+++ b/lib/Controller/MessagesController.php
@@ -44,6 +44,7 @@
use OCP\AppFramework\Http\ZipResponse;
use OCP\Files\Folder;
use OCP\Files\GenericFileException;
+use OCP\Files\IFilenameValidator;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\NotPermittedException;
use OCP\ICache;
@@ -71,6 +72,7 @@ public function __construct(
private ItineraryService $itineraryService,
private ?string $userId,
private ?Folder $userFolder,
+ private IFilenameValidator $filenameValidator,
private LoggerInterface $logger,
IL10N $l10n,
IMimeTypeDetector $mimeTypeDetector,
@@ -585,6 +587,76 @@ public function export(int $id): Response {
);
}
+ /**
+ * Save a whole message as an .eml file in the local storage
+ *
+ * @NoAdminRequired
+ *
+ * @param int $id
+ * @param string $targetPath
+ *
+ * @return Response
+ *
+ * @throws ClientException
+ * @throws GenericFileException
+ * @throws NotPermittedException
+ * @throws LockedException
+ * @throws ServiceException
+ */
+ #[TrapError]
+ public function saveFile(int $id, string $targetPath): Response {
+ if ($this->userId === null) {
+ return new JSONResponse([], Http::STATUS_UNAUTHORIZED);
+ }
+ if ($this->userFolder === null) {
+ return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ if (!$this->userFolder->nodeExists($targetPath)) {
+ return new JSONResponse([], Http::STATUS_BAD_REQUEST);
+ }
+ if (!($this->userFolder->get($targetPath) instanceof Folder)) {
+ return new JSONResponse([], Http::STATUS_BAD_REQUEST);
+ }
+ try {
+ $effectiveUserId = $this->delegationService->resolveMessageUserId($id, $this->userId);
+ $message = $this->mailManager->getMessage($effectiveUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($effectiveUserId, $message->getMailboxId());
+ $account = $this->accountService->find($effectiveUserId, $mailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse([], Http::STATUS_FORBIDDEN);
+ }
+
+ $client = $this->clientFactory->getClient($account);
+ try {
+ $source = $this->mailManager->getSource(
+ $client,
+ $account,
+ $mailbox->getName(),
+ $message->getUid()
+ );
+ } finally {
+ $client->logout();
+ }
+
+ if ($source === null) {
+ return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+
+ $fileName = $this->filenameValidator->sanitizeFilename($message->getSubject());
+ $fileExtension = 'eml';
+ $fullPath = "$targetPath/$fileName.$fileExtension";
+ $counter = 2;
+ while ($this->userFolder->nodeExists($fullPath)) {
+ $fullPath = "$targetPath/$fileName ($counter).$fileExtension";
+ $counter++;
+ }
+
+ $newFile = $this->userFolder->newFile($fullPath);
+ $newFile->putContent($source);
+
+ return new JSONResponse();
+ }
+
/**
* @NoAdminRequired
* @NoCSRFRequired
diff --git a/src/components/Envelope.vue b/src/components/Envelope.vue
index b88311fa50..f6a70e19b1 100644
--- a/src/components/Envelope.vue
+++ b/src/components/Envelope.vue
@@ -189,6 +189,14 @@
fill-color="var(--color-primary-element)" />
+ isFilePickerOpen = false" />
{{ t('mail', 'Download message') }}
+ isFilePickerOpen = true">
+
+
+
+ {{ t('mail', 'Save message to Files') }}
+
import { showError, showSuccess, showWarning } from '@nextcloud/dialogs'
+import { FilePickerVue as FilePicker } from '@nextcloud/dialogs/filepicker.js'
import { isRTL } from '@nextcloud/l10n'
import moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router'
@@ -543,6 +562,7 @@ import DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'
import IconEmailFast from 'vue-material-design-icons/EmailFastOutline.vue'
import EmailRead from 'vue-material-design-icons/EmailOpenOutline.vue'
import EmailUnread from 'vue-material-design-icons/EmailOutline.vue'
+import IconSave from 'vue-material-design-icons/FolderOutline.vue'
import ImportantIcon from 'vue-material-design-icons/LabelVariant.vue'
import ImportantOutlineIcon from 'vue-material-design-icons/LabelVariantOutline.vue'
import OpenInNewIcon from 'vue-material-design-icons/OpenInNew.vue'
@@ -572,6 +592,7 @@ import NoTrashMailboxConfiguredError
import logger from '../logger.js'
import AttachmentMixin from '../mixins/AttachmentMixin.js'
import { buildRecipients as buildReplyRecipients } from '../ReplyBuilder.js'
+import { saveMessage } from '../service/MessageService.js'
import { FOLLOW_UP_TAG_LABEL } from '../store/constants.js'
import useMainStore from '../store/mainStore.js'
import { mailboxHasRights } from '../util/acl.js'
@@ -594,6 +615,8 @@ export default {
DotsHorizontalIcon,
EnvelopePrimaryActions,
EventModal,
+ IconSave,
+ FilePicker,
ImportantIcon,
ImportantOutlineIcon,
TaskModal,
@@ -687,6 +710,15 @@ export default {
hoveringAvatar: false,
quickActionLoading: false,
possibleAttachmentsCount: 0,
+ savingToCloud: false,
+ isFilePickerOpen: false,
+ saveMessageButtons: [
+ {
+ label: t('mail', 'Choose'),
+ callback: this.saveToCloud,
+ type: 'primary',
+ },
+ ],
}
},
@@ -1424,6 +1456,23 @@ export default {
this.showTagModal = false
},
+ async saveToCloud(dest) {
+ const path = dest[0].path
+ this.savingToCloud = true
+ const id = this.data.databaseId
+
+ try {
+ await saveMessage(id, path)
+ logger.info('saved')
+ showSuccess(t('mail', 'Message saved to Files'))
+ } catch (e) {
+ logger.error('not saved', { error: e })
+ showError(t('mail', 'Message could not be saved'))
+ } finally {
+ this.savingToCloud = false
+ }
+ },
+
getTimestamp(momentObject) {
return momentObject?.minute(0).second(0).millisecond(0).valueOf() || null
},
diff --git a/src/components/MenuEnvelope.vue b/src/components/MenuEnvelope.vue
index b5bbf77197..d5fd7d9860 100644
--- a/src/components/MenuEnvelope.vue
+++ b/src/components/MenuEnvelope.vue
@@ -5,6 +5,14 @@
+
isFilePickerOpen = false" />
{{ t('mail', 'Download message') }}
+ isFilePickerOpen = true">
+
+
+
+
+ {{ t('mail', 'Save message to Files') }}
+
import { showError, showSuccess } from '@nextcloud/dialogs'
+import { FilePickerVue as FilePicker } from '@nextcloud/dialogs/filepicker.js'
import moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router'
import {
NcActionButton as ActionButton,
NcActionLink as ActionLink,
+ NcLoadingIcon as IconLoading,
NcActionButton,
} from '@nextcloud/vue'
import { Base64 } from 'js-base64'
@@ -296,6 +317,7 @@ import ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'
import ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'
import DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'
import FilterIcon from 'vue-material-design-icons/FilterOutline.vue'
+import IconSave from 'vue-material-design-icons/FolderOutline.vue'
import InformationIcon from 'vue-material-design-icons/InformationOutline.vue'
import ImportantIcon from 'vue-material-design-icons/LabelVariant.vue'
import ImportantOutlineIcon from 'vue-material-design-icons/LabelVariantOutline.vue'
@@ -308,6 +330,7 @@ import TranslationIcon from 'vue-material-design-icons/Translate.vue'
import DownloadIcon from 'vue-material-design-icons/TrayArrowDown.vue'
import logger from '../logger.js'
import { buildRecipients as buildReplyRecipients } from '../ReplyBuilder.js'
+import { saveMessage } from '../service/MessageService.js'
import useMainStore from '../store/mainStore.js'
import { mailboxHasRights } from '../util/acl.js'
@@ -327,6 +350,9 @@ export default {
DotsHorizontalIcon,
TranslationIcon,
DownloadIcon,
+ IconLoading,
+ IconSave,
+ FilePicker,
InformationIcon,
OpenInNewIcon,
PlusIcon,
@@ -387,6 +413,15 @@ export default {
customSnoozeDateTime: new Date(moment().add(2, 'hours').minute(0).second(0).valueOf()),
copied: false,
copyResetTimer: null,
+ savingToCloud: false,
+ isFilePickerOpen: false,
+ saveMessageButtons: [
+ {
+ label: t('mail', 'Choose'),
+ callback: this.saveToCloud,
+ type: 'primary',
+ },
+ ],
}
},
@@ -687,6 +722,23 @@ export default {
}
},
+ async saveToCloud(dest) {
+ const path = dest[0].path
+ this.savingToCloud = true
+ const id = this.envelope.databaseId
+
+ try {
+ await saveMessage(id, path)
+ logger.info('saved')
+ showSuccess(t('mail', 'Message saved to Files'))
+ } catch (e) {
+ logger.error('not saved', { error: e })
+ showError(t('mail', 'Message could not be saved'))
+ } finally {
+ this.savingToCloud = false
+ }
+ },
+
isSieveEnabled() {
return this.account.sieveEnabled
},
diff --git a/src/service/MessageService.js b/src/service/MessageService.js
index 2af9dd1a28..ac55668181 100644
--- a/src/service/MessageService.js
+++ b/src/service/MessageService.js
@@ -276,6 +276,16 @@ export function moveMessage(id, destFolderId) {
})
}
+export async function saveMessage(id, directory) {
+ const url = generateUrl('/apps/mail/api/messages/{id}/file', {
+ id,
+ })
+
+ return await axios.post(url, {
+ targetPath: directory,
+ })
+}
+
export function snoozeMessage(id, unixTimestamp, destMailboxId) {
const url = generateUrl('/apps/mail/api/messages/{id}/snooze', {
id,
diff --git a/tests/Unit/Controller/MessagesControllerTest.php b/tests/Unit/Controller/MessagesControllerTest.php
index 2954d0809a..245d2253ca 100644
--- a/tests/Unit/Controller/MessagesControllerTest.php
+++ b/tests/Unit/Controller/MessagesControllerTest.php
@@ -49,6 +49,7 @@
use OCP\AppFramework\Http\ZipResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\Folder;
+use OCP\Files\IFilenameValidator;
use OCP\Files\IMimeTypeDetector;
use OCP\ICacheFactory;
use OCP\IL10N;
@@ -171,6 +172,10 @@ protected function setUp(): void {
$this->delegationService->method('resolveMessageUserId')->willReturn($this->userId);
$this->delegationService->method('resolveMailboxUserId')->willReturn($this->userId);
+ $this->filenameValidator = $this->createMock(IFilenameValidator::class);
+ $this->filenameValidator->method('sanitizeFilename')
+ ->willReturn('core_master has new results');
+
$timeFactory = $this->createMocK(ITimeFactory::class);
$timeFactory->expects($this->any())
->method('getTime')
@@ -187,6 +192,7 @@ protected function setUp(): void {
$this->itineraryService,
$this->userId,
$this->userFolder,
+ $this->filenameValidator,
$this->logger,
$this->l10n,
$this->mimeTypeDetector,
@@ -1189,6 +1195,66 @@ public function testExport() {
$this->assertEquals($expectedResponse, $actualResponse);
}
+ public function testSaveFile() {
+ $accountId = 17;
+ $mailboxId = 13;
+ $folderId = 'testfolder';
+ $messageId = 4321;
+ $targetPath = 'Downloads';
+ $this->account
+ ->method('getId')
+ ->willReturn($accountId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $message = new \OCA\Mail\Db\Message();
+ $message->setMailboxId($mailboxId);
+ $message->setUid(123);
+ $message->setSubject('core/master has new results');
+ $mailbox->setAccountId($accountId);
+ $mailbox->setName($folderId);
+ $this->mailManager->expects($this->exactly(1))
+ ->method('getMessage')
+ ->with($this->userId, $messageId)
+ ->willReturn($message);
+ $this->mailManager->expects($this->exactly(1))
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
+ $this->accountService->expects($this->exactly(1))
+ ->method('find')
+ ->with($this->equalTo($this->userId), $this->equalTo($accountId))
+ ->will($this->returnValue($this->account));
+ $source = file_get_contents(__DIR__ . '/../../data/mail-message-123.txt');
+ $client = $this->createStub(Horde_Imap_Client_Socket::class);
+ $this->mailManager->expects($this->exactly(1))
+ ->method('getSource')
+ ->with($client, $this->account, $folderId, 123)
+ ->willReturn($source);
+ $folderNode = $this->createStub(Folder::class);
+ $this->userFolder->expects($this->once())
+ ->method('get')
+ ->with('Downloads')
+ ->willReturn($folderNode);
+ $this->userFolder->expects($this->exactly(2))
+ ->method('nodeExists')
+ ->withConsecutive(['Downloads'], ['Downloads/core_master has new results.eml'])
+ ->willReturnOnConsecutiveCalls(true, false);
+ $file = $this->getMockBuilder('\OCP\Files\File')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->userFolder->expects($this->once())
+ ->method('newFile')
+ ->with('Downloads/core_master has new results.eml')
+ ->will($this->returnValue($file));
+ $this->clientFactory->expects($this->once())
+ ->method('getClient')
+ ->willReturn($client);
+
+ $expectedResponse = new JSONResponse();
+ $actualResponse = $this->controller->saveFile($messageId, $targetPath);
+
+ $this->assertEquals($expectedResponse, $actualResponse);
+ }
+
public function testGetDkim() {
$mailAccount = new MailAccount();
$mailAccount->setId(100);
@@ -1295,6 +1361,7 @@ public function testNeedsTranslationNoUser() {
$this->itineraryService,
null,
$this->userFolder,
+ $this->filenameValidator,
$this->logger,
$this->l10n,
$this->mimeTypeDetector,
@@ -1500,6 +1567,7 @@ public function testSmartReplyNoUser(): void {
$this->itineraryService,
null,
$this->userFolder,
+ $this->filenameValidator,
$this->logger,
$this->l10n,
$this->mimeTypeDetector,
From 63d08c1ff86fc7f9050e54341eccbb43c44f7a8d Mon Sep 17 00:00:00 2001
From: Roberto Guido
Date: Thu, 16 Jul 2026 21:35:58 +0200
Subject: [PATCH 223/228] fix(ui): improve quick actions modal design
Signed-off-by: Roberto Guido
---
src/components/quickActions/Action.vue | 23 +++++++++++++++++++++--
src/components/quickActions/Settings.vue | 15 ++++++++++++---
2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/src/components/quickActions/Action.vue b/src/components/quickActions/Action.vue
index 3079aeae68..3b510ebef1 100644
--- a/src/components/quickActions/Action.vue
+++ b/src/components/quickActions/Action.vue
@@ -5,7 +5,7 @@
-
+
{{ actionTitle }}
@@ -18,7 +18,11 @@
:model-value="selectedOption"
@update:modelValue="update" />
-
+
@@ -54,6 +58,11 @@ export default {
type: Object,
required: true,
},
+
+ draggable: {
+ type: Boolean,
+ required: true,
+ },
},
computed: {
@@ -134,13 +143,23 @@ export default {
align-items: center;
&__info{
display: flex;
+ flex-grow: 1;
&__icon{
margin-inline-end : 3px
}
&__drag{
margin-inline-end : 6px;
cursor: grab;
+
+ &.undraggable {
+ opacity: .2;
+ cursor: revert;
+ }
}
}
+
+ .delete-button {
+ margin-inline-start : 6px;
+ }
}
diff --git a/src/components/quickActions/Settings.vue b/src/components/quickActions/Settings.vue
index 20f0918649..29a6283365 100644
--- a/src/components/quickActions/Settings.vue
+++ b/src/components/quickActions/Settings.vue
@@ -43,6 +43,7 @@
updateAction(payload, item)"
@delete="deleteAction(item)" />
@@ -370,9 +371,10 @@ export default {