aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/comments/l10n/ga.js39
-rw-r--r--apps/comments/l10n/ga.json37
-rw-r--r--apps/dashboard/l10n/fr.js4
-rw-r--r--apps/dashboard/l10n/fr.json4
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php2
-rw-r--r--apps/dav/composer/composer/autoload_static.php2
-rw-r--r--apps/dav/lib/AppInfo/Application.php2
-rw-r--r--apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php2
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscription.php6
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscriptionImpl.php117
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscriptionProvider.php57
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php8
-rw-r--r--apps/dav/lib/CalDAV/CalendarHome.php14
-rw-r--r--apps/dav/lib/CalDAV/CalendarRoot.php13
-rw-r--r--apps/dav/lib/CalDAV/WebcalCaching/Plugin.php20
-rw-r--r--apps/dav/lib/Connector/Sabre/DavAclPlugin.php2
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php96
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php88
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php5
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarHomeTest.php126
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarImplTest.php3
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php51
-rw-r--r--apps/files_sharing/l10n/fr.js2
-rw-r--r--apps/files_sharing/l10n/fr.json2
-rw-r--r--apps/provisioning_api/l10n/fr.js8
-rw-r--r--apps/provisioning_api/l10n/fr.json8
-rw-r--r--apps/settings/l10n/fr.js20
-rw-r--r--apps/settings/l10n/fr.json20
-rw-r--r--apps/sharebymail/l10n/fr.js4
-rw-r--r--apps/sharebymail/l10n/fr.json4
-rw-r--r--apps/theming/l10n/fr.js2
-rw-r--r--apps/theming/l10n/fr.json2
-rw-r--r--apps/user_ldap/l10n/fr.js2
-rw-r--r--apps/user_ldap/l10n/fr.json2
34 files changed, 703 insertions, 71 deletions
diff --git a/apps/comments/l10n/ga.js b/apps/comments/l10n/ga.js
new file mode 100644
index 00000000000..266a792873c
--- /dev/null
+++ b/apps/comments/l10n/ga.js
@@ -0,0 +1,39 @@
+OC.L10N.register(
+ "comments",
+ {
+ "Comments" : "Tuairimí",
+ "You commented" : "Rinne tú trácht",
+ "{author} commented" : "Rinne {author} nóta tráchta",
+ "You commented on %1$s" : "Rinne tú trácht ar%1$s",
+ "You commented on {file}" : "Rinne tú trácht ar {file}",
+ "%1$s commented on %2$s" : "%1$s trácht ar %2$s",
+ "{author} commented on {file}" : "{author} trácht ar {file}",
+ "<strong>Comments</strong> for files" : "<strong>Tuairimí</strong> le haghaidh comhaid",
+ "You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Luadh thú ar \"{file}\", i nóta tráchta ó chuntas a scriosadh ó shin",
+ "{user} mentioned you in a comment on \"{file}\"" : "Luaigh {úsáideoir} tú i nóta tráchta ar \"{file}\"",
+ "Files app plugin to add comments to files" : "Breiseán aip Comhaid chun tuairimí a chur le comhaid",
+ "Edit comment" : "Cuir trácht in eagar",
+ "Delete comment" : "Scrios nóta tráchta",
+ "Cancel edit" : "Cealaigh eagarthóireacht",
+ "New comment" : "Trácht nua",
+ "Write a comment …" : "Scríobh trácht…",
+ "Post comment" : "Post trácht",
+ "@ for mentions, : for emoji, / for smart picker" : "@ le haghaidh tagairtí, : le haghaidh emoji, / le haghaidh roghnóir cliste",
+ "Could not reload comments" : "Níorbh fhéidir na nótaí tráchta a athlódáil",
+ "No comments yet, start the conversation!" : "Gan trácht ar bith go fóill, cuir tús leis an gcomhrá!",
+ "No more messages" : "Níl a thuilleadh teachtaireachtaí",
+ "Retry" : "Bain triail eile as",
+ "Failed to mark comments as read" : "Theip ar nótaí tráchta a mharcáil mar léite",
+ "Unable to load the comments list" : "Ní féidir an liosta tuairimí a lódáil",
+ "_1 new comment_::_{unread} new comments_" : ["1 trácht nua","{unread} nóta tráchta nua","{unread} nóta tráchta nua","{unread} nóta tráchta nua","{unread} nóta tráchta nua"],
+ "Comment" : "Trácht",
+ "An error occurred while trying to edit the comment" : "Tharla earráid agus an nóta tráchta á chur in eagar",
+ "Comment deleted" : "Trácht scriosta",
+ "An error occurred while trying to delete the comment" : "Tharla earráid agus an nóta tráchta á scriosadh",
+ "An error occurred while trying to create the comment" : "Tharla earráid agus an nóta tráchta á chruthú",
+ "You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Luadh thú ar \"{file}\", i nóta tráchta ó úsáideoir atá scriosta ó shin",
+ "Write a message …" : "Scríobh teachtaireacht…",
+ "\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "\"@\" le haghaidh tagairtí, \":\" le haghaidh emoji, \"/\" don roghnóir cliste",
+ "_%n unread comment_::_%n unread comments_" : ["%n trácht gan léamh","%n tuairimí neamhléite","%n tuairimí neamhléite","%n tuairimí neamhléite","%n tuairimí neamhléite"]
+},
+"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);");
diff --git a/apps/comments/l10n/ga.json b/apps/comments/l10n/ga.json
new file mode 100644
index 00000000000..7830a787ae2
--- /dev/null
+++ b/apps/comments/l10n/ga.json
@@ -0,0 +1,37 @@
+{ "translations": {
+ "Comments" : "Tuairimí",
+ "You commented" : "Rinne tú trácht",
+ "{author} commented" : "Rinne {author} nóta tráchta",
+ "You commented on %1$s" : "Rinne tú trácht ar%1$s",
+ "You commented on {file}" : "Rinne tú trácht ar {file}",
+ "%1$s commented on %2$s" : "%1$s trácht ar %2$s",
+ "{author} commented on {file}" : "{author} trácht ar {file}",
+ "<strong>Comments</strong> for files" : "<strong>Tuairimí</strong> le haghaidh comhaid",
+ "You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Luadh thú ar \"{file}\", i nóta tráchta ó chuntas a scriosadh ó shin",
+ "{user} mentioned you in a comment on \"{file}\"" : "Luaigh {úsáideoir} tú i nóta tráchta ar \"{file}\"",
+ "Files app plugin to add comments to files" : "Breiseán aip Comhaid chun tuairimí a chur le comhaid",
+ "Edit comment" : "Cuir trácht in eagar",
+ "Delete comment" : "Scrios nóta tráchta",
+ "Cancel edit" : "Cealaigh eagarthóireacht",
+ "New comment" : "Trácht nua",
+ "Write a comment …" : "Scríobh trácht…",
+ "Post comment" : "Post trácht",
+ "@ for mentions, : for emoji, / for smart picker" : "@ le haghaidh tagairtí, : le haghaidh emoji, / le haghaidh roghnóir cliste",
+ "Could not reload comments" : "Níorbh fhéidir na nótaí tráchta a athlódáil",
+ "No comments yet, start the conversation!" : "Gan trácht ar bith go fóill, cuir tús leis an gcomhrá!",
+ "No more messages" : "Níl a thuilleadh teachtaireachtaí",
+ "Retry" : "Bain triail eile as",
+ "Failed to mark comments as read" : "Theip ar nótaí tráchta a mharcáil mar léite",
+ "Unable to load the comments list" : "Ní féidir an liosta tuairimí a lódáil",
+ "_1 new comment_::_{unread} new comments_" : ["1 trácht nua","{unread} nóta tráchta nua","{unread} nóta tráchta nua","{unread} nóta tráchta nua","{unread} nóta tráchta nua"],
+ "Comment" : "Trácht",
+ "An error occurred while trying to edit the comment" : "Tharla earráid agus an nóta tráchta á chur in eagar",
+ "Comment deleted" : "Trácht scriosta",
+ "An error occurred while trying to delete the comment" : "Tharla earráid agus an nóta tráchta á scriosadh",
+ "An error occurred while trying to create the comment" : "Tharla earráid agus an nóta tráchta á chruthú",
+ "You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Luadh thú ar \"{file}\", i nóta tráchta ó úsáideoir atá scriosta ó shin",
+ "Write a message …" : "Scríobh teachtaireacht…",
+ "\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "\"@\" le haghaidh tagairtí, \":\" le haghaidh emoji, \"/\" don roghnóir cliste",
+ "_%n unread comment_::_%n unread comments_" : ["%n trácht gan léamh","%n tuairimí neamhléite","%n tuairimí neamhléite","%n tuairimí neamhléite","%n tuairimí neamhléite"]
+},"pluralForm" :"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/fr.js b/apps/dashboard/l10n/fr.js
index b446dabe0f2..ef5729508c1 100644
--- a/apps/dashboard/l10n/fr.js
+++ b/apps/dashboard/l10n/fr.js
@@ -3,7 +3,7 @@ OC.L10N.register(
{
"Dashboard" : "Tableau de bord",
"Dashboard app" : "App Tableau de bord",
- "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des courriels urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les personnes peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise.",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des e-mails urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les personnes peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise.",
"\"{title} icon\"" : "« Icône {title} »",
"Customize" : "Personnaliser",
"Edit widgets" : "Modifier les widgets",
@@ -23,6 +23,6 @@ OC.L10N.register(
"Good evening, {name}" : "Bonsoir {name}",
"Hello" : "Bonjour",
"Hello, {name}" : "Bonjour {name}",
- "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! Users can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des courriels urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les utilisateurs peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise."
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! Users can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des e-mails urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les utilisateurs peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise."
},
"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/fr.json b/apps/dashboard/l10n/fr.json
index 5527d322f2a..550ba418238 100644
--- a/apps/dashboard/l10n/fr.json
+++ b/apps/dashboard/l10n/fr.json
@@ -1,7 +1,7 @@
{ "translations": {
"Dashboard" : "Tableau de bord",
"Dashboard app" : "App Tableau de bord",
- "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des courriels urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les personnes peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise.",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des e-mails urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les personnes peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise.",
"\"{title} icon\"" : "« Icône {title} »",
"Customize" : "Personnaliser",
"Edit widgets" : "Modifier les widgets",
@@ -21,6 +21,6 @@
"Good evening, {name}" : "Bonsoir {name}",
"Hello" : "Bonjour",
"Hello, {name}" : "Bonjour {name}",
- "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! Users can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des courriels urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les utilisateurs peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise."
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! Users can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des e-mails urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les utilisateurs peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise."
},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 01f750f7727..1aff4d758c7 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -46,7 +46,9 @@ return array(
'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => $baseDir . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
'OCA\\DAV\\CalDAV\\BirthdayService' => $baseDir . '/../lib/CalDAV/BirthdayService.php',
'OCA\\DAV\\CalDAV\\CachedSubscription' => $baseDir . '/../lib/CalDAV/CachedSubscription.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionImpl' => $baseDir . '/../lib/CalDAV/CachedSubscriptionImpl.php',
'OCA\\DAV\\CalDAV\\CachedSubscriptionObject' => $baseDir . '/../lib/CalDAV/CachedSubscriptionObject.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionProvider' => $baseDir . '/../lib/CalDAV/CachedSubscriptionProvider.php',
'OCA\\DAV\\CalDAV\\CalDavBackend' => $baseDir . '/../lib/CalDAV/CalDavBackend.php',
'OCA\\DAV\\CalDAV\\Calendar' => $baseDir . '/../lib/CalDAV/Calendar.php',
'OCA\\DAV\\CalDAV\\CalendarHome' => $baseDir . '/../lib/CalDAV/CalendarHome.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 481b95c432a..9850414b8af 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -61,7 +61,9 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
'OCA\\DAV\\CalDAV\\BirthdayService' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayService.php',
'OCA\\DAV\\CalDAV\\CachedSubscription' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscription.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionImpl' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionImpl.php',
'OCA\\DAV\\CalDAV\\CachedSubscriptionObject' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionObject.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionProvider' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionProvider.php',
'OCA\\DAV\\CalDAV\\CalDavBackend' => __DIR__ . '/..' . '/../lib/CalDAV/CalDavBackend.php',
'OCA\\DAV\\CalDAV\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Calendar.php',
'OCA\\DAV\\CalDAV\\CalendarHome' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarHome.php',
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index deb28797952..5841d9ec241 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -34,6 +34,7 @@ namespace OCA\DAV\AppInfo;
use OCA\DAV\CalDAV\Activity\Backend;
use OCA\DAV\CalDAV\AppCalendar\AppCalendarPlugin;
+use OCA\DAV\CalDAV\CachedSubscriptionProvider;
use OCA\DAV\CalDAV\CalendarManager;
use OCA\DAV\CalDAV\CalendarProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProvider\AudioProvider;
@@ -207,6 +208,7 @@ class Application extends App implements IBootstrap {
$context->registerNotifierService(Notifier::class);
$context->registerCalendarProvider(CalendarProvider::class);
+ $context->registerCalendarProvider(CachedSubscriptionProvider::class);
$context->registerUserMigrator(CalendarMigrator::class);
$context->registerUserMigrator(ContactsMigrator::class);
diff --git a/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php b/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php
index ddf76e27f3a..b6e00baafd6 100644
--- a/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php
+++ b/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php
@@ -68,7 +68,7 @@ class AppCalendarPlugin implements ICalendarProvider {
return array_values(
array_filter($this->manager->getCalendarsForPrincipal($principalUri, $calendarUris), function ($c) {
// We must not provide a wrapper for DAV calendars
- return ! ($c instanceof \OCA\DAV\CalDAV\CalendarImpl);
+ return ! (($c instanceof \OCA\DAV\CalDAV\CalendarImpl) || ($c instanceof \OCA\DAV\CalDAV\CachedSubscriptionImpl));
})
);
}
diff --git a/apps/dav/lib/CalDAV/CachedSubscription.php b/apps/dav/lib/CalDAV/CachedSubscription.php
index 4047f8dad0b..79a57bc8c23 100644
--- a/apps/dav/lib/CalDAV/CachedSubscription.php
+++ b/apps/dav/lib/CalDAV/CachedSubscription.php
@@ -73,6 +73,11 @@ class CachedSubscription extends \Sabre\CalDAV\Calendar {
'principal' => '{DAV:}authenticated',
'protected' => true,
],
+ [
+ 'privilege' => '{DAV:}write-properties',
+ 'principal' => $this->getOwner(),
+ 'protected' => true,
+ ]
];
}
@@ -97,7 +102,6 @@ class CachedSubscription extends \Sabre\CalDAV\Calendar {
'principal' => $this->getOwner() . '/calendar-proxy-read',
'protected' => true,
],
-
];
}
diff --git a/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php b/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
new file mode 100644
index 00000000000..3406707d0d4
--- /dev/null
+++ b/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
@@ -0,0 +1,117 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\DAV\CalDAV;
+
+use OCP\Calendar\ICalendar;
+use OCP\Constants;
+
+class CachedSubscriptionImpl implements ICalendar {
+ private CalDavBackend $backend;
+ private CachedSubscription $calendar;
+ /** @var array<string, mixed> */
+ private array $calendarInfo;
+
+ public function __construct(
+ CachedSubscription $calendar,
+ array $calendarInfo,
+ CalDavBackend $backend
+ ) {
+ $this->calendar = $calendar;
+ $this->calendarInfo = $calendarInfo;
+ $this->backend = $backend;
+ }
+
+ /**
+ * @return string defining the technical unique key
+ * @since 13.0.0
+ */
+ public function getKey(): string {
+ return (string) $this->calendarInfo['id'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getUri(): string {
+ return $this->calendarInfo['uri'];
+ }
+
+ /**
+ * In comparison to getKey() this function returns a human readable (maybe translated) name
+ * @since 13.0.0
+ */
+ public function getDisplayName(): ?string {
+ return $this->calendarInfo['{DAV:}displayname'];
+ }
+
+ /**
+ * Calendar color
+ * @since 13.0.0
+ */
+ public function getDisplayColor(): ?string {
+ return $this->calendarInfo['{http://apple.com/ns/ical/}calendar-color'];
+ }
+
+ /**
+ * @param string $pattern which should match within the $searchProperties
+ * @param array $searchProperties defines the properties within the query pattern should match
+ * @param array $options - optional parameters:
+ * ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]]
+ * @param int|null $limit - limit number of search results
+ * @param int|null $offset - offset for paging of search results
+ * @return array an array of events/journals/todos which are arrays of key-value-pairs
+ * @since 13.0.0
+ */
+ public function search(string $pattern, array $searchProperties = [], array $options = [], $limit = null, $offset = null): array {
+ return $this->backend->search($this->calendarInfo, $pattern, $searchProperties, $options, $limit, $offset);
+ }
+
+ /**
+ * @return int build up using \OCP\Constants
+ * @since 13.0.0
+ */
+ public function getPermissions(): int {
+ $permissions = $this->calendar->getACL();
+ $result = 0;
+ foreach ($permissions as $permission) {
+ switch ($permission['privilege']) {
+ case '{DAV:}read':
+ $result |= Constants::PERMISSION_READ;
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ public function isDeleted(): bool {
+ return false;
+ }
+
+ public function getSource(): string {
+ return $this->calendarInfo['source'];
+ }
+}
diff --git a/apps/dav/lib/CalDAV/CachedSubscriptionProvider.php b/apps/dav/lib/CalDAV/CachedSubscriptionProvider.php
new file mode 100644
index 00000000000..e2508af5592
--- /dev/null
+++ b/apps/dav/lib/CalDAV/CachedSubscriptionProvider.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\DAV\CalDAV;
+
+use OCP\Calendar\ICalendarProvider;
+
+class CachedSubscriptionProvider implements ICalendarProvider {
+
+ public function __construct(
+ private CalDavBackend $calDavBackend
+ ) {
+ }
+
+ public function getCalendars(string $principalUri, array $calendarUris = []): array {
+ $calendarInfos = $this->calDavBackend->getSubscriptionsForUser($principalUri);
+
+ if (count($calendarUris) > 0) {
+ $calendarInfos = array_filter($calendarInfos, fn (array $subscription) => in_array($subscription['uri'], $calendarUris));
+ }
+
+ $calendarInfos = array_values(array_filter($calendarInfos));
+
+ $iCalendars = [];
+ foreach ($calendarInfos as $calendarInfo) {
+ $calendar = new CachedSubscription($this->calDavBackend, $calendarInfo);
+ $iCalendars[] = new CachedSubscriptionImpl(
+ $calendar,
+ $calendarInfo,
+ $this->calDavBackend,
+ );
+ }
+ return $iCalendars;
+ }
+}
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 1424ee4f9be..0aa4426c786 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -1882,12 +1882,18 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$outerQuery = $this->db->getQueryBuilder();
$innerQuery = $this->db->getQueryBuilder();
+ if (isset($calendarInfo['source'])) {
+ $calendarType = self::CALENDAR_TYPE_SUBSCRIPTION;
+ } else {
+ $calendarType = self::CALENDAR_TYPE_CALENDAR;
+ }
+
$innerQuery->selectDistinct('op.objectid')
->from($this->dbObjectPropertiesTable, 'op')
->andWhere($innerQuery->expr()->eq('op.calendarid',
$outerQuery->createNamedParameter($calendarInfo['id'])))
->andWhere($innerQuery->expr()->eq('op.calendartype',
- $outerQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)));
+ $outerQuery->createNamedParameter($calendarType)));
$outerQuery->select('c.id', 'c.calendardata', 'c.componenttype', 'c.uid', 'c.uri')
->from('calendarobjects', 'c')
diff --git a/apps/dav/lib/CalDAV/CalendarHome.php b/apps/dav/lib/CalDAV/CalendarHome.php
index cbf5cebc9e7..31463bcc678 100644
--- a/apps/dav/lib/CalDAV/CalendarHome.php
+++ b/apps/dav/lib/CalDAV/CalendarHome.php
@@ -53,14 +53,16 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
/** @var PluginManager */
private $pluginManager;
- /** @var bool */
- private $returnCachedSubscriptions = false;
-
/** @var LoggerInterface */
private $logger;
private ?array $cachedChildren = null;
- public function __construct(BackendInterface $caldavBackend, $principalInfo, LoggerInterface $logger) {
+ public function __construct(
+ BackendInterface $caldavBackend,
+ array $principalInfo,
+ LoggerInterface $logger,
+ private bool $returnCachedSubscriptions
+ ) {
parent::__construct($caldavBackend, $principalInfo);
$this->l10n = \OC::$server->getL10N('dav');
$this->config = \OC::$server->getConfig();
@@ -219,8 +221,4 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
$principalUri = $this->principalInfo['uri'];
return $this->caldavBackend->calendarSearch($principalUri, $filters, $limit, $offset);
}
-
- public function enableCachedSubscriptionsForThisRequest() {
- $this->returnCachedSubscriptions = true;
- }
}
diff --git a/apps/dav/lib/CalDAV/CalendarRoot.php b/apps/dav/lib/CalDAV/CalendarRoot.php
index 0c701d9cdcf..bece2087e8a 100644
--- a/apps/dav/lib/CalDAV/CalendarRoot.php
+++ b/apps/dav/lib/CalDAV/CalendarRoot.php
@@ -32,6 +32,8 @@ use Sabre\DAVACL\PrincipalBackend;
class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
private LoggerInterface $logger;
+ private array $returnCachedSubscriptions = [];
+
public function __construct(
PrincipalBackend\BackendInterface $principalBackend,
Backend\BackendInterface $caldavBackend,
@@ -43,7 +45,12 @@ class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
}
public function getChildForPrincipal(array $principal) {
- return new CalendarHome($this->caldavBackend, $principal, $this->logger);
+ return new CalendarHome(
+ $this->caldavBackend,
+ $principal,
+ $this->logger,
+ array_key_exists($principal['uri'], $this->returnCachedSubscriptions)
+ );
}
public function getName() {
@@ -56,4 +63,8 @@ class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
return parent::getName();
}
+
+ public function enableReturnCachedSubscriptions(string $principalUri): void {
+ $this->returnCachedSubscriptions['principals/users/' . $principalUri] = true;
+ }
}
diff --git a/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php b/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
index 8d4714d313a..25a68c40eb2 100644
--- a/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
+++ b/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
@@ -26,7 +26,7 @@ declare(strict_types=1);
*/
namespace OCA\DAV\CalDAV\WebcalCaching;
-use OCA\DAV\CalDAV\CalendarHome;
+use OCA\DAV\CalDAV\CalendarRoot;
use OCP\IRequest;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Server;
@@ -71,6 +71,11 @@ class Plugin extends ServerPlugin {
if ($magicHeader === 'On') {
$this->enabled = true;
}
+
+ $isExportRequest = $request->getMethod() === 'GET' && array_key_exists('export', $request->getParams());
+ if ($isExportRequest) {
+ $this->enabled = true;
+ }
}
/**
@@ -85,7 +90,7 @@ class Plugin extends ServerPlugin {
*/
public function initialize(Server $server) {
$this->server = $server;
- $server->on('beforeMethod:*', [$this, 'beforeMethod']);
+ $server->on('beforeMethod:*', [$this, 'beforeMethod'], 15);
}
/**
@@ -107,16 +112,11 @@ class Plugin extends ServerPlugin {
return;
}
- // $calendarHomePath will look like: calendars/username
- $calendarHomePath = $pathParts[0] . '/' . $pathParts[1];
try {
- $calendarHome = $this->server->tree->getNodeForPath($calendarHomePath);
- if (!($calendarHome instanceof CalendarHome)) {
- //how did we end up here?
- return;
+ $calendarRoot = $this->server->tree->getNodeForPath($pathParts[0]);
+ if ($calendarRoot instanceof CalendarRoot) {
+ $calendarRoot->enableReturnCachedSubscriptions($pathParts[1]);
}
-
- $calendarHome->enableCachedSubscriptionsForThisRequest();
} catch (NotFound $ex) {
return;
}
diff --git a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
index 61fac7250bc..8e5000fa9fb 100644
--- a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
@@ -27,6 +27,7 @@
*/
namespace OCA\DAV\Connector\Sabre;
+use OCA\DAV\CalDAV\CachedSubscription;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CardDAV\AddressBook;
use Sabre\CalDAV\Principal\User;
@@ -61,6 +62,7 @@ class DavAclPlugin extends \Sabre\DAVACL\Plugin {
$type = 'Addressbook';
break;
case Calendar::class:
+ case CachedSubscription::class:
$type = 'Calendar';
break;
default:
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
new file mode 100644
index 00000000000..1d612585c49
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
@@ -0,0 +1,96 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\CachedSubscription;
+use OCA\DAV\CalDAV\CachedSubscriptionImpl;
+use OCA\DAV\CalDAV\CalDavBackend;
+use Test\TestCase;
+
+class CachedSubscriptionImplTest extends TestCase {
+ private CachedSubscription $cachedSubscription;
+ private array $cachedSubscriptionInfo;
+ private CachedSubscriptionImpl $cachedSubscriptionImpl;
+ private CalDavBackend $backend;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->cachedSubscription = $this->createMock(CachedSubscription::class);
+ $this->cachedSubscriptionInfo = [
+ 'id' => 'fancy_id_123',
+ '{DAV:}displayname' => 'user readable name 123',
+ '{http://apple.com/ns/ical/}calendar-color' => '#AABBCC',
+ 'uri' => '/this/is/a/uri',
+ 'source' => 'https://test.localhost/calendar1',
+ ];
+ $this->backend = $this->createMock(CalDavBackend::class);
+
+ $this->cachedSubscriptionImpl = new CachedSubscriptionImpl(
+ $this->cachedSubscription,
+ $this->cachedSubscriptionInfo,
+ $this->backend
+ );
+ }
+
+ public function testGetKey(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getKey(), 'fancy_id_123');
+ }
+
+ public function testGetDisplayname(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getDisplayName(), 'user readable name 123');
+ }
+
+ public function testGetDisplayColor(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getDisplayColor(), '#AABBCC');
+ }
+
+ public function testGetSource(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getSource(), 'https://test.localhost/calendar1');
+ }
+
+ public function testSearch(): void {
+ $this->backend->expects($this->once())
+ ->method('search')
+ ->with($this->cachedSubscriptionInfo, 'abc', ['def'], ['ghi'], 42, 1337)
+ ->willReturn(['SEARCHRESULTS']);
+
+ $result = $this->cachedSubscriptionImpl->search('abc', ['def'], ['ghi'], 42, 1337);
+ $this->assertEquals($result, ['SEARCHRESULTS']);
+ }
+
+ public function testGetPermissionRead(): void {
+ $this->cachedSubscription->expects($this->once())
+ ->method('getACL')
+ ->with()
+ ->willReturn([
+ ['privilege' => '{DAV:}read']
+ ]);
+
+ $this->assertEquals(1, $this->cachedSubscriptionImpl->getPermissions());
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
new file mode 100644
index 00000000000..8331d259ce8
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
@@ -0,0 +1,88 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\CachedSubscriptionImpl;
+use OCA\DAV\CalDAV\CachedSubscriptionProvider;
+use OCA\DAV\CalDAV\CalDavBackend;
+use Test\TestCase;
+
+class CachedSubscriptionProviderTest extends TestCase {
+
+ private CalDavBackend $backend;
+ private CachedSubscriptionProvider $provider;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->backend = $this->createMock(CalDavBackend::class);
+ $this->backend
+ ->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('user-principal-123')
+ ->willReturn([
+ [
+ 'id' => 'subscription-1',
+ 'uri' => 'subscription-1',
+ 'principaluris' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-1',
+ // A subscription array has actually more properties.
+ ],
+ [
+ 'id' => 'subscription-2',
+ 'uri' => 'subscription-2',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-2',
+ // A subscription array has actually more properties.
+ ]
+ ]);
+
+ $this->provider = new CachedSubscriptionProvider($this->backend);
+ }
+
+ public function testGetCalendars() {
+ $calendars = $this->provider->getCalendars(
+ 'user-principal-123',
+ []
+ );
+
+ $this->assertCount(2, $calendars);
+ $this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[0]);
+ $this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[1]);
+ }
+
+ public function testGetCalendarsFilterByUri() {
+ $calendars = $this->provider->getCalendars(
+ 'user-principal-123',
+ ['subscription-1']
+ );
+
+ $this->assertCount(1, $calendars);
+ $this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[0]);
+ $this->assertEquals('subscription-1', $calendars[0]->getUri());
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
index 254c3199472..285609496a7 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
@@ -61,6 +61,11 @@ class CachedSubscriptionTest extends \Test\TestCase {
'principal' => '{DAV:}authenticated',
'protected' => true,
],
+ [
+ 'privilege' => '{DAV:}write-properties',
+ 'principal' => 'user1',
+ 'protected' => 'true'
+ ]
], $calendar->getACL());
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
index 50430029c61..1b2feb99df3 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
@@ -26,6 +26,7 @@
namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\AppInfo\PluginManager;
+use OCA\DAV\CalDAV\CachedSubscription;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
@@ -35,6 +36,7 @@ use OCA\DAV\CalDAV\Trashbin\TrashbinHome;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\CalDAV\Schedule\Inbox;
+use Sabre\CalDAV\Subscriptions\Subscription;
use Sabre\DAV\MkCol;
use Test\TestCase;
@@ -68,13 +70,13 @@ class CalendarHomeTest extends TestCase {
$this->calendarHome = new CalendarHome(
$this->backend,
$this->principalInfo,
- $this->logger
+ $this->logger,
+ false
);
// Replace PluginManager with our mock
$reflection = new \ReflectionClass($this->calendarHome);
$reflectionProperty = $reflection->getProperty('pluginManager');
- $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->calendarHome, $this->pluginManager);
}
@@ -249,4 +251,124 @@ class CalendarHomeTest extends TestCase {
$actual = $this->calendarHome->getChild('app-generated--calendar_plugin_2--calendar-uri-from-backend');
$this->assertEquals($externalCalendarMock, $actual);
}
+
+ public function testGetChildrenSubscriptions(): void {
+ $this->backend
+ ->expects(self::once())
+ ->method('getCalendarsForUser')
+ ->with('user-principal-123')
+ ->willReturn([]);
+
+ $this->backend
+ ->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('user-principal-123')
+ ->willReturn([
+ [
+ 'id' => 'subscription-1',
+ 'uri' => 'subscription-1',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-1',
+ // A subscription array has actually more properties.
+ ],
+ [
+ 'id' => 'subscription-2',
+ 'uri' => 'subscription-2',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-2',
+ // A subscription array has actually more properties.
+ ]
+ ]);
+
+ /*
+ * @FIXME: PluginManager should be injected via constructor.
+ */
+
+ $pluginManager = $this->createMock(PluginManager::class);
+ $pluginManager
+ ->expects(self::once())
+ ->method('getCalendarPlugins')
+ ->with()
+ ->willReturn([]);
+
+ $calendarHome = new CalendarHome(
+ $this->backend,
+ $this->principalInfo,
+ $this->logger,
+ false
+ );
+
+ $reflection = new \ReflectionClass($calendarHome);
+ $reflectionProperty = $reflection->getProperty('pluginManager');
+ $reflectionProperty->setValue($calendarHome, $pluginManager);
+
+ $actual = $calendarHome->getChildren();
+
+ $this->assertCount(5, $actual);
+ $this->assertInstanceOf(Inbox::class, $actual[0]);
+ $this->assertInstanceOf(Outbox::class, $actual[1]);
+ $this->assertInstanceOf(TrashbinHome::class, $actual[2]);
+ $this->assertInstanceOf(Subscription::class, $actual[3]);
+ $this->assertInstanceOf(Subscription::class, $actual[4]);
+ }
+
+ public function testGetChildrenCachedSubscriptions(): void {
+ $this->backend
+ ->expects(self::once())
+ ->method('getCalendarsForUser')
+ ->with('user-principal-123')
+ ->willReturn([]);
+
+ $this->backend
+ ->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('user-principal-123')
+ ->willReturn([
+ [
+ 'id' => 'subscription-1',
+ 'uri' => 'subscription-1',
+ 'principaluris' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-1',
+ // A subscription array has actually more properties.
+ ],
+ [
+ 'id' => 'subscription-2',
+ 'uri' => 'subscription-2',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-2',
+ // A subscription array has actually more properties.
+ ]
+ ]);
+
+ /*
+ * @FIXME: PluginManager should be injected via constructor.
+ */
+
+ $pluginManager = $this->createMock(PluginManager::class);
+ $pluginManager
+ ->expects(self::once())
+ ->method('getCalendarPlugins')
+ ->with()
+ ->willReturn([]);
+
+ $calendarHome = new CalendarHome(
+ $this->backend,
+ $this->principalInfo,
+ $this->logger,
+ true
+ );
+
+ $reflection = new \ReflectionClass($calendarHome);
+ $reflectionProperty = $reflection->getProperty('pluginManager');
+ $reflectionProperty->setValue($calendarHome, $pluginManager);
+
+ $actual = $calendarHome->getChildren();
+
+ $this->assertCount(5, $actual);
+ $this->assertInstanceOf(Inbox::class, $actual[0]);
+ $this->assertInstanceOf(Outbox::class, $actual[1]);
+ $this->assertInstanceOf(TrashbinHome::class, $actual[2]);
+ $this->assertInstanceOf(CachedSubscription::class, $actual[3]);
+ $this->assertInstanceOf(CachedSubscription::class, $actual[4]);
+ }
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
index 132526e604f..85f2b1aedaf 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
@@ -39,9 +39,6 @@ use Sabre\VObject\Component\VEvent;
use Sabre\VObject\ITip\Message;
use Sabre\VObject\Reader;
-/**
- * @group DB
- */
class CalendarImplTest extends \Test\TestCase {
/** @var CalendarImpl */
private $calendarImpl;
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
index 24b72117658..10e11d5090f 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
@@ -48,17 +48,64 @@ class PluginTest extends \Test\TestCase {
$this->assertEquals(false, $plugin->isCachingEnabledForThisRequest());
}
- public function testEnabled(): void {
+ public function testEnabledUserAgent(): void {
$request = $this->createMock(IRequest::class);
$request->expects($this->once())
->method('isUserAgent')
->with(Plugin::ENABLE_FOR_CLIENTS)
- ->willReturn(false);
+ ->willReturn(true);
+ $request->expects($this->once())
+ ->method('getHeader')
+ ->with('X-NC-CalDAV-Webcal-Caching')
+ ->willReturn('');
+ $request->expects($this->once())
+ ->method('getMethod')
+ ->willReturn('REPORT');
+ $request->expects($this->never())
+ ->method('getParams');
+
+ $plugin = new Plugin($request);
+ $this->assertEquals(true, $plugin->isCachingEnabledForThisRequest());
+ }
+
+ public function testEnabledWebcalCachingHeader(): void {
+ $request = $this->createMock(IRequest::class);
+ $request->expects($this->once())
+ ->method('isUserAgent')
+ ->with(Plugin::ENABLE_FOR_CLIENTS)
+ ->willReturn(false);
$request->expects($this->once())
->method('getHeader')
->with('X-NC-CalDAV-Webcal-Caching')
->willReturn('On');
+ $request->expects($this->once())
+ ->method('getMethod')
+ ->willReturn('REPORT');
+ $request->expects($this->never())
+ ->method('getParams');
+
+ $plugin = new Plugin($request);
+
+ $this->assertEquals(true, $plugin->isCachingEnabledForThisRequest());
+ }
+
+ public function testEnabledExportRequest(): void {
+ $request = $this->createMock(IRequest::class);
+ $request->expects($this->once())
+ ->method('isUserAgent')
+ ->with(Plugin::ENABLE_FOR_CLIENTS)
+ ->willReturn(false);
+ $request->expects($this->once())
+ ->method('getHeader')
+ ->with('X-NC-CalDAV-Webcal-Caching')
+ ->willReturn('');
+ $request->expects($this->once())
+ ->method('getMethod')
+ ->willReturn('GET');
+ $request->expects($this->once())
+ ->method('getParams')
+ ->willReturn(['export' => '']);
$plugin = new Plugin($request);
diff --git a/apps/files_sharing/l10n/fr.js b/apps/files_sharing/l10n/fr.js
index cf836b68968..575dfc05135 100644
--- a/apps/files_sharing/l10n/fr.js
+++ b/apps/files_sharing/l10n/fr.js
@@ -208,7 +208,7 @@ OC.L10N.register(
"Share" : "Partager",
"Delete share" : "Supprimer le partage",
"Share with {userName}" : "Partager avec {userName}",
- "Share with email {email}" : "Partager avec l’adresse électronique {email}",
+ "Share with email {email}" : "Partager avec l'e-mail {email}",
"Share with group" : "Partager avec le groupe",
"Share in conversation" : "Partager dans la conversation",
"Share with {user} on remote server {server}" : "Partager avec {user} sur le serveur distant {server}",
diff --git a/apps/files_sharing/l10n/fr.json b/apps/files_sharing/l10n/fr.json
index 3f996cea698..8489aeb7b27 100644
--- a/apps/files_sharing/l10n/fr.json
+++ b/apps/files_sharing/l10n/fr.json
@@ -206,7 +206,7 @@
"Share" : "Partager",
"Delete share" : "Supprimer le partage",
"Share with {userName}" : "Partager avec {userName}",
- "Share with email {email}" : "Partager avec l’adresse électronique {email}",
+ "Share with email {email}" : "Partager avec l'e-mail {email}",
"Share with group" : "Partager avec le groupe",
"Share in conversation" : "Partager dans la conversation",
"Share with {user} on remote server {server}" : "Partager avec {user} sur le serveur distant {server}",
diff --git a/apps/provisioning_api/l10n/fr.js b/apps/provisioning_api/l10n/fr.js
index cc53eb9ce93..5808ee02a21 100644
--- a/apps/provisioning_api/l10n/fr.js
+++ b/apps/provisioning_api/l10n/fr.js
@@ -9,7 +9,7 @@ OC.L10N.register(
"Sub-admin group does not exist" : "Le groupe des sous-administrateurs n'existe pas",
"Cannot create sub-admins for admin group" : "Impossible de créer des sous-administrateurs pour le groupe des administrateurs",
"Invalid password value" : "Valeur de mot de passe invalide",
- "To send a password link to the user an email address is required." : "Pour envoyer un mot de passe par lien à l’utilisateur, une adresse électronique est requise.",
+ "To send a password link to the user an email address is required." : "Pour envoyer un mot de passe par lien à l’utilisateur, une adresse e-mail est requise.",
"Required email address was not provided" : "L'adresse e-mail exigée n'a pas été fournie",
"Invalid quota value: %1$s" : "Valeur de quota invalide : %1$s",
"Invalid quota value. %1$s is exceeding the maximum quota" : "Valeur de quota invalide : %1$s dépasse le quota maximum",
@@ -21,9 +21,9 @@ OC.L10N.register(
"User does not exist" : "L'utilisateur n'existe pas",
"Group does not exist" : "Le groupe n'existe pas",
"User is not a sub-admin of this group" : "L'utilisateur n'est pas un sous-administrateur de ce groupe",
- "Email address not available" : "Adresse électronique indisponible ",
- "Sending email failed" : "L'envoi du courriel a échoué",
- "Email confirmation" : "Confirmation de l’adresse électronique",
+ "Email address not available" : "Adresse e-mail indisponible ",
+ "Sending email failed" : "L'envoi de l'e-mail a échoué",
+ "Email confirmation" : "Confirmation par e-mail",
"To enable the email address %s please click the button below." : "Pour activer l'adresse e-mail %s, veuillez cliquer sur le bouton ci-dessous.",
"Confirm" : "Confirmer",
"Email was already removed from account and cannot be confirmed anymore." : "L'adresse e-mail a déjà été supprimée du compte et ne peut donc plus être confirmée.",
diff --git a/apps/provisioning_api/l10n/fr.json b/apps/provisioning_api/l10n/fr.json
index 23b6da85b6a..95cb6f0b689 100644
--- a/apps/provisioning_api/l10n/fr.json
+++ b/apps/provisioning_api/l10n/fr.json
@@ -7,7 +7,7 @@
"Sub-admin group does not exist" : "Le groupe des sous-administrateurs n'existe pas",
"Cannot create sub-admins for admin group" : "Impossible de créer des sous-administrateurs pour le groupe des administrateurs",
"Invalid password value" : "Valeur de mot de passe invalide",
- "To send a password link to the user an email address is required." : "Pour envoyer un mot de passe par lien à l’utilisateur, une adresse électronique est requise.",
+ "To send a password link to the user an email address is required." : "Pour envoyer un mot de passe par lien à l’utilisateur, une adresse e-mail est requise.",
"Required email address was not provided" : "L'adresse e-mail exigée n'a pas été fournie",
"Invalid quota value: %1$s" : "Valeur de quota invalide : %1$s",
"Invalid quota value. %1$s is exceeding the maximum quota" : "Valeur de quota invalide : %1$s dépasse le quota maximum",
@@ -19,9 +19,9 @@
"User does not exist" : "L'utilisateur n'existe pas",
"Group does not exist" : "Le groupe n'existe pas",
"User is not a sub-admin of this group" : "L'utilisateur n'est pas un sous-administrateur de ce groupe",
- "Email address not available" : "Adresse électronique indisponible ",
- "Sending email failed" : "L'envoi du courriel a échoué",
- "Email confirmation" : "Confirmation de l’adresse électronique",
+ "Email address not available" : "Adresse e-mail indisponible ",
+ "Sending email failed" : "L'envoi de l'e-mail a échoué",
+ "Email confirmation" : "Confirmation par e-mail",
"To enable the email address %s please click the button below." : "Pour activer l'adresse e-mail %s, veuillez cliquer sur le bouton ci-dessous.",
"Confirm" : "Confirmer",
"Email was already removed from account and cannot be confirmed anymore." : "L'adresse e-mail a déjà été supprimée du compte et ne peut donc plus être confirmée.",
diff --git a/apps/settings/l10n/fr.js b/apps/settings/l10n/fr.js
index f3b830ee4c8..f1b73a73b60 100644
--- a/apps/settings/l10n/fr.js
+++ b/apps/settings/l10n/fr.js
@@ -70,8 +70,8 @@ OC.L10N.register(
"Well done, %s!" : "Bien joué, %s !",
"If you received this email, the email configuration seems to be correct." : "Si vous avez reçu cet e-mail, la configuration de l'adresse e-mail semble être correcte.",
"Email could not be sent. Check your mail server log" : "L'e-mail n'a pu être envoyé. Vérifiez le journal du serveur de messagerie",
- "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Une erreur est survenue lors de l’envoi du courriel. Veuillez vérifier vos paramètres. (Erreur : %s)",
- "You need to set your account email before being able to send test emails. Go to %s for that." : "Vous devez définir votre adresse électronique de compte avant de tester l'envoi de courriel. Allez à %s pour cela.",
+ "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Une erreur est survenue lors de l’envoi de l'e-mail. Veuillez vérifier vos paramètres. (Erreur : %s)",
+ "You need to set your account email before being able to send test emails. Go to %s for that." : "Vous devez définir l'e-mail de votre compte avant de pouvoir envoyer des e-mails de test. Allez à %s pour cela.",
"Invalid account" : "Compte invalide",
"Invalid mail address" : "Adresse e-mail non valide",
"Settings saved" : "Paramètres sauvegardés",
@@ -165,7 +165,7 @@ OC.L10N.register(
"Your installation has no default phone region set. This is required to validate phone numbers in the profile settings without a country code. To allow numbers without a country code, please add \"default_phone_region\" with the respective ISO 3166-1 code of the region to your config file." : "Votre installation n’a pas de préfixe de région par défaut. C’est nécessaire pour valider les numéros de téléphone dans les paramètres du profil sans code pays. Pour autoriser les numéros sans code pays, veuillez ajouter « default_phone_region » avec le code ISO 3166-1 respectif de la région dans votre fichier de configuration.",
"Email test" : "Test de l’e-mail",
"Email test was successfully sent" : "L'e-mail de test a été envoyé avec succès",
- "You have not set or verified your email server configuration, yet. Please head over to the \"Basic settings\" in order to set them. Afterwards, use the \"Send email\" button below the form to verify your settings." : "Vous n’avez pas encore paramétré ou vérifié la configuration de votre serveur mail. Merci de le faire sur la page « Paramètres de base ». Ensuite, utilisez le bouton « Envoyer un courriel » sous le formulaire pour vérifier vos paramètres.",
+ "You have not set or verified your email server configuration, yet. Please head over to the \"Basic settings\" in order to set them. Afterwards, use the \"Send email\" button below the form to verify your settings." : "Vous n’avez pas encore paramétré ou vérifié la configuration de votre serveur mail. Merci de le faire sur la page « Paramètres de base ». Ensuite, utilisez le bouton « Envoyer un e-mail » sous le formulaire pour vérifier vos paramètres.",
"File locking" : "Verrouillage des fichiers",
"Transactional file locking is disabled, this might lead to issues with race conditions. Enable \"filelocking.enabled\" in config.php to avoid these problems." : "Le verrouillage transactionnel de fichiers est désactivé, cela peut causer des conflits en cas d'accès concurrent. Configurez « filelocking.enabled » dans config.php pour éviter ces problèmes.",
"The database is used for transactional file locking. To enhance performance, please configure memcache, if available." : "La base de données est actuellement utilisée pour les verrous. Afin d'améliorer les performances, veuillez si possible configurer un cache mémoire.",
@@ -339,7 +339,7 @@ OC.L10N.register(
"Enforce expiration date for remote shares" : "Imposer une date d’expiration pour les partages distants",
"Default expiration time of remote shares in days" : "Délai d’expiration par défaut en jours des partages distants",
"Expire remote shares after x days" : "Expiration des partages distants après x jours",
- "Set default expiration date for shares via link or mail" : "Définir par défaut une date d’expiration pour les partages par lien ou par courriel",
+ "Set default expiration date for shares via link or mail" : "Définir par défaut une date d’expiration pour les partages par lien ou par e-mail",
"Default expiration time of shares in days" : "Délai d’expiration des partages par défaut en jours",
"Privacy settings for sharing" : "Paramètres de confidentialité pour le partage",
"Allow username autocompletion in share dialog and allow access to the system address book" : "Autoriser l'autocomplétion du nom d'utilisateur dans le dialogue de partage et permettre l'accès au carnet d'adresses du système",
@@ -522,7 +522,7 @@ OC.L10N.register(
"Your full name" : "Votre nom complet",
"Primary email for password reset and notifications" : "Adresse e-mail principale pour la réinitialisation du mot de passe et les notifications",
"Email options" : "Options de messagerie",
- "Options for additional email address {index}" : "Options pour une adresse électronique supplémentaire {index}",
+ "Options for additional email address {index}" : "Options pour une adresse e-mail supplémentaire {index}",
"Remove primary email" : "Supprimer l'adresse e-mail principale",
"Delete email" : "Supprimer l'adresse e-mail",
"This address is not confirmed" : "Cette adresse n'est pas confirmée",
@@ -648,8 +648,8 @@ OC.L10N.register(
"Group list sorting" : "Tri de la liste des groupes",
"By member count" : "Par nombre de membres",
"By name" : "Par nom",
- "Send email" : "Envoyer un courriel",
- "Send welcome email to new accounts" : "Envoyer un courriel de bienvenue aux nouveaux comptes",
+ "Send email" : "Envoyer un e-mail",
+ "Send welcome email to new accounts" : "Envoyer un e-mail de bienvenue aux nouveaux comptes",
"Defaults" : "Par défaut",
"Default quota" : "Quota par défaut",
"Select default quota" : "Sélectionner le quota par défaut",
@@ -741,7 +741,7 @@ OC.L10N.register(
"None/STARTTLS" : "Aucun/STARTTLS",
"SSL" : "SSL",
"Open documentation" : "Ouvrir la documentation",
- "It is important to set up this server to be able to send emails, like for password reset and notifications." : "Il est important d’indiquer un serveur afin de pouvoir envoyer des courriels en cas de perte de mot de passe et pour d’autres notifications.",
+ "It is important to set up this server to be able to send emails, like for password reset and notifications." : "Il est important d’indiquer un serveur afin de pouvoir envoyer des e-mails en cas de perte de mot de passe et pour d’autres notifications.",
"Send mode" : "Mode d’envoi",
"Encryption" : "Chiffrement",
"Sendmail mode" : "Mode Sendmail",
@@ -853,7 +853,7 @@ OC.L10N.register(
"Default quota:" : "Quota par défaut :",
"Show Languages" : "Afficher la langue",
"Show user backend" : "Afficher l'origine du compte",
- "Send email to new user" : "Envoyer un courriel aux nouveaux utilisateurs",
+ "Send email to new user" : "Envoyer un e-mail aux nouveaux utilisateurs",
"Not saved" : "Non sauvegardé",
"Twitter" : "Twitter",
"Not available as federation has been disabled for your account, contact your system administrator if you have any questions" : "Non disponible car la fédération a été désactivée pour votre compte, contactez votre administrateur système si vous avez des questions.",
@@ -879,7 +879,7 @@ OC.L10N.register(
"Loading user …" : "Chargement de l'utilisateur...",
"Failed to update user manager" : "Impossible de mettre à jour le gestionnaire d'utilisateurs",
"User management settings" : "Paramètres de la gestion utilisateurs",
- "Send welcome email to new users" : "Envoyer un courriel de bienvenue aux nouveaux utilisateurs",
+ "Send welcome email to new users" : "Envoyer un e-mail de bienvenue aux nouveaux utilisateurs",
"User management" : "Gestion des utilisateurs",
"Creating group …" : "Création du groupe...",
"User group: {group}" : "Groupe d'utilisateurs : {group}",
diff --git a/apps/settings/l10n/fr.json b/apps/settings/l10n/fr.json
index 4d0114d4ded..b37d3676239 100644
--- a/apps/settings/l10n/fr.json
+++ b/apps/settings/l10n/fr.json
@@ -68,8 +68,8 @@
"Well done, %s!" : "Bien joué, %s !",
"If you received this email, the email configuration seems to be correct." : "Si vous avez reçu cet e-mail, la configuration de l'adresse e-mail semble être correcte.",
"Email could not be sent. Check your mail server log" : "L'e-mail n'a pu être envoyé. Vérifiez le journal du serveur de messagerie",
- "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Une erreur est survenue lors de l’envoi du courriel. Veuillez vérifier vos paramètres. (Erreur : %s)",
- "You need to set your account email before being able to send test emails. Go to %s for that." : "Vous devez définir votre adresse électronique de compte avant de tester l'envoi de courriel. Allez à %s pour cela.",
+ "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Une erreur est survenue lors de l’envoi de l'e-mail. Veuillez vérifier vos paramètres. (Erreur : %s)",
+ "You need to set your account email before being able to send test emails. Go to %s for that." : "Vous devez définir l'e-mail de votre compte avant de pouvoir envoyer des e-mails de test. Allez à %s pour cela.",
"Invalid account" : "Compte invalide",
"Invalid mail address" : "Adresse e-mail non valide",
"Settings saved" : "Paramètres sauvegardés",
@@ -163,7 +163,7 @@
"Your installation has no default phone region set. This is required to validate phone numbers in the profile settings without a country code. To allow numbers without a country code, please add \"default_phone_region\" with the respective ISO 3166-1 code of the region to your config file." : "Votre installation n’a pas de préfixe de région par défaut. C’est nécessaire pour valider les numéros de téléphone dans les paramètres du profil sans code pays. Pour autoriser les numéros sans code pays, veuillez ajouter « default_phone_region » avec le code ISO 3166-1 respectif de la région dans votre fichier de configuration.",
"Email test" : "Test de l’e-mail",
"Email test was successfully sent" : "L'e-mail de test a été envoyé avec succès",
- "You have not set or verified your email server configuration, yet. Please head over to the \"Basic settings\" in order to set them. Afterwards, use the \"Send email\" button below the form to verify your settings." : "Vous n’avez pas encore paramétré ou vérifié la configuration de votre serveur mail. Merci de le faire sur la page « Paramètres de base ». Ensuite, utilisez le bouton « Envoyer un courriel » sous le formulaire pour vérifier vos paramètres.",
+ "You have not set or verified your email server configuration, yet. Please head over to the \"Basic settings\" in order to set them. Afterwards, use the \"Send email\" button below the form to verify your settings." : "Vous n’avez pas encore paramétré ou vérifié la configuration de votre serveur mail. Merci de le faire sur la page « Paramètres de base ». Ensuite, utilisez le bouton « Envoyer un e-mail » sous le formulaire pour vérifier vos paramètres.",
"File locking" : "Verrouillage des fichiers",
"Transactional file locking is disabled, this might lead to issues with race conditions. Enable \"filelocking.enabled\" in config.php to avoid these problems." : "Le verrouillage transactionnel de fichiers est désactivé, cela peut causer des conflits en cas d'accès concurrent. Configurez « filelocking.enabled » dans config.php pour éviter ces problèmes.",
"The database is used for transactional file locking. To enhance performance, please configure memcache, if available." : "La base de données est actuellement utilisée pour les verrous. Afin d'améliorer les performances, veuillez si possible configurer un cache mémoire.",
@@ -337,7 +337,7 @@
"Enforce expiration date for remote shares" : "Imposer une date d’expiration pour les partages distants",
"Default expiration time of remote shares in days" : "Délai d’expiration par défaut en jours des partages distants",
"Expire remote shares after x days" : "Expiration des partages distants après x jours",
- "Set default expiration date for shares via link or mail" : "Définir par défaut une date d’expiration pour les partages par lien ou par courriel",
+ "Set default expiration date for shares via link or mail" : "Définir par défaut une date d’expiration pour les partages par lien ou par e-mail",
"Default expiration time of shares in days" : "Délai d’expiration des partages par défaut en jours",
"Privacy settings for sharing" : "Paramètres de confidentialité pour le partage",
"Allow username autocompletion in share dialog and allow access to the system address book" : "Autoriser l'autocomplétion du nom d'utilisateur dans le dialogue de partage et permettre l'accès au carnet d'adresses du système",
@@ -520,7 +520,7 @@
"Your full name" : "Votre nom complet",
"Primary email for password reset and notifications" : "Adresse e-mail principale pour la réinitialisation du mot de passe et les notifications",
"Email options" : "Options de messagerie",
- "Options for additional email address {index}" : "Options pour une adresse électronique supplémentaire {index}",
+ "Options for additional email address {index}" : "Options pour une adresse e-mail supplémentaire {index}",
"Remove primary email" : "Supprimer l'adresse e-mail principale",
"Delete email" : "Supprimer l'adresse e-mail",
"This address is not confirmed" : "Cette adresse n'est pas confirmée",
@@ -646,8 +646,8 @@
"Group list sorting" : "Tri de la liste des groupes",
"By member count" : "Par nombre de membres",
"By name" : "Par nom",
- "Send email" : "Envoyer un courriel",
- "Send welcome email to new accounts" : "Envoyer un courriel de bienvenue aux nouveaux comptes",
+ "Send email" : "Envoyer un e-mail",
+ "Send welcome email to new accounts" : "Envoyer un e-mail de bienvenue aux nouveaux comptes",
"Defaults" : "Par défaut",
"Default quota" : "Quota par défaut",
"Select default quota" : "Sélectionner le quota par défaut",
@@ -739,7 +739,7 @@
"None/STARTTLS" : "Aucun/STARTTLS",
"SSL" : "SSL",
"Open documentation" : "Ouvrir la documentation",
- "It is important to set up this server to be able to send emails, like for password reset and notifications." : "Il est important d’indiquer un serveur afin de pouvoir envoyer des courriels en cas de perte de mot de passe et pour d’autres notifications.",
+ "It is important to set up this server to be able to send emails, like for password reset and notifications." : "Il est important d’indiquer un serveur afin de pouvoir envoyer des e-mails en cas de perte de mot de passe et pour d’autres notifications.",
"Send mode" : "Mode d’envoi",
"Encryption" : "Chiffrement",
"Sendmail mode" : "Mode Sendmail",
@@ -851,7 +851,7 @@
"Default quota:" : "Quota par défaut :",
"Show Languages" : "Afficher la langue",
"Show user backend" : "Afficher l'origine du compte",
- "Send email to new user" : "Envoyer un courriel aux nouveaux utilisateurs",
+ "Send email to new user" : "Envoyer un e-mail aux nouveaux utilisateurs",
"Not saved" : "Non sauvegardé",
"Twitter" : "Twitter",
"Not available as federation has been disabled for your account, contact your system administrator if you have any questions" : "Non disponible car la fédération a été désactivée pour votre compte, contactez votre administrateur système si vous avez des questions.",
@@ -877,7 +877,7 @@
"Loading user …" : "Chargement de l'utilisateur...",
"Failed to update user manager" : "Impossible de mettre à jour le gestionnaire d'utilisateurs",
"User management settings" : "Paramètres de la gestion utilisateurs",
- "Send welcome email to new users" : "Envoyer un courriel de bienvenue aux nouveaux utilisateurs",
+ "Send welcome email to new users" : "Envoyer un e-mail de bienvenue aux nouveaux utilisateurs",
"User management" : "Gestion des utilisateurs",
"Creating group …" : "Création du groupe...",
"User group: {group}" : "Groupe d'utilisateurs : {group}",
diff --git a/apps/sharebymail/l10n/fr.js b/apps/sharebymail/l10n/fr.js
index 330ba5f3447..8c2c0c9d814 100644
--- a/apps/sharebymail/l10n/fr.js
+++ b/apps/sharebymail/l10n/fr.js
@@ -15,7 +15,7 @@ OC.L10N.register(
"Password to access {file} was sent to you" : "Le mot de passe pour accèder à {file} vous a été envoyé",
"Share by mail" : "Partage par e-mail",
"Sharing %1$s failed, because this item is already shared with the account %2$s" : "Impossible de partager %1$s car il est déjà partagé avec le compte %2$s",
- "We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Nous ne pouvons pas vous envoyer le mot de passe généré automatiquement. Merci de définir une adresse électronique valide dans vos paramètres personnels et essayez à nouveau.",
+ "We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Nous ne pouvons pas vous envoyer le mot de passe généré automatiquement. Merci de définir une adresse e-mail valide dans vos paramètres personnels et essayez à nouveau.",
"Failed to send share by email. Got an invalid email address" : "Échec lors de l'envoi du partage par e-mail. L'adresse e-mail est invalide",
"Failed to send share by email" : "Échec lors de l'envoi du partage par e-mail",
"%1$s shared »%2$s« with you" : "%1$s a partagé « %2$s » avec vous",
@@ -38,7 +38,7 @@ OC.L10N.register(
"You can choose a different password at any time in the share dialog." : "Vous pouvez choisir un mot de passe différent à n'importe quel moment dans la boîte de dialogue de partage.",
"Could not find share" : "Impossible de trouver le partage",
"Share provider which allows you to share files by mail" : "Fournisseur de partage qui vous permet de partager des fichiers par courrier électronique.",
- "Allows people to share a personalized link to a file or folder by putting in an email address." : "Autoriser les personnes à partager un lien personnalisé vers un fichier ou un dossier en renseignant une adresse électronique.",
+ "Allows people to share a personalized link to a file or folder by putting in an email address." : "Autoriser les personnes à partager un lien personnalisé vers un fichier ou un dossier en renseignant une adresse e-mail.",
"Send password by mail" : "Envoyer le mot de passe par e-mail",
"Reply to initiator" : "Répondre à l'initiateur",
"Unable to update share by mail config" : "Impossible de mettre à jour la configuration du partage par e-mail",
diff --git a/apps/sharebymail/l10n/fr.json b/apps/sharebymail/l10n/fr.json
index d68e2fb70cf..3f8e69ae061 100644
--- a/apps/sharebymail/l10n/fr.json
+++ b/apps/sharebymail/l10n/fr.json
@@ -13,7 +13,7 @@
"Password to access {file} was sent to you" : "Le mot de passe pour accèder à {file} vous a été envoyé",
"Share by mail" : "Partage par e-mail",
"Sharing %1$s failed, because this item is already shared with the account %2$s" : "Impossible de partager %1$s car il est déjà partagé avec le compte %2$s",
- "We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Nous ne pouvons pas vous envoyer le mot de passe généré automatiquement. Merci de définir une adresse électronique valide dans vos paramètres personnels et essayez à nouveau.",
+ "We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Nous ne pouvons pas vous envoyer le mot de passe généré automatiquement. Merci de définir une adresse e-mail valide dans vos paramètres personnels et essayez à nouveau.",
"Failed to send share by email. Got an invalid email address" : "Échec lors de l'envoi du partage par e-mail. L'adresse e-mail est invalide",
"Failed to send share by email" : "Échec lors de l'envoi du partage par e-mail",
"%1$s shared »%2$s« with you" : "%1$s a partagé « %2$s » avec vous",
@@ -36,7 +36,7 @@
"You can choose a different password at any time in the share dialog." : "Vous pouvez choisir un mot de passe différent à n'importe quel moment dans la boîte de dialogue de partage.",
"Could not find share" : "Impossible de trouver le partage",
"Share provider which allows you to share files by mail" : "Fournisseur de partage qui vous permet de partager des fichiers par courrier électronique.",
- "Allows people to share a personalized link to a file or folder by putting in an email address." : "Autoriser les personnes à partager un lien personnalisé vers un fichier ou un dossier en renseignant une adresse électronique.",
+ "Allows people to share a personalized link to a file or folder by putting in an email address." : "Autoriser les personnes à partager un lien personnalisé vers un fichier ou un dossier en renseignant une adresse e-mail.",
"Send password by mail" : "Envoyer le mot de passe par e-mail",
"Reply to initiator" : "Répondre à l'initiateur",
"Unable to update share by mail config" : "Impossible de mettre à jour la configuration du partage par e-mail",
diff --git a/apps/theming/l10n/fr.js b/apps/theming/l10n/fr.js
index 2e117f5a726..9b6688bc71a 100644
--- a/apps/theming/l10n/fr.js
+++ b/apps/theming/l10n/fr.js
@@ -75,7 +75,7 @@ OC.L10N.register(
"Appearance and accessibility settings" : "Paramètres d’apparence et d’accessibilité",
"Background and color" : "Image d’arrière-plan et couleur",
"Customization has been disabled by your administrator" : "La personnalisation a été désactivée par votre administrateur",
- "The background can be set to an image from the default set, a custom uploaded image, or a plain color. The primary color will automatically be adapted based on this and used for elements like folder icons, primary buttons and highlights." : "L’arrière-plan peut être défini sur une image par défaut, une image personnalisée téléchargée ou une couleur unie. La couleur primaire sera automatiquement adaptée en fonction de celle-ci et utilisée pour des éléments tels que les icônes de dossier, les boutons primaires et les mises en évidence.",
+ "The background can be set to an image from the default set, a custom uploaded image, or a plain color. The primary color will automatically be adapted based on this and used for elements like folder icons, primary buttons and highlights." : "L’arrière-plan peut être défini avec une image provenant de la collection d'images par défaut, une image personnalisée téléversée ou une couleur unie. La couleur primaire sera automatiquement adaptée en fonction de cela et utilisée pour des éléments tels que les icônes de dossier, les boutons primaires et les mises en évidence.",
"Keyboard shortcuts" : "Raccourcis clavier",
"In some cases keyboard shortcuts can interfere with accessibility tools. In order to allow focusing on your tool correctly you can disable all keyboard shortcuts here. This will also disable all available shortcuts in apps." : "Dans certains cas, les raccourcis clavier peuvent interférer avec les outils d'accessibilité. Afin de vous permettre de vous concentrer correctement sur votre outil, vous pouvez désactiver tous les raccourcis clavier ici. Cela désactivera également tous les raccourcis disponibles dans les applications.",
"Disable all keyboard shortcuts" : "Désactiver tous les raccourcis clavier",
diff --git a/apps/theming/l10n/fr.json b/apps/theming/l10n/fr.json
index 66a1e35440e..8fe0f2928e3 100644
--- a/apps/theming/l10n/fr.json
+++ b/apps/theming/l10n/fr.json
@@ -73,7 +73,7 @@
"Appearance and accessibility settings" : "Paramètres d’apparence et d’accessibilité",
"Background and color" : "Image d’arrière-plan et couleur",
"Customization has been disabled by your administrator" : "La personnalisation a été désactivée par votre administrateur",
- "The background can be set to an image from the default set, a custom uploaded image, or a plain color. The primary color will automatically be adapted based on this and used for elements like folder icons, primary buttons and highlights." : "L’arrière-plan peut être défini sur une image par défaut, une image personnalisée téléchargée ou une couleur unie. La couleur primaire sera automatiquement adaptée en fonction de celle-ci et utilisée pour des éléments tels que les icônes de dossier, les boutons primaires et les mises en évidence.",
+ "The background can be set to an image from the default set, a custom uploaded image, or a plain color. The primary color will automatically be adapted based on this and used for elements like folder icons, primary buttons and highlights." : "L’arrière-plan peut être défini avec une image provenant de la collection d'images par défaut, une image personnalisée téléversée ou une couleur unie. La couleur primaire sera automatiquement adaptée en fonction de cela et utilisée pour des éléments tels que les icônes de dossier, les boutons primaires et les mises en évidence.",
"Keyboard shortcuts" : "Raccourcis clavier",
"In some cases keyboard shortcuts can interfere with accessibility tools. In order to allow focusing on your tool correctly you can disable all keyboard shortcuts here. This will also disable all available shortcuts in apps." : "Dans certains cas, les raccourcis clavier peuvent interférer avec les outils d'accessibilité. Afin de vous permettre de vous concentrer correctement sur votre outil, vous pouvez désactiver tous les raccourcis clavier ici. Cela désactivera également tous les raccourcis disponibles dans les applications.",
"Disable all keyboard shortcuts" : "Désactiver tous les raccourcis clavier",
diff --git a/apps/user_ldap/l10n/fr.js b/apps/user_ldap/l10n/fr.js
index a44db93fd9e..a86c0ab858c 100644
--- a/apps/user_ldap/l10n/fr.js
+++ b/apps/user_ldap/l10n/fr.js
@@ -94,7 +94,7 @@ OC.L10N.register(
"When logging in, %s will find the user based on the following attributes:" : "À la connexion, %s cherchera l'utilisateur sur la base des attributs suivant :",
"LDAP/AD Username:" : "Nom d’utilisateur LDAP/AD :",
"Allows login against the LDAP/AD username, which is either \"uid\" or \"sAMAccountName\" and will be detected." : "Autorise l'authentification à partir du nom d'utilisateur LDAP/AD.Celui-ci sera détecté et pourra être soit \"uid\", soit \"sAMAccountName\".",
- "LDAP/AD Email Address:" : "Adresse électronique LDAP/AD :",
+ "LDAP/AD Email Address:" : "Adresse e-mail LDAP/AD :",
"Allows login against an email attribute. \"mail\" and \"mailPrimaryAddress\" allowed." : "Autorise l'authentification par adresse e-mail. \"mail\" et \"mailPrimaryAddress\" sont autorisés.",
"Other Attributes:" : "Autres attributs :",
"Defines the filter to apply, when login is attempted. \"%%uid\" replaces the username in the login action. Example: \"uid=%%uid\"" : "Définit le filtre à appliquer lors de la tentative de connexion. \"%%uid\" remplace le nom d'utilisateur lors de l'authentification. Exemple: \"uid=%%uid\"",
diff --git a/apps/user_ldap/l10n/fr.json b/apps/user_ldap/l10n/fr.json
index c4778c312c1..2993d746061 100644
--- a/apps/user_ldap/l10n/fr.json
+++ b/apps/user_ldap/l10n/fr.json
@@ -92,7 +92,7 @@
"When logging in, %s will find the user based on the following attributes:" : "À la connexion, %s cherchera l'utilisateur sur la base des attributs suivant :",
"LDAP/AD Username:" : "Nom d’utilisateur LDAP/AD :",
"Allows login against the LDAP/AD username, which is either \"uid\" or \"sAMAccountName\" and will be detected." : "Autorise l'authentification à partir du nom d'utilisateur LDAP/AD.Celui-ci sera détecté et pourra être soit \"uid\", soit \"sAMAccountName\".",
- "LDAP/AD Email Address:" : "Adresse électronique LDAP/AD :",
+ "LDAP/AD Email Address:" : "Adresse e-mail LDAP/AD :",
"Allows login against an email attribute. \"mail\" and \"mailPrimaryAddress\" allowed." : "Autorise l'authentification par adresse e-mail. \"mail\" et \"mailPrimaryAddress\" sont autorisés.",
"Other Attributes:" : "Autres attributs :",
"Defines the filter to apply, when login is attempted. \"%%uid\" replaces the username in the login action. Example: \"uid=%%uid\"" : "Définit le filtre à appliquer lors de la tentative de connexion. \"%%uid\" remplace le nom d'utilisateur lors de l'authentification. Exemple: \"uid=%%uid\"",